From b4ed16ad9cd52905a94ea18b70148724998742ab Mon Sep 17 00:00:00 2001 From: Kyle Daruwalla Date: Tue, 3 Dec 2019 22:48:48 -0600 Subject: [PATCH 1/9] Added outdims for some basic layers --- src/layers/basic.jl | 35 +++++++++++++++++++++++++++++++ src/layers/conv.jl | 51 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/src/layers/basic.jl b/src/layers/basic.jl index 2a465208..f2e7645d 100644 --- a/src/layers/basic.jl +++ b/src/layers/basic.jl @@ -39,6 +39,17 @@ function Base.show(io::IO, c::Chain) print(io, ")") end +""" + outdims(c::Chain, isize::Tuple) + +Calculate the output dimensions given the input dimensions, `isize`. + +```julia +m = Chain(Conv((3, 3), 3 => 16), Conv((3, 3), 16 => 32)) +outdims(m, (10, 10)) == (6, 6) +``` +""" +outdims(c::Chain, isize::Tuple) = foldl(∘, map(l -> (x -> outdims(l, x)), c.layers)) # This is a temporary and naive implementation # it might be replaced in the future for better performance @@ -116,6 +127,19 @@ end (a::Dense{<:Any,W})(x::AbstractArray{<:AbstractFloat}) where {T <: Union{Float32,Float64}, W <: AbstractArray{T}} = a(T.(x)) +""" + outdims(l::Dense, isize) + +Calculate the output dimensions given the input dimensions, `isize`. + +```julia +m = Dense(10, 5) +outdims(m, (5, 2)) == (5,) +outdims(m, (10,)) == (5,) +``` +""" +outdims(l::Dense, isize) = (size(l.W)[2],) + """ Diagonal(in::Integer) @@ -145,6 +169,17 @@ function Base.show(io::IO, l::Diagonal) print(io, "Diagonal(", length(l.α), ")") end +""" + outdims(l::Diagonal, isize) + +Calculate the output dimensions given the input dimensions, `isize`. + +```julia +m = Diagonal(10) +outdims(m, (10,)) == (10,) +``` +""" +outdims(l::Diagonal, isize) = (length(l.α),) """ Maxout(over) diff --git a/src/layers/conv.jl b/src/layers/conv.jl index f4de3ffc..eeeea82b 100644 --- a/src/layers/conv.jl +++ b/src/layers/conv.jl @@ -1,5 +1,7 @@ using NNlib: conv, ∇conv_data, depthwiseconv +_convoutdims(isize, ksize, ssize, pad) = Int.(floor.((isize .- ksize .+ 2 .* pad) ./ ssize .+ 1)) + expand(N, i::Tuple) = i expand(N, i::Integer) = ntuple(_ -> i, N) """ @@ -68,6 +70,18 @@ end (a::Conv{<:Any,<:Any,W})(x::AbstractArray{<:Real}) where {T <: Union{Float32,Float64}, W <: AbstractArray{T}} = a(T.(x)) +""" + outdims(l::Conv, isize::Tuple) + +Calculate the output dimensions given the input dimensions, `isize`. + +```julia +m = Conv((3, 3), 3 => 16) +outdims(m, (10, 10)) == (8, 8) +``` +""" +outdims(l::Conv{N}, isize) where N = _convoutdims(isize, size(l.weight)[1:N], l.stride, l.pad[1:N]) + """ ConvTranspose(size, in=>out) ConvTranspose(size, in=>out, relu) @@ -140,6 +154,7 @@ end (a::ConvTranspose{<:Any,<:Any,W})(x::AbstractArray{<:Real}) where {T <: Union{Float32,Float64}, W <: AbstractArray{T}} = a(T.(x)) + """ DepthwiseConv(size, in=>out) DepthwiseConv(size, in=>out, relu) @@ -204,6 +219,18 @@ end (a::DepthwiseConv{<:Any,<:Any,W})(x::AbstractArray{<:Real}) where {T <: Union{Float32,Float64}, W <: AbstractArray{T}} = a(T.(x)) +""" + outdims(l::DepthwiseConv, isize::Tuple) + +Calculate the output dimensions given the input dimensions, `isize`. + +```julia +m = DepthwiseConv((3, 3), 3 => 16) +outdims(m, (10, 10)) == (8, 8) +``` +""" +outdims(l::DepthwiseConv{N}, isize) where N = _convoutdims(isize, size(l.weight)[1:N], l.stride, l.pad[1:N]) + """ CrossCor(size, in=>out) CrossCor(size, in=>out, relu) @@ -304,6 +331,18 @@ function Base.show(io::IO, m::MaxPool) print(io, "MaxPool(", m.k, ", pad = ", m.pad, ", stride = ", m.stride, ")") end +""" + outdims(l::MaxPool, isize::Tuple) + +Calculate the output dimensions given the input dimensions, `isize`. + +```julia +m = MaxPool((2, 2)) +outdims(m, (10, 10)) == (5, 5) +``` +""" +outdims(l::MaxPool{N}, isize) where N = _convoutdims(isize, l.weight, l.stride, l.pad[1:N]) + """ MeanPool(k) @@ -331,3 +370,15 @@ end function Base.show(io::IO, m::MeanPool) print(io, "MeanPool(", m.k, ", pad = ", m.pad, ", stride = ", m.stride, ")") end + +""" + outdims(l::MeanPool, isize::Tuple) + +Calculate the output dimensions given the input dimensions, `isize`. + +```julia +m = MeanPool((2, 2)) +outdims(m, (10, 10)) == (5, 5) +``` +""" +outdims(l::MeanPool{N}, isize) where N = _convoutdims(isize, l.weight, l.stride, l.pad[1:N]) \ No newline at end of file From 31dda0ce6cd8c264d083d453823f4f13fa755da5 Mon Sep 17 00:00:00 2001 From: Kyle Daruwalla Date: Thu, 5 Dec 2019 21:57:10 -0600 Subject: [PATCH 2/9] Updated with all basic and conv layers outdims --- src/layers/basic.jl | 16 ++++++++++++++-- src/layers/conv.jl | 25 +++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/layers/basic.jl b/src/layers/basic.jl index f2e7645d..8794b58c 100644 --- a/src/layers/basic.jl +++ b/src/layers/basic.jl @@ -40,7 +40,7 @@ function Base.show(io::IO, c::Chain) end """ - outdims(c::Chain, isize::Tuple) + outdims(c::Chain, isize) Calculate the output dimensions given the input dimensions, `isize`. @@ -49,7 +49,7 @@ m = Chain(Conv((3, 3), 3 => 16), Conv((3, 3), 16 => 32)) outdims(m, (10, 10)) == (6, 6) ``` """ -outdims(c::Chain, isize::Tuple) = foldl(∘, map(l -> (x -> outdims(l, x)), c.layers)) +outdims(c::Chain, isize) = foldl(∘, map(l -> (x -> outdims(l, x)), c.layers)) # This is a temporary and naive implementation # it might be replaced in the future for better performance @@ -228,6 +228,18 @@ function (mo::Maxout)(input::AbstractArray) mapreduce(f -> f(input), (acc, out) -> max.(acc, out), mo.over) end +""" + outdims(c::Maxout, isize) + +Calculate the output dimensions given the input dimensions, `isize`. + +```julia +m = Maxout(Conv((3, 3), 3 => 16), Conv((3, 3), 16 => 32)) +outdims(m, (10, 10)) == (8, 8) +``` +""" +outdims(l::Maxout, isize) = outdims(first(l.over)) + """ SkipConnection(layers, connection) diff --git a/src/layers/conv.jl b/src/layers/conv.jl index eeeea82b..2e3e87d7 100644 --- a/src/layers/conv.jl +++ b/src/layers/conv.jl @@ -1,6 +1,7 @@ using NNlib: conv, ∇conv_data, depthwiseconv _convoutdims(isize, ksize, ssize, pad) = Int.(floor.((isize .- ksize .+ 2 .* pad) ./ ssize .+ 1)) +_convtransoutdims(isize, ksize, ssize, pad) = Int.(ssize .* (isize .- 1) .+ ksize .- 2 .* pad)) expand(N, i::Tuple) = i expand(N, i::Integer) = ntuple(_ -> i, N) @@ -155,6 +156,18 @@ end (a::ConvTranspose{<:Any,<:Any,W})(x::AbstractArray{<:Real}) where {T <: Union{Float32,Float64}, W <: AbstractArray{T}} = a(T.(x)) +""" + outdims(l::ConvTranspose, isize::Tuple) + +Calculate the output dimensions given the input dimensions, `isize`. + +```julia +m = ConvTranspose((3, 3), 3 => 16) +outdims(m, (8, 8)) == (10, 10) +``` +""" +outdims(l::ConvTranspose{N}, isize) where N = _convtransoutdims(isize, size(l.weight)[1:N], l.stride, l.pad[1:N]) + """ DepthwiseConv(size, in=>out) DepthwiseConv(size, in=>out, relu) @@ -302,6 +315,18 @@ end (a::CrossCor{<:Any,<:Any,W})(x::AbstractArray{<:Real}) where {T <: Union{Float32,Float64}, W <: AbstractArray{T}} = a(T.(x)) +""" + outdims(l::CrossCor, isize::Tuple) + +Calculate the output dimensions given the input dimensions, `isize`. + +```julia +m = CrossCor((3, 3), 3 => 16) +outdims(m, (10, 10)) == (8, 8) +``` +""" +outdims(l::CrossCor{N}, isize) where N = _convoutdims(isize, size(l.weight)[1:N], l.stride, l.pad[1:N]) + """ MaxPool(k) From 6265b1fa39c5d7d289ccd5a00c94ae9f448377fc Mon Sep 17 00:00:00 2001 From: Kyle Daruwalla Date: Thu, 5 Dec 2019 22:54:25 -0600 Subject: [PATCH 3/9] Added tests for outdims --- src/layers/basic.jl | 8 ++++---- src/layers/conv.jl | 8 ++++---- test/layers/basic.jl | 15 +++++++++++++++ test/layers/conv.jl | 20 ++++++++++++++++++++ 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/layers/basic.jl b/src/layers/basic.jl index 8794b58c..b62d8bb9 100644 --- a/src/layers/basic.jl +++ b/src/layers/basic.jl @@ -49,7 +49,7 @@ m = Chain(Conv((3, 3), 3 => 16), Conv((3, 3), 16 => 32)) outdims(m, (10, 10)) == (6, 6) ``` """ -outdims(c::Chain, isize) = foldl(∘, map(l -> (x -> outdims(l, x)), c.layers)) +outdims(c::Chain, isize) = foldl(∘, map(l -> (x -> outdims(l, x)), c.layers))(isize) # This is a temporary and naive implementation # it might be replaced in the future for better performance @@ -138,7 +138,7 @@ outdims(m, (5, 2)) == (5,) outdims(m, (10,)) == (5,) ``` """ -outdims(l::Dense, isize) = (size(l.W)[2],) +outdims(l::Dense, isize) = (size(l.W)[1],) """ Diagonal(in::Integer) @@ -234,11 +234,11 @@ end Calculate the output dimensions given the input dimensions, `isize`. ```julia -m = Maxout(Conv((3, 3), 3 => 16), Conv((3, 3), 16 => 32)) +m = Maxout(() -> Conv((3, 3), 3 => 16), 2) outdims(m, (10, 10)) == (8, 8) ``` """ -outdims(l::Maxout, isize) = outdims(first(l.over)) +outdims(l::Maxout, isize) = outdims(first(l.over), isize) """ SkipConnection(layers, connection) diff --git a/src/layers/conv.jl b/src/layers/conv.jl index 2e3e87d7..6ce9bcbf 100644 --- a/src/layers/conv.jl +++ b/src/layers/conv.jl @@ -1,7 +1,7 @@ using NNlib: conv, ∇conv_data, depthwiseconv _convoutdims(isize, ksize, ssize, pad) = Int.(floor.((isize .- ksize .+ 2 .* pad) ./ ssize .+ 1)) -_convtransoutdims(isize, ksize, ssize, pad) = Int.(ssize .* (isize .- 1) .+ ksize .- 2 .* pad)) +_convtransoutdims(isize, ksize, ssize, pad) = Int.(ssize .* (isize .- 1) .+ ksize .- 2 .* pad) expand(N, i::Tuple) = i expand(N, i::Integer) = ntuple(_ -> i, N) @@ -238,7 +238,7 @@ end Calculate the output dimensions given the input dimensions, `isize`. ```julia -m = DepthwiseConv((3, 3), 3 => 16) +m = DepthwiseConv((3, 3), 3 => 6) outdims(m, (10, 10)) == (8, 8) ``` """ @@ -366,7 +366,7 @@ m = MaxPool((2, 2)) outdims(m, (10, 10)) == (5, 5) ``` """ -outdims(l::MaxPool{N}, isize) where N = _convoutdims(isize, l.weight, l.stride, l.pad[1:N]) +outdims(l::MaxPool{N}, isize) where N = _convoutdims(isize, l.k, l.stride, l.pad[1:N]) """ MeanPool(k) @@ -406,4 +406,4 @@ m = MeanPool((2, 2)) outdims(m, (10, 10)) == (5, 5) ``` """ -outdims(l::MeanPool{N}, isize) where N = _convoutdims(isize, l.weight, l.stride, l.pad[1:N]) \ No newline at end of file +outdims(l::MeanPool{N}, isize) where N = _convoutdims(isize, l.k, l.stride, l.pad[1:N]) \ No newline at end of file diff --git a/test/layers/basic.jl b/test/layers/basic.jl index 0ff1776d..421c7721 100644 --- a/test/layers/basic.jl +++ b/test/layers/basic.jl @@ -92,4 +92,19 @@ import Flux: activations @test size(SkipConnection(Dense(10,10), (a,b) -> cat(a, b, dims = 2))(input)) == (10,4) end end + + @testset "output dimensions" begin + m = Chain(Conv((3, 3), 3 => 16), Conv((3, 3), 16 => 32)) + @test Flux.outdims(m, (10, 10)) == (6, 6) + + m = Dense(10, 5) + @test Flux.outdims(m, (5, 2)) == (5,) + @test Flux.outdims(m, (10,)) == (5,) + + m = Flux.Diagonal(10) + @test Flux.outdims(m, (10,)) == (10,) + + m = Maxout(() -> Conv((3, 3), 3 => 16), 2) + @test Flux.outdims(m, (10, 10)) == (8, 8) + end end diff --git a/test/layers/conv.jl b/test/layers/conv.jl index b4136062..5701df80 100644 --- a/test/layers/conv.jl +++ b/test/layers/conv.jl @@ -107,3 +107,23 @@ end true end end + +@testset "conv output dimensions" begin + m = Conv((3, 3), 3 => 16) + @test Flux.outdims(m, (10, 10)) == (8, 8) + + m = ConvTranspose((3, 3), 3 => 16) + @test Flux.outdims(m, (8, 8)) == (10, 10) + + m = DepthwiseConv((3, 3), 3 => 6) + @test Flux.outdims(m, (10, 10)) == (8, 8) + + m = CrossCor((3, 3), 3 => 16) + @test Flux.outdims(m, (10, 10)) == (8, 8) + + m = MaxPool((2, 2)) + @test Flux.outdims(m, (10, 10)) == (5, 5) + + m = MeanPool((2, 2)) + @test Flux.outdims(m, (10, 10)) == (5, 5) +end \ No newline at end of file From a64378b11272444f8803ec0155262d47ab0cef71 Mon Sep 17 00:00:00 2001 From: Kyle Daruwalla Date: Sat, 7 Dec 2019 13:21:26 -0600 Subject: [PATCH 4/9] Switched to using NNlib for conv.jl outdims. --- src/layers/basic.jl | 20 ------------- src/layers/conv.jl | 73 ++++++++++----------------------------------- 2 files changed, 15 insertions(+), 78 deletions(-) diff --git a/src/layers/basic.jl b/src/layers/basic.jl index b62d8bb9..6f056429 100644 --- a/src/layers/basic.jl +++ b/src/layers/basic.jl @@ -169,16 +169,6 @@ function Base.show(io::IO, l::Diagonal) print(io, "Diagonal(", length(l.α), ")") end -""" - outdims(l::Diagonal, isize) - -Calculate the output dimensions given the input dimensions, `isize`. - -```julia -m = Diagonal(10) -outdims(m, (10,)) == (10,) -``` -""" outdims(l::Diagonal, isize) = (length(l.α),) """ @@ -228,16 +218,6 @@ function (mo::Maxout)(input::AbstractArray) mapreduce(f -> f(input), (acc, out) -> max.(acc, out), mo.over) end -""" - outdims(c::Maxout, isize) - -Calculate the output dimensions given the input dimensions, `isize`. - -```julia -m = Maxout(() -> Conv((3, 3), 3 => 16), 2) -outdims(m, (10, 10)) == (8, 8) -``` -""" outdims(l::Maxout, isize) = outdims(first(l.over), isize) """ diff --git a/src/layers/conv.jl b/src/layers/conv.jl index 6ce9bcbf..7b32f999 100644 --- a/src/layers/conv.jl +++ b/src/layers/conv.jl @@ -1,6 +1,8 @@ -using NNlib: conv, ∇conv_data, depthwiseconv +using NNlib: conv, ∇conv_data, depthwiseconv, output_size + +# pad dims of x with dims of y until ndims(x) == ndims(y) +_paddims(x::Tuple, y::Tuple) = (x..., y[(end - (length(y) - length(x) - 1)):end]...) -_convoutdims(isize, ksize, ssize, pad) = Int.(floor.((isize .- ksize .+ 2 .* pad) ./ ssize .+ 1)) _convtransoutdims(isize, ksize, ssize, pad) = Int.(ssize .* (isize .- 1) .+ ksize .- 2 .* pad) expand(N, i::Tuple) = i @@ -75,13 +77,16 @@ end outdims(l::Conv, isize::Tuple) Calculate the output dimensions given the input dimensions, `isize`. +Batch size and channel size are ignored as per `NNlib.jl`. ```julia m = Conv((3, 3), 3 => 16) outdims(m, (10, 10)) == (8, 8) +outdims(m, (10, 10, 1, 3)) == (8, 8) ``` """ -outdims(l::Conv{N}, isize) where N = _convoutdims(isize, size(l.weight)[1:N], l.stride, l.pad[1:N]) +outdims(l::Conv, isize) = + output_size(DenseConvDims(_paddims(isize, size(l.weight)), size(l.weight); stride = l.stride, padding = l.pad, dilation = l.dilation)) """ ConvTranspose(size, in=>out) @@ -156,17 +161,7 @@ end (a::ConvTranspose{<:Any,<:Any,W})(x::AbstractArray{<:Real}) where {T <: Union{Float32,Float64}, W <: AbstractArray{T}} = a(T.(x)) -""" - outdims(l::ConvTranspose, isize::Tuple) - -Calculate the output dimensions given the input dimensions, `isize`. - -```julia -m = ConvTranspose((3, 3), 3 => 16) -outdims(m, (8, 8)) == (10, 10) -``` -""" -outdims(l::ConvTranspose{N}, isize) where N = _convtransoutdims(isize, size(l.weight)[1:N], l.stride, l.pad[1:N]) +outdims(l::ConvTranspose{N}, isize) where N = _convtransoutdims(isize[1:2], size(l.weight)[1:N], l.stride, l.pad[1:N]) """ DepthwiseConv(size, in=>out) @@ -232,17 +227,8 @@ end (a::DepthwiseConv{<:Any,<:Any,W})(x::AbstractArray{<:Real}) where {T <: Union{Float32,Float64}, W <: AbstractArray{T}} = a(T.(x)) -""" - outdims(l::DepthwiseConv, isize::Tuple) - -Calculate the output dimensions given the input dimensions, `isize`. - -```julia -m = DepthwiseConv((3, 3), 3 => 6) -outdims(m, (10, 10)) == (8, 8) -``` -""" -outdims(l::DepthwiseConv{N}, isize) where N = _convoutdims(isize, size(l.weight)[1:N], l.stride, l.pad[1:N]) +outdims(l::DepthwiseConv, isize) = + output_size(DepthwiseConvDims(_paddims(isize, (1, 1, size(l.weight)[end], 1)), size(l.weight); stride = l.stride, padding = l.pad, dilation = l.dilation)) """ CrossCor(size, in=>out) @@ -315,17 +301,8 @@ end (a::CrossCor{<:Any,<:Any,W})(x::AbstractArray{<:Real}) where {T <: Union{Float32,Float64}, W <: AbstractArray{T}} = a(T.(x)) -""" - outdims(l::CrossCor, isize::Tuple) - -Calculate the output dimensions given the input dimensions, `isize`. - -```julia -m = CrossCor((3, 3), 3 => 16) -outdims(m, (10, 10)) == (8, 8) -``` -""" -outdims(l::CrossCor{N}, isize) where N = _convoutdims(isize, size(l.weight)[1:N], l.stride, l.pad[1:N]) +outdims(l::CrossCor, isize) = + output_size(DenseConvDims(_paddims(isize, size(l.weight)), size(l.weight); stride = l.stride, padding = l.pad, dilation = l.dilation)) """ MaxPool(k) @@ -356,17 +333,7 @@ function Base.show(io::IO, m::MaxPool) print(io, "MaxPool(", m.k, ", pad = ", m.pad, ", stride = ", m.stride, ")") end -""" - outdims(l::MaxPool, isize::Tuple) - -Calculate the output dimensions given the input dimensions, `isize`. - -```julia -m = MaxPool((2, 2)) -outdims(m, (10, 10)) == (5, 5) -``` -""" -outdims(l::MaxPool{N}, isize) where N = _convoutdims(isize, l.k, l.stride, l.pad[1:N]) +outdims(l::MaxPool{N}, isize) where N = output_size(PoolDims(_paddims(isize, (l.k..., 1, 1)), l.k; stride = l.stride, padding = l.pad)) """ MeanPool(k) @@ -396,14 +363,4 @@ function Base.show(io::IO, m::MeanPool) print(io, "MeanPool(", m.k, ", pad = ", m.pad, ", stride = ", m.stride, ")") end -""" - outdims(l::MeanPool, isize::Tuple) - -Calculate the output dimensions given the input dimensions, `isize`. - -```julia -m = MeanPool((2, 2)) -outdims(m, (10, 10)) == (5, 5) -``` -""" -outdims(l::MeanPool{N}, isize) where N = _convoutdims(isize, l.k, l.stride, l.pad[1:N]) \ No newline at end of file +outdims(l::MeanPool{N}, isize) where N = output_size(PoolDims(_paddims(isize, (l.k..., 1, 1)), l.k; stride = l.stride, padding = l.pad)) \ No newline at end of file From 0cdd11c0dc8e8e82a90467cc66e3b8330ad57682 Mon Sep 17 00:00:00 2001 From: Kyle Daruwalla Date: Sat, 7 Dec 2019 14:05:50 -0600 Subject: [PATCH 5/9] Added tests for varying padding, stride, and dilation with outdims. --- src/layers/conv.jl | 4 ++-- test/layers/conv.jl | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/layers/conv.jl b/src/layers/conv.jl index 7b32f999..03de438a 100644 --- a/src/layers/conv.jl +++ b/src/layers/conv.jl @@ -3,7 +3,7 @@ using NNlib: conv, ∇conv_data, depthwiseconv, output_size # pad dims of x with dims of y until ndims(x) == ndims(y) _paddims(x::Tuple, y::Tuple) = (x..., y[(end - (length(y) - length(x) - 1)):end]...) -_convtransoutdims(isize, ksize, ssize, pad) = Int.(ssize .* (isize .- 1) .+ ksize .- 2 .* pad) +_convtransoutdims(isize, ksize, ssize, dsize, pad) = (isize .- 1).*ssize .+ 1 .+ (ksize .- 1).*dsize .- (pad[1:2:end] .+ pad[2:2:end]) expand(N, i::Tuple) = i expand(N, i::Integer) = ntuple(_ -> i, N) @@ -161,7 +161,7 @@ end (a::ConvTranspose{<:Any,<:Any,W})(x::AbstractArray{<:Real}) where {T <: Union{Float32,Float64}, W <: AbstractArray{T}} = a(T.(x)) -outdims(l::ConvTranspose{N}, isize) where N = _convtransoutdims(isize[1:2], size(l.weight)[1:N], l.stride, l.pad[1:N]) +outdims(l::ConvTranspose{N}, isize) where N = _convtransoutdims(isize[1:2], size(l.weight)[1:N], l.stride, l.dilation, l.pad) """ DepthwiseConv(size, in=>out) diff --git a/test/layers/conv.jl b/test/layers/conv.jl index 5701df80..1a22b385 100644 --- a/test/layers/conv.jl +++ b/test/layers/conv.jl @@ -111,19 +111,51 @@ end @testset "conv output dimensions" begin m = Conv((3, 3), 3 => 16) @test Flux.outdims(m, (10, 10)) == (8, 8) + m = Conv((3, 3), 3 => 16; stride = 2) + @test Flux.outdims(m, (5, 5)) == (2, 2) + m = Conv((3, 3), 3 => 16; stride = 2, pad = 3) + @test Flux.outdims(m, (5, 5)) == (5, 5) + m = Conv((3, 3), 3 => 16; stride = 2, pad = 3, dilation = 2) + @test Flux.outdims(m, (5, 5)) == (4, 4) m = ConvTranspose((3, 3), 3 => 16) @test Flux.outdims(m, (8, 8)) == (10, 10) + m = ConvTranspose((3, 3), 3 => 16; stride = 2) + @test Flux.outdims(m, (2, 2)) == (5, 5) + m = ConvTranspose((3, 3), 3 => 16; stride = 2, pad = 3) + @test Flux.outdims(m, (5, 5)) == (5, 5) + m = ConvTranspose((3, 3), 3 => 16; stride = 2, pad = 3, dilation = 2) + @test Flux.outdims(m, (4, 4)) == (5, 5) m = DepthwiseConv((3, 3), 3 => 6) @test Flux.outdims(m, (10, 10)) == (8, 8) + m = DepthwiseConv((3, 3), 3 => 6; stride = 2) + @test Flux.outdims(m, (5, 5)) == (2, 2) + m = DepthwiseConv((3, 3), 3 => 6; stride = 2, pad = 3) + @test Flux.outdims(m, (5, 5)) == (5, 5) + m = DepthwiseConv((3, 3), 3 => 6; stride = 2, pad = 3, dilation = 2) + @test Flux.outdims(m, (5, 5)) == (4, 4) m = CrossCor((3, 3), 3 => 16) @test Flux.outdims(m, (10, 10)) == (8, 8) + m = CrossCor((3, 3), 3 => 16; stride = 2) + @test Flux.outdims(m, (5, 5)) == (2, 2) + m = CrossCor((3, 3), 3 => 16; stride = 2, pad = 3) + @test Flux.outdims(m, (5, 5)) == (5, 5) + m = CrossCor((3, 3), 3 => 16; stride = 2, pad = 3, dilation = 2) + @test Flux.outdims(m, (5, 5)) == (4, 4) m = MaxPool((2, 2)) @test Flux.outdims(m, (10, 10)) == (5, 5) + m = MaxPool((2, 2); stride = 1) + @test Flux.outdims(m, (5, 5)) == (4, 4) + m = MaxPool((2, 2); stride = 2, pad = 3) + @test Flux.outdims(m, (5, 5)) == (5, 5) m = MeanPool((2, 2)) @test Flux.outdims(m, (10, 10)) == (5, 5) + m = MeanPool((2, 2); stride = 1) + @test Flux.outdims(m, (5, 5)) == (4, 4) + m = MeanPool((2, 2); stride = 2, pad = 3) + @test Flux.outdims(m, (5, 5)) == (5, 5) end \ No newline at end of file From 04991d3261f006f134beb6333f504ad27e11a706 Mon Sep 17 00:00:00 2001 From: Kyle Daruwalla Date: Sat, 7 Dec 2019 14:06:11 -0600 Subject: [PATCH 6/9] Added entry to docs for outdims --- docs/src/models/basics.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/src/models/basics.md b/docs/src/models/basics.md index d83fc462..c6dc4e19 100644 --- a/docs/src/models/basics.md +++ b/docs/src/models/basics.md @@ -219,3 +219,13 @@ Flux.@functor Affine ``` This enables a useful extra set of functionality for our `Affine` layer, such as [collecting its parameters](../training/optimisers.md) or [moving it to the GPU](../gpu.md). + +## Utility functions + +Flux provides some utility functions to help you generate models in an automated fashion. + +`outdims` enables you to calculate the spatial output dimensions of layers like `Conv` when applied to input images of a given size. + +```@docs +outdims +``` From 2f854bdfc0d7064f4e28988d6418d9b09324c11e Mon Sep 17 00:00:00 2001 From: Kyle Daruwalla Date: Tue, 10 Dec 2019 09:57:08 -0600 Subject: [PATCH 7/9] Recommitting to trigger new build From c37fc3cfa63a82deec33d40f837b880341440c7a Mon Sep 17 00:00:00 2001 From: Kyle Daruwalla Date: Sun, 9 Feb 2020 19:45:04 -0600 Subject: [PATCH 8/9] Recommitting to trigger build From f5b9cf659cb14f0b05ab98b2fef70f705adfc8c3 Mon Sep 17 00:00:00 2001 From: Kyle Daruwalla Date: Thu, 20 Feb 2020 23:38:56 -0600 Subject: [PATCH 9/9] Updated docs to specify exactly what layers support outdims --- docs/src/models/basics.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/src/models/basics.md b/docs/src/models/basics.md index c6dc4e19..6e8d0b76 100644 --- a/docs/src/models/basics.md +++ b/docs/src/models/basics.md @@ -225,6 +225,17 @@ This enables a useful extra set of functionality for our `Affine` layer, such as Flux provides some utility functions to help you generate models in an automated fashion. `outdims` enables you to calculate the spatial output dimensions of layers like `Conv` when applied to input images of a given size. +Currently limited to the following layers: +- `Chain` +- `Dense` +- `Conv` +- `Diagonal` +- `Maxout` +- `ConvTranspose` +- `DepthwiseConv` +- `CrossCor` +- `MaxPool` +- `MeanPool` ```@docs outdims