Flux.jl
Flux.jl copied to clipboard
Add a macro to opt-in to fancy printing, and to everything else
Originally, @big_show
This adds a macro which lets you tell Flux to treat some container type much the same way as it treats Chain, starting the recursive printing walk over all children.
Prompted by #1929. Closes #2044
Metalhead also has show methods for top-level layers which enable the recursive printing, which could be replaced by this macro:
https://github.com/FluxML/Metalhead.jl/blob/aba6fb832093d88dc2d2b4d5b1d2d63a0f21eb9c/src/Metalhead.jl#L53-L57
https://github.com/FluxML/Metalhead.jl/blob/c8f0a88e4d24274c53b62c2b740822aa6a781709/src/utilities.jl#L49-L52
Searching for other uses on github, I see only two:
https://github.com/avik-pal/ExplicitFluxLayers.jl/blob/8e1cff447afda225bc12144ff27ae1370e8fc3da/src/show_layers.jl
https://github.com/maxfreu/SegmentationModels.jl/blob/7bfdbaa438910baf49543f03f2931de765dbd761/src/unet.jl#L99-L112
Later, @layer
Now aims to also replace @functor, in addition to handling show.
Discussed at https://github.com/FluxML/Flux.jl/pull/2028 -- a layer supertype is another way to make opting into pretty printing easier. (We wouldn't do both, so this closes https://github.com/FluxML/Flux.jl/pull/2028 .)
PR Checklist
- [x] Tests are added
- [x] Entry in NEWS.md
- [ ] Documentation, if applicable
Looks reasonable, so if you'd let me indulge in some light bikeshedding how about @show_expanded over @big_show?
Not at all set on the name.
Another question is whether there should be a matching way to disable recursion. Overloading _show_leaflike(::Diagonal) to make LayerNorm not expand is slightly weird. It's a hack to re-use the fact that layers all of whose children area leaflike aren't expanded, and has side-effects like this:
julia> Chain(Flux.Scale(2), Flux.Scale(2))
Chain(Scale(2), Scale(2)) # 8 parameters
julia> Chain(Flux.Scale(2), Flux.Scale(2), Dense(2=>2))
Chain(
Scale(2), # 4 parameters
Scale(2), # 4 parameters
Dense(2 => 2), # 6 parameters
) # Total: 6 arrays, 14 parameters, 440 bytes.
If this needs a public face, then perhaps it should be more like @show_noexpand LayerNorm i.e. a property of the container, not the contents.
show_leaflike(x::MyType) = true allowing to customize on the specific object seems more flexible and it feels ok to me as an interface, I would prefer that over a macro.
We could also merge this PR now since it seems ready and expose that interface later
6370374 upgrades this to a replacement for @functor. The idea is to have just one magic macro do several things for us, maybe that's less confusing. It would also allow any back-end changes later, once Flux owns the macro. Discussed at https://github.com/FluxML/Flux.jl/pull/2028 (as an alternative to the supertype idea there).
Still WIP, but roughly works, I think.
Doctest failure looks real, but I'm not sure why it's only showing up now.
Doc failure seems to be that this doesn't work on 1.6, where the first argument is a vector:
julia> Dense([3.3;;], false)
Dense(1 => 1; bias=false) # 1 parameters
Downstream tests didn't run, not sure why.
Failures look unrelated:
- GeometricFlux.jl I see only
create_biasfailures, https://github.com/FluxML/Flux.jl/issues/2049 - FastAI.jl has failures like "Expression: isempty(stderr_content) [1105] Evaluated: isempty("┌ Warning:
ignore(f)is deprecated, useChainRulesCore.ignore_derivatives(f)instead.\n│ caller =" - AtomicGraphNets.jl has failures like "MethodError: no method matching needs_concrete_A(::Nothing) Closest candidates are: needs_concrete_A(::LinearSolve.AbstractFactorization) at ~/.julia/packages/LinearSolve/AoYJI/src/LinearSolve.jl:34"
- OperatorLearning.jl has
create_biasonly
So just the doctest fixup for 1.6?
Shall we do this?
Making Functors opt-out instead isn't going to happen tomorrow. And having an official way to opt-in to show would still be worth something.
Codecov Report
Attention: Patch coverage is 70.19231% with 31 lines in your changes are missing coverage. Please review.
Project coverage is 73.91%. Comparing base (
20d516b) to head (63e10f6).
| Files | Patch % | Lines |
|---|---|---|
| src/layers/attention.jl | 9.52% | 19 Missing :warning: |
| src/layers/macro.jl | 81.66% | 11 Missing :warning: |
| src/layers/normalise.jl | 0.00% | 1 Missing :warning: |
Additional details and impacted files
@@ Coverage Diff @@
## master #1932 +/- ##
===========================================
+ Coverage 42.55% 73.91% +31.35%
===========================================
Files 31 32 +1
Lines 1786 1909 +123
===========================================
+ Hits 760 1411 +651
+ Misses 1026 498 -528
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
Rebased in 2024. We should just do this, right?
The biggest questions is: Should this support children at all? Or can we simply forbid that... do we really need 4 ways to customise things, alla #2385? Maybe if you want to hack things with Functors.jl directly you are welcome, but Flux.jl can pretend this doesn't exist.
I agree. Given that you almost never want to set children, having to support and explain children vs trainable is just confusing for users. Anyone wanting to restrict children probably needs to take a minute to understand @functor first.
OK, children is gone.
This should be ready to merge, I think. As always there may be further cleaning up of the docs possible.