Optimization 提高以下计算softmax导数的代码性能的提示
编辑:添加了函数标题Optimization 提高以下计算softmax导数的代码性能的提示,optimization,machine-learning,neural-network,julia,softmax,Optimization,Machine Learning,Neural Network,Julia,Softmax,编辑:添加了函数标题 function backward(l::SoftMax, DLDY::Array{Float64}; kwargs...) # credits: https://stats.stackexchange.com/questions/79454/softmax-layer-in-a-neural-network?newreg=d1e89b443dd346ae8bccaf038a944221 m,n =size(l.x) ly = Array{Floa
function backward(l::SoftMax, DLDY::Array{Float64}; kwargs...)
# credits: https://stats.stackexchange.com/questions/79454/softmax-layer-in-a-neural-network?newreg=d1e89b443dd346ae8bccaf038a944221
m,n =size(l.x)
ly = Array{Float64}(n)
for batch=1:m
ly = l.y[batch,:]
for i=1:n
li = ly[i]
l.jacobian[:,i] = -li * ly
l.jacobian[i,i] = li*(1-li)
end
# l.jacobian = ly'.*repmat(ly, 1, n)
# for i=1:n
# li = l.y[batch,i]
# l.jacobian[i,i] = li*(1.0-li)
# end
# # n x 1 = n x n * n x 1
l.dldx[batch,:] = l.jacobian * DLDY[batch,:]
end
return l.dldx
end
上面是我的softmax层向后函数的代码。本线程中的答案很好地描述了计算softmax导数的方法。在这里,我正在寻找一种更有效的方法来计算导数,因为上面的代码需要0.05~6
秒来计算1000 x 100,而之前的softmax+交叉熵组合层只需要0.002
秒
因此,我正在寻找一种使代码运行更快的方法。我不确定我是否使用了计算雅可比矩阵的最有效的方法,但我尝试了另一种方法,即我repmat(ly,1,n)
,然后用ly
进行点乘。结果更糟,因为显然julia的repmat
占用了太多的分配
本质上,我正在寻找一种有效的方法,将数组与数组中的每个元素相乘,并将结果合并成一个方阵。朱莉娅大师对此有什么想法吗?谢谢 在抱怨了可运行代码之后(抱怨仍然相关),我将尝试一个更具建设性的评论。更换回路:
for i=1:n
li = ly[i]
l.jacobian[:,i] = -li * ly
l.jacobian[i,i] = li*(1-li)
end
带(无需循环):
得到的l.jacobian
应该是相同的,而且效率更高
作为一种解释,使用的关键特性是:
broadcast
和diagind
如果问题中有运行缓慢的代码,那么回答有关速度的问题就容易多了。如果您添加可运行代码,响应通常很快。我不认为有办法在这里显示我的“可运行”代码,因为它比较庞大和复杂。除此之外,真正使代码变慢的部分实际上是向后调用函数
,这是我提出的问题。我相信我试图在功能上实现的应该是相对明显的,同时我也尽力用语言来描述。正如我在最初的帖子中所说,第二个循环I=1:n
花费的时间最多,也是我在这里发布代码进行优化的主要部分。如果你对我的代码有任何疑问,我也很乐意澄清。这确实让代码更快了!后退功能现在平均运行0.03
秒,几乎是前一个的两倍。现在我将寻找一种方法来取消batch1:m的外部循环,以使其更快!感谢您对使用=
操作提出的建设性建议!看来应该可以改进外环。如果您询问有关StackOverflow的另一个问题,并包含一个函数和几行代码以进行演示运行,您可以得到更快的响应,或者至少在投票方面得到更好的响应;)
l.jacobian .= -ly .* ly'
l.jacobian[diagind(jacobian)] .= ly.*(1.0.-ly)