Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MethodError from show on custom layer, using @functor with no fields #2208

Closed
kuanchiun opened this issue Mar 11, 2023 · 3 comments · Fixed by #2210
Closed

MethodError from show on custom layer, using @functor with no fields #2208

kuanchiun opened this issue Mar 11, 2023 · 3 comments · Fixed by #2210
Labels

Comments

@kuanchiun
Copy link

Package Version

0.13.14

Julia Version

1.8.2

OS / Environment

Windows 10

Describe the bug

I constructed the layer called MinMaxScale, and when I tried to use Flux.Chain() to chain the Dense layer and MinMaxScale layer, I got the method error about the empty collection.

Steps to Reproduce

using Flux
struct MinMaxScale end

Flux.@functor MinMaxScale

function (l::MinMaxScale)(x::AbstractArray)
    minx, maxx = extrema(x)
    return (x .- minx) ./ (maxx - minx)
end

function Base.show(io::IO, l::MinMaxScale)
    print(io, "MinMaxScale")
end

encoder = Chain(
    Dense(100 => 10, gelu),
    Dense(10 => 1, gelu),
    MinMaxScale()
)

Expected Results

The model should be worked

Observed Results

Got Method error

MethodError: reducing over an empty collection is not allowed; consider supplying init to the reducer

Relevant log output

MethodError: reducing over an empty collection is not allowed; consider supplying init to the reducer
Stacktrace:
[1] reduce_empty(op::Base.MappingRF{Flux.var"#350#351"{Flux.var"#348#349"}, Base.BottomRF{typeof(Base.add_sum)}}, #unused#::Type{Union{}})
@ Base .\reduce.jl:356
[2] reduce_empty_iter(op::Base.MappingRF{Flux.var"#350#351"{Flux.var"#348#349"}, Base.BottomRF{typeof(Base.add_sum)}}, itr::NamedTuple{(), Tuple{}}, #unused#::Base.HasEltype)
@ Base .\reduce.jl:379
[3] reduce_empty_iter(op::Base.MappingRF{Flux.var"#350#351"{Flux.var"#348#349"}, Base.BottomRF{typeof(Base.add_sum)}}, itr::NamedTuple{(), Tuple{}})
@ Base .\reduce.jl:378
[4] foldl_impl(op::Base.MappingRF{Flux.var"#350#351"{Flux.var"#348#349"}, Base.BottomRF{typeof(Base.add_sum)}}, nt::Base._InitialValue, itr::NamedTuple{(), Tuple{}})
@ Base .\reduce.jl:49
[5] mapfoldl_impl(f::Flux.var"#350#351"{Flux.var"#348#349"}, op::typeof(Base.add_sum), nt::Base._InitialValue, itr::NamedTuple{(), Tuple{}})
@ Base .\reduce.jl:44
[6] mapfoldl(f::Function, op::Function, itr::NamedTuple{(), Tuple{}}; init::Base._InitialValue)
@ Base .\reduce.jl:170
[7] mapfoldl
@ .\reduce.jl:170 [inlined]
[8] #mapreduce#263
@ .\reduce.jl:302 [inlined]
[9] mapreduce
@ .\reduce.jl:302 [inlined]
[10] #sum#266
@ .\reduce.jl:528 [inlined]
[11] sum
@ .\reduce.jl:528 [inlined]
[12] _childarray_sum(f::Function, x::MinMaxScale)
@ Flux C:\Users\Tung.julia\packages\Flux\Nzh8J\src\layers\show.jl:110
[13] (::Flux.var"#350#351"{Flux.var"#348#349"})(y::MinMaxScale)
@ Flux C:\Users\Tung.julia\packages\Flux\Nzh8J\src\layers\show.jl:110
[14] MappingRF
@ .\reduce.jl:95 [inlined]
[15] afoldl(::Base.MappingRF{Flux.var"#350#351"{Flux.var"#348#349"}, Base.BottomRF{typeof(Base.add_sum)}}, ::Base._InitialValue, ::Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, ::Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, ::MinMaxScale)
@ Base .\operators.jl:550
[16] _foldl_impl(op::Base.MappingRF{Flux.var"#350#351"{Flux.var"#348#349"}, Base.BottomRF{typeof(Base.add_sum)}}, init::Base._InitialValue, itr::Tuple{Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, MinMaxScale})
@ Base .\tuple.jl:277
[17] foldl_impl(op::Base.MappingRF{Flux.var"#350#351"{Flux.var"#348#349"}, Base.BottomRF{typeof(Base.add_sum)}}, nt::Base._InitialValue, itr::Tuple{Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, MinMaxScale})
@ Base .\reduce.jl:48
[18] mapfoldl_impl(f::Flux.var"#350#351"{Flux.var"#348#349"}, op::typeof(Base.add_sum), nt::Base._InitialValue, itr::Tuple{Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, MinMaxScale})
@ Base .\reduce.jl:44
[19] mapfoldl(f::Function, op::Function, itr::Tuple{Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, MinMaxScale}; init::Base._InitialValue)
@ Base .\reduce.jl:170
[20] mapfoldl
@ .\reduce.jl:170 [inlined]
[21] #mapreduce#263
@ .\reduce.jl:302 [inlined]
[22] mapreduce
@ .\reduce.jl:302 [inlined]
[23] #sum#266
@ .\reduce.jl:528 [inlined]
[24] sum
@ .\reduce.jl:528 [inlined]
[25] _childarray_sum(f::Function, x::Tuple{Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, MinMaxScale})
@ Flux C:\Users\Tung.julia\packages\Flux\Nzh8J\src\layers\show.jl:110
[26] (::Flux.var"#350#351"{Flux.var"#348#349"})(y::Tuple{Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, MinMaxScale})
@ Flux C:\Users\Tung.julia\packages\Flux\Nzh8J\src\layers\show.jl:110
[27] MappingRF
@ .\reduce.jl:95 [inlined]
[28] _foldl_impl(op::Base.MappingRF{Flux.var"#350#351"{Flux.var"#348#349"}, Base.BottomRF{typeof(Base.add_sum)}}, init::Base._InitialValue, itr::NamedTuple{(:layers,), Tuple{Tuple{Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, MinMaxScale}}})
@ Base .\reduce.jl:58
[29] foldl_impl(op::Base.MappingRF{Flux.var"#350#351"{Flux.var"#348#349"}, Base.BottomRF{typeof(Base.add_sum)}}, nt::Base._InitialValue, itr::NamedTuple{(:layers,), Tuple{Tuple{Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, MinMaxScale}}})
@ Base .\reduce.jl:48
[30] mapfoldl_impl(f::Flux.var"#350#351"{Flux.var"#348#349"}, op::typeof(Base.add_sum), nt::Base._InitialValue, itr::NamedTuple{(:layers,), Tuple{Tuple{Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, MinMaxScale}}})
@ Base .\reduce.jl:44
[31] mapfoldl(f::Function, op::Function, itr::NamedTuple{(:layers,), Tuple{Tuple{Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, MinMaxScale}}}; init::Base._InitialValue)
@ Base .\reduce.jl:170
[32] mapfoldl
@ .\reduce.jl:170 [inlined]
[33] #mapreduce#263
@ .\reduce.jl:302 [inlined]
[34] mapreduce
@ .\reduce.jl:302 [inlined]
[35] #sum#266
@ .\reduce.jl:528 [inlined]
[36] sum(f::Function, a::NamedTuple{(:layers,), Tuple{Tuple{Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, MinMaxScale}}})
@ Base .\reduce.jl:528
[37] _childarray_sum
@ C:\Users\Tung.julia\packages\Flux\Nzh8J\src\layers\show.jl:110 [inlined]
[38] _big_finale(io::IOContext{IOBuffer}, m::Chain{Tuple{Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, MinMaxScale}})
@ Flux C:\Users\Tung.julia\packages\Flux\Nzh8J\src\layers\show.jl:95
[39] _big_show(io::IOContext{IOBuffer}, obj::Chain{Tuple{Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, MinMaxScale}}, indent::Int64, name::Nothing)
@ Flux C:\Users\Tung.julia\packages\Flux\Nzh8J\src\layers\show.jl:40
[40] _big_show
@ C:\Users\Tung.julia\packages\Flux\Nzh8J\src\layers\show.jl:17 [inlined]
[41] show(io::IOContext{IOBuffer}, m::MIME{Symbol("text/plain")}, x::Chain{Tuple{Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, MinMaxScale}})
@ Flux C:\Users\Tung.julia\packages\Flux\Nzh8J\src\layers\show.jl:7
[42] limitstringmime(mime::MIME{Symbol("text/plain")}, x::Chain{Tuple{Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, MinMaxScale}})
@ IJulia C:\Users\Tung.julia\packages\IJulia\6TIq1\src\inline.jl:43
[43] display_mimestring
@ C:\Users\Tung.julia\packages\IJulia\6TIq1\src\display.jl:71 [inlined]
[44] display_dict(x::Chain{Tuple{Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, Dense{typeof(gelu), Matrix{Float32}, Vector{Float32}}, MinMaxScale}})
@ IJulia C:\Users\Tung.julia\packages\IJulia\6TIq1\src\display.jl:102
[45] #invokelatest#2
@ .\essentials.jl:729 [inlined]
[46] invokelatest
@ .\essentials.jl:726 [inlined]
[47] execute_request(socket::ZMQ.Socket, msg::IJulia.Msg)
@ IJulia C:\Users\Tung.julia\packages\IJulia\6TIq1\src\execute_request.jl:112
[48] #invokelatest#2
@ .\essentials.jl:729 [inlined]
[49] invokelatest
@ .\essentials.jl:726 [inlined]
[50] eventloop(socket::ZMQ.Socket)
@ IJulia C:\Users\Tung.julia\packages\IJulia\6TIq1\src\eventloop.jl:8

@mcabbott
Copy link
Member

This is a bug. Somewhere in show.jl there's a sum which should have init=0 or something?

But the minimal work-around is not to call @functor MinMaxScale. Since it does not wrap any parameters, there should be no need for Functors to walk inside it.

@ToucheSir
Copy link
Member

The custom show method is probably not required either, as the default will print MinMaxScale() as expected.

@kuanchiun
Copy link
Author

Removed Flux.@functor and return normal, Thank you @mcabbott !
I will remove the show method, Thank you @ToucheSir

@mcabbott mcabbott changed the title MethodError when using the custom layer. MethodError from show on custom layer, using @functor with no fields Mar 11, 2023
@mcabbott mcabbott added the bug label Mar 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants