Skip to content

[WIP] Make ImageFiltering.imfilter pipeline differentiable#21

Open
SomTambe wants to merge 4 commits into
mainfrom
som/kernels
Open

[WIP] Make ImageFiltering.imfilter pipeline differentiable#21
SomTambe wants to merge 4 commits into
mainfrom
som/kernels

Conversation

@SomTambe

@SomTambe SomTambe commented Aug 25, 2021

Copy link
Copy Markdown
Member

This PR aims to make the ImageFiltering.imfilter function differentiable.

  • Add adjoints
  • Get the gradient of the kernel
  • Put tests

The current issue I am facing causes the gradient of the kernel to be nothing. There seems to be a place where I have incorrectly put a NoTangent(), or a @nograd. Infact upon some further tracing I found out it does go inside the rule of __imfilter_inbounds!, but never calls the pullback inside it.

julia> img = testimage("cameraman");

julia> gradf(x, k, args...) = Zygote.gradient((a, b)->imfilter(a, b, args...) |> sum |> (z->z.val), x, k)
gradf (generic function with 1 method)

julia> gradf(img, t*t') 
(Tangent{Gray{Float64}, NamedTuple{(:val,), Tuple{Float64}}}[Tangent{Gray{Float64}}(val = 1.0,) Tangent{Gray{Float64}}(val = 1.0,)  Tangent{Gray{Float64}}(val = 1.0,) Tangent{Gray{Float64}}(val = 1.0,); Tangent{Gray{Float64}}(val = 1.0,) Tangent{Gray{Float64}}(val = 1.0,)  Tangent{Gray{Float64}}(val = 1.0,) Tangent{Gray{Float64}}(val = 1.0,);  ; Tangent{Gray{Float64}}(val = 1.0,) Tangent{Gray{Float64}}(val = 1.0,)  Tangent{Gray{Float64}}(val = 1.0,) Tangent{Gray{Float64}}(val = 1.0,); Tangent{Gray{Float64}}(val = 1.0,) Tangent{Gray{Float64}}(val = 1.0,)  Tangent{Gray{Float64}}(val = 1.0,) Tangent{Gray{Float64}}(val = 1.0,)], nothing)

The img gradient is incorrect too, and I shall get it rectified when I write tests and figure out the kernel thing.

@codecov-commenter

codecov-commenter commented Aug 25, 2021

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

@DhairyaLGandhi

Copy link
Copy Markdown
Member

Yeah you definitely want the Tangent to wrap an array and not elements I would imagine.

@DhairyaLGandhi DhairyaLGandhi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking this up! Looking forward to the tests. I'll also take a look through the adjoints to see if they're correct

Comment thread src/filters/adjoints.jl
z)
y = __imfilter_inbounds!(r, out, A, kern, border, R, z)
function ∇__imfilter_inbounds!(Δy)
# ∇out should not have any gradients

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it will be used further down in the computation pipeline, i think you still need to provide it the gradient so it can be accumulated properly. Else the answer would be incorrect

Comment thread src/filters/adjoints.jl
y = imfilter!(out, img, kernel, border, alg)
function ∇imfilter!_try(Δy)
k = default_resource(alg_defaults(alg, out, kernel))
ret = imfilter!(k, out, img, kernel, border)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this true generically?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants