Проблема двойного вывода Julia Flux
Недавно я обнаружил, что Джулия Лэнг стала более сильной, и пришло время вернуться к ней снова. Но в каждом учебнике я обнаруживал одну и ту же проблему с двойным выводом - для каждой партии вам нужно рассчитать модель, чтобы получить градиенты, а затем пересчитать ее, чтобы получить потери и другие показатели. Это кажется смешным, и это должен быть выход. Могу ли я получить прогноз модели и ее потерю до этапа обновления градиентов без пересчета? Здесь я сделал пример для MLP и MNIST
using Flux, Flux.Data.MNIST, Statistics
using Flux: onehotbatch, onecold, crossentropy
using Flux.Optimise: update!
using Flux.Data: DataLoader
using Printf
X = hcat(float.(reshape.(MNIST.images(), :))...) |> gpu
Y = onehotbatch(MNIST.labels(), 0:9) |> gpu
m = Chain(
Dense(784, 32, relu),
Dense(32, 32, relu),
Dense(32, 10),
softmax
) |> gpu
loss(ŷ, y) = Flux.crossentropy(ŷ, y)
accuracy(x, y) = mean(onecold(cpu(x)) .== onecold(cpu(y)))
dl = DataLoader(X, Y, batchsize=128)
ps = params(m)
opt = Descent(0.1)
@progress for i = 1:10
@info "Epoch $i"
for (x, y) in dl
gs = gradient(ps) do
loss(m(x), y)
end
update!(opt, ps, gs)
end
vloss, vacc = [], []
for (x,y) in dl
ŷ = m(x)
l = loss(ŷ, y)
push!(vloss, l)
push!(vacc, accuracy(ŷ, y))
end
@printf "Train :: loss: %-5f acc: %-5f\n" mean(vloss) mean(vacc)
end
1 ответ
Кстати, AD в обратном режиме работает, вы в любом случае получаете обратно так называемое "прямое значение" каждый раз, когда вычисляете градиент. Если вы посмотрите, какgradient
определено в Zygote, вы видите, что вы можете использоватьpullback
чтобы получить и то, и другое одновременно:
function value_and_gradient(f, args...)
y, back = pullback(f, args...)
return y, back(sensitivity(y))
end
sensitivity
просто one
, или ошибка для недифференцируемых типов вывода.