-
-
Notifications
You must be signed in to change notification settings - Fork 36
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
Make jacobian work with CuArrays #33
Conversation
So the reason Jacobian is written this way is so that nested AD works, and this PR will likely break that (ideally we'd test it explicitly). I think you can get the best of both if you find a way to write this as You can add GPU tests in the |
julia> function jacobian_with_fill(f, x::AbstractVector)
y::AbstractVector, back = forward(f, x)
function ȳ(i)
δ = fill!(similar(y, Bool), false)
δ[i] = true
return δ
end
vcat([transpose(back(ȳ(i))[1]) for i = 1:length(y)]...)
end
jacobian_with_fill (generic function with 1 method)
julia> Tracker.gradient(x -> sum(jacobian_with_fill(y -> y .^ 2, x) .^ 2), [1.0, 2.0, 3.0])
([8.0, 16.0, 24.0] (tracked),)
julia> Tracker.gradient(x -> sum(jacobian_with_fill(y -> sum(y) .* y, x) .^ 2), [1.0, 2.0, 3.0])
([66.0, 72.0, 78.0] (tracked),)
julia> function jacobian_with_bc(f, x::AbstractVector)
y::AbstractVector, back = forward(f, x)
ȳ(i) = ((j, _) -> i == j).(1:length(x), x)
vcat([transpose(back(ȳ(i))[1]) for i = 1:length(y)]...)
end
jacobian_with_bc (generic function with 1 method)
julia> Tracker.gradient(x -> sum(jacobian_with_bc(y -> y .^ 2, x) .^ 2), [1.0, 2.0, 3.0])
([8.0, 16.0, 24.0] (tracked),)
julia> Tracker.gradient(x -> sum(jacobian_with_bc(y -> sum(y) .* y, x) .^ 2), [1.0, 2.0, 3.0])
([66.0, 72.0, 78.0] (tracked),)
I don't see |
Of course, I always forget we split tracker out of Flux. In that case it'd still be nice to have a test on the Flux side once this is in. You are probably right that this can be done with the |
Thanks for the clarification. The latest commit in this PR uses broadcasting approach. So it's good to go?
|
I just found a related problem: z = float(zero(eltype(data(y))))
ȳ(i) = ((j, _) -> i == j).(1:length(y), y) .+ z Or should it be fixed in NNlib.jl? Edit: implemented in 9c2c05e |
It looks like the tests in Flux failed because of If these are the case, wouldn't it be better to use the |
@@ -173,7 +173,11 @@ Calculate the output jacobian `J = d/dx m(x)` such that each row `i` of `J` corr | |||
""" | |||
function jacobian(f, x::AbstractVector) | |||
y::AbstractVector, back = forward(f, x) | |||
ȳ(i) = [i == j for j = 1:length(y)] | |||
function ȳ(i) | |||
δ = fill!(float(similar(data(y))), false) |
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.
δ = false .* y .+ (1:length(y) .== i)
. Though you should then make it be color_i
and loop through colors for it to be sparse, but this is good for now.
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.
I'll open a fresh PR for this.
Closing in favor of #44 (thank you @ChrisRackauckas!) |
It looks like
Tracker.jacobian
does not support CuArrays at the moment:This is because
ȳ(i)
always returnVector{Bool}
:Tracker.jl/src/back.jl
Lines 174 to 178 in 593aba6
A fix I found (implemented in this PR) was to create the output array using
similar(y, Bool)
:I didn't added any tests (sorry) because Tracker's test suite does not load CuArrays.