python - 反向传播的扩展

标签 python matlab machine-learning neural-network backpropagation

我正在跟踪nn和反向传播上的this tutorial
我是python新手,我正在尝试将代码转换成matlab。
有人能解释一下下面的代码行吗(来自教程):

delta3[range(num_examples), y] -= 1

简而言之,如果我没有弄错的话,delta3y是向量,num_examples是整数。
我的理解是,delta3=probs-ythis math exchange entry一样(谢谢@rayryeng)。为什么和什么时候我应该减去1?
否则,有谁能指引我到一个我可以简单运行并遵循代码的在线站点?我试图运行的所有地方(包括我的家用电脑)都出现错误:
“nameerror:未定义名称'sklearn'(可能缺少导入)

最佳答案

这一行:delta3[range(num_examples), y] -= 1是计算softmax损耗函数梯度的一部分。我给你们介绍这个很好的链接,给你们更多的信息,关于这个损失函数是如何形成的,以及它背后的直觉:http://peterroelants.github.io/posts/neural_network_implementation_intermezzo02/
另外,我给你介绍了数学堆栈交换的这篇文章,它向你展示了如何导出SoftMax损耗的梯度:https://math.stackexchange.com/questions/945871/derivative-of-softmax-loss-function。将第一个链接视为一个深潜水,而第二个链接是第一个链接的tl;dr
SoftMax损耗函数的梯度是输出层的梯度,您需要将其向后传播到输出层之前的层才能继续反向传播算法。
总结我在上面链接的帖子,如果你为一个训练示例计算softmax损失的梯度,那么对于每个类,损失的梯度就是为该类计算的softmax值对于实际训练示例所属的类,还需要将损失值减去1记住,类i的示例的梯度等于p_i - y_i,其中p_i是该示例的类i的softmax得分,y_i是使用一个热编码方案的分类标签。具体来说,如果y_i = 0不是示例的真正类,则为i,如果是,则为y_i = 1delta3包含小批量中每个示例的softmax loss函数的梯度。具体来说,它是一个2d矩阵,其中行的总数等于训练示例的数目,或者num_examples,而列的数目是类的总数。
首先,我们计算每个训练示例和每个类的softmax分数。接下来,对于渐变的每一行,我们确定对应于示例所属的真实类的列位置,然后将分数减去1。range(num_examples)将生成一个从0num_examples - 1的列表,y包含每个示例的真正类标签。因此,对于每一对range(num_examples)y,它访问要减去1的右行和列位置,以确定损失函数的梯度。
现在在数学堆栈交换帖子以及你的理解中,梯度是delta3 = probs - y。这假设y是一个单热编码矩阵,这意味着y的大小与probs相同,并且对于y的每一行,除了包含正确类的列索引(设置为1)之外,它都为零。因此,如果您考虑正确,如果您生成了一个矩阵y,其中除了示例所属的类号之外,每一行的列都为零,这相当于简单地访问每一行的右列,然后将分数减去1。
在Matlab中,您实际上需要创建线性索引,以便简化此减法。具体来说,您需要使用sub2ind将这些行和列位置转换为线性索引,然后我们可以访问渐变矩阵并将值减去1。
因此:

ind = sub2ind(size(delta3), 1 : num_examples, y + 1);
delta3(ind) = delta3(ind) - 1;

在您链接的python教程中,假定类标签从0N-1,其中N是类的总数。在Matlab中,我们必须小心地从1开始索引数组,所以我在上面的代码中添加了1y,以确保您的标签开始在1而不是0ind包含我们需要访问的行和列位置的线性索引,因此我们使用这些索引完成减法。
如果你要用你从编辑中获得的知识来表述这一点,你可以这样做:
ymatrix = full(sparse(1 : num_examples, y + 1, 1, size(delta3, 1), size(delta3, 2));
delta3 = probs - ymatrix;

ymatrix包含我讨论过的矩阵,其中每一行对应一个示例,除了与该示例所属的类(即1)相关的列之外,其他列都为零。您以前可能没有见过的是sparsefull函数sparse允许您创建一个零矩阵,您可以指定非零的行和列位置以及这些位置中每个位置的值。在本例中,我正是每行访问一个元素,并使用示例中的类ID来访问列,并将这些位置中的每一个设置为1还要记住,假设类id从0开始,我将添加1。因为这是一个sparse矩阵,所以我把它转换成full来给你一个数值矩阵,而不是用sparse的形式来表示它。因此,此代码在操作上与我显示的前一个代码段等效。但是,第一种方法更有效,因为不需要创建额外的矩阵来方便梯度计算而是就地修改渐变。
另请注意,sklearn是python机器学习包,NameError是指没有安装实际的包。要安装它,请使用scikit-learnpip将Python包安装到您的计算机所以在命令行中,它很简单:
pip install sklearn

或:
easy_install sklearn

但是,运行上述减法代码不需要scikit learn。但您确实需要easy_install,因此请确保安装了该软件包。
对于pip
pip install numpy

…对于easy_install
easy_install numpy

关于python - 反向传播的扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41653482/

相关文章:

algorithm - 如何解决机器学习挑战?

python - 从提供者列表中的单个结果中抓取数据

python - 在 Tornado 应用程序中将阻塞功能卸载到执行程序的通用解决方案

matlab - 获取一条线的像素 - :- MATLAB

基于第三个参数的matlab绘图标记

python - 在高性能环境中的 fork 工作进程之间共享状态

python更改启动/默认目录

python - Pandas 多个条件下行之间的差异

matlab - 你如何在matlab中格式化文本输出的复数

matlab - 如何将K-mean算法应用于多维数组?