Closed zsteve closed 3 years ago
Unfortunately I can't reproduce the issue (I don't know f_primal
). The solution is to not to remove the in-place assignments but to fix the initializations of the variables - I've already noticed that they are not correct since both the element types and containers can be wrong. I think I already fixed this in my local branch, so it would be interesting if you can post a full example that allows to reproduce the issue.
I added some of the changes that I wanted to make (performance can be improved a bit more, so it's not complete yet) to the dw/sinkhorn_gibbs
branch: https://github.com/JuliaOptimalTransport/OptimalTransport.jl/tree/dw/sinkhorn_gibbs
You can check if this fixes your problem above. You can install the branch with
julia> ] add OptimalTransport#dw/sinkhorn_gibbs
Unfortunately I can't reproduce the issue (I don't know f_primal). The solution is to not to remove the in-place assignments but to fix the initializations of the variables - I've already noticed that they are not correct since both the element types and containers can be wrong. I think I already fixed this in my local branch, so it would be interesting if you can post a full example that allows to reproduce the issue.
Yep, sorry for the slow response. I was under the impression that I was making some 'rookie mistake' with trying to do autodiff, but after reading the above, you are right! the problem results from u
and v
being initialised to have types derived from mu
, I believe
The issue arises because in the case I posted, I wanted to differentiate in nu
. The problem then is that typeof(u) = Vector{Float64}
, but we need to be able to compute gradients in u
and v
.
I added some of the changes that I wanted to make (performance can be improved a bit more, so it's not complete yet) to the dw/sinkhorn_gibbs branch: https://github.com/JuliaOptimalTransport/OptimalTransport.jl/tree/dw/sinkhorn_gibbs You can check if this fixes your problem above. You can install the branch with julia> ] add OptimalTransport#dw/sinkhorn_gibbs
Yes, thanks for fixing this! It is working now. For reference here is the full code I was trying to run
Here is a working example:
using OptimalTransport, PythonOT
using StatsBase, Distances
using ReverseDiff, Optim, LinearAlgebra
using PyPlot
using BenchmarkTools
using LogExpFunctions
ot_smooth_primal(α, β, C, ε; iter = 50) = OptimalTransport.sinkhorn2(α, β, C, ε; regularization = true, maxiter = iter)
gaussian(x, σ) = @. exp(-x^2/σ^2)
support = LinRange(-1, 1, 64)
μ0 = @. gaussian(support - 0.5, 0.1) + gaussian(support + 0.5, 0.1)
μ0 = μ0/sum(μ0)
μ1 = @. 0.5*gaussian(support - 0.25, 0.1) + 0.5*gaussian(support + 0.25, 0.1)
μ1 = μ1/sum(μ1)
ε = 0.01
C = pairwise(SqEuclidean(), support')
K = @. exp(-C/ε)
f_primal(μ, ε, C, f) = f*ot_smooth_primal(μ0, μ, C, ε; iter = 100) + (1.0-f)*ot_smooth_primal(μ1, μ, C, ε; iter = 100)
interp_frac = 0.5
opt_primal = optimize(u -> f_primal(softmax(u), ε, C, interp_frac), zeros(size(μ0)), LBFGS(), Optim.Options(store_trace = true, show_trace = true, iterations = 250); autodiff = :forward)
α_opt_primal = softmax(Optim.minimizer(opt_primal))
plot(support, α_opt_primal)
I'm currently trying to autodiff through
sinkhorn2
via Optim.jl, but I'm running into the following error:The relevant code appears to be OptimalTransport.jl:194:
I'm not sure why 194 causes this issue. I tried looking at the types of u, tmp1 and tmp2:
[ Info: (Matrix{Float64}, Matrix{ForwardDiff.Dual{ForwardDiff.Tag{var"#4#5", Float64}, Float64, 11}}, Matrix{Float64})
So it appears that the in-place assignment here is resulting in a type incompatibility. I suppose this could be mitigated by avoiding explicit in place assignments?