-
-
Notifications
You must be signed in to change notification settings - Fork 124
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
Add lppool
implementation
#447
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, thanks! I have not checked the implementation closely but have a few comments in the meantime...
lppool(x, p::Number, k::NTuple; pad=0, stride=k) | ||
|
||
Perform Lp pool operation with `p`-norm and `window size `k` on input tensor `x` | ||
""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this explain a bit more?
-
It should say that it requires
ndims(x) == length(k)+2
. -
I think it should also say
lppool(x, 1, k) ./ prod(k) ≈ meanpool(x, k)
, and maybelppool(x, 2, k).^2 ./ prod(k) ≈ meanpool(x.^2, k)
. -
What range of
p
is allowed? E.g. someone might expectlppool(reshape(1:10.0,:,1,1), Inf, (3,))
to be maxpool, but it isn't... maybe anything which works fornorm
but not here should be an error? -
Can it briefly say what types are allowed for
stride, pad
, or refer to fuller docs elsewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PyTorch layer docstring would be a good inspiration for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this explain a bit more?
- It should say that it requires
ndims(x) == length(k)+2
.- I think it should also say
lppool(x, 1, k) ./ prod(k) ≈ meanpool(x, k)
, and maybelppool(x, 2, k).^2 ./ prod(k) ≈ meanpool(x.^2, k)
.- What range of
p
is allowed? E.g. someone might expectlppool(reshape(1:10.0,:,1,1), Inf, (3,))
to be maxpool, but it isn't... maybe anything which works fornorm
but not here should be an error?- Can it briefly say what types are allowed for
stride, pad
, or refer to fuller docs elsewhere?
I add docs for these aspects in new commit.
The PyTorch layer docstring would be a good inspiration for this.
I wonder if it might be suitable to write super detailed docs here. Flux.jl would wrap pooling layer after all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Our docstrings for meanpool
and maxpool
are quite short. Given that LP-pooling is far less well known however, it warrants a bit more explanation.
Re the name, we have This one maps I realise this breaks with pytorch, but we aren't tied to copying them. Also, |
The PyTorch implementation uses "power-average pooling", so that's another option. One concerning thing I did find while looking around for name ideas is that nobody seems to be using this? GitHub search turns up only a couple instances of |
The paper proposes |
Nice find! Do you mind adding it as the primary reference in the docstring (see how this is done for Flux layers)? Also, is |
OK, I've changed the name in recent commit and add paper reference. |
The title does have "Norm Pooling" as they felt squeezing L_p in there too much? Also LinearAlgebra's function could be called |
I think lppool is ok or "lp" is needed because pytorch uses this. If normpool is used as name, users may spend time figuring out that normpool equals lppool in pytorch. |
having the more articulate name |
@mcabbott Thanks for your patient review! I resolved all points metioned above and re-requested a new review just now :) |
@mcabbott @ToucheSir @CarloLucibello Thanks for your patience and kindness again! I really learn alot from this PR. |
@@ -103,7 +109,7 @@ end | |||
# Finally, let's generate auto-allocating versions of all our functions, for all backends: | |||
for backend in (Symbol(), :_direct, :_nnpack) | |||
# First make auto-allocating versions of the basic pooling calls: | |||
for name in (:maxpool, :meanpool) | |||
for name in (:maxpool, :meanpool, :lpnormpool) | |||
@eval begin | |||
function $(Symbol("$(name)$(backend)"))( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe worth noting that this similar
means that lower-precision input gives the correct output without promotion, and that integer input fails here (unlike other pooling):
julia> NNlib.lpnormpool(ones(Float32, 4,1,1), 2.001, (2,), stride=1)
3×1×1 Array{Float32, 3}:
[:, :, 1] =
1.4139687
1.4139687
1.4139687
julia> NNlib.lpnormpool(ones(Int, 4,1,1), 2.001, (2,), stride=1)
ERROR: InexactError: Int64(1.4139686415190424)
julia> NNlib.maxpool(ones(Int, 4,1,1), (2,), stride=1) # is OK with integers
3×1×1 Array{Int64, 3}:
[:, :, 1] =
1
1
1
julia> NNlib.meanpool(ones(Int, 4,1,1), (2,), stride=1) # is OK with integers
3×1×1 Array{Int64, 3}:
[:, :, 1] =
1
1
1
About FluxML/Flux.jl#1431: LPPool1d and LPPool2d.
PR Checklist
Related tests and documentation will come soon.