### 反向传播的缩放

我正在按照这个教程学习神经网络和反向传播。

我是Python新手,正在尝试将代码转换为MATLAB。有人可以解释一下教程中的以下代码行吗:

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

简而言之,如果我没记错的话,delta3y是向量,而num_examples是一个整数。

据我理解,delta3=probs-y,如这个数学交换条目中所述(感谢@隐藏人名)。为什么以及何时我应该减去1?

否则,有人能指引我到一个可以简单运行和跟随代码的在线网站吗?我在尝试运行的每个地方都遇到了错误(包括我的家用电脑):

“NameError: name ‘sklearn’ is not defined”(可能是我缺少的导入)


回答:

这一行:delta3[range(num_examples), y] -= 1是计算softmax损失函数梯度的一部分。我推荐你查看这个链接,它提供了更多关于这个损失函数如何构建以及背后的直觉的信息:http://peterroelants.github.io/posts/neural_network_implementation_intermezzo02/

此外,我推荐你查看Mathematics Stack Exchange上的这个帖子,它展示了如何推导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是使用独热编码方案的分类标签。具体来说,如果i不是示例的真实类别,则y_i = 0,如果是,则y_i = 1delta3包含你小批量中每个示例的softmax损失函数的梯度。具体来说,它是一个二维矩阵,其中总行数等于训练示例的数量,或num_examples,而列数是类别的总数。

首先,我们计算每个训练示例和每个类别的softmax分数。接下来,对于梯度的每一行,我们确定对应于示例所属的真实类别的列位置,并将分数减去1。range(num_examples)将生成从0num_examples - 1的列表,而y包含每个示例的真实类别标签。因此,对于range(num_examples)y的每一对,这将访问正确的行和列位置,以减去1来完成损失函数的梯度计算。

现在,在Mathematics Stack Exchange的帖子以及你的理解中,梯度是delta3 = probs - y。这假设y是一个独热编码矩阵,意思是yprobs大小相同,并且对于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开始索引数组,所以我在上面的代码中对y加了1,以确保你的标签从1而不是0开始。ind包含我们需要访问的行和列位置的线性索引,我们因此使用这些索引完成减法运算。

如果你使用你编辑中获得的知识来表述这个,你会这样做:

ymatrix = full(sparse(1 : num_examples, y + 1, 1, size(delta3, 1), size(delta3, 2));delta3 = probs - ymatrix;

ymatrix包含我提到过的矩阵,其中每一行对应一个示例,所有的值都是零,除了与示例所属的类别相关的列,该列是1。你可能之前没有见过sparsefull函数。sparse允许你创建一个零矩阵,你可以指定非零的行和列位置以及这些位置的取值。在这种情况下,我准确地访问每一行的单个元素,并使用示例的类别ID来访问列,并将这些位置设置为1。还要记住,我加了1,因为我假设你的类别ID从0开始。因为这是一个sparse矩阵,我然后将其转换为full,以给你一个数字矩阵而不是以sparse形式表示。因此,这段代码在操作上与我之前展示的代码片段等效。然而,第一种方法更有效,因为你没有创建额外的矩阵来促进梯度计算。你是在原地修改梯度。


作为一个旁注,sklearnscikit-learnPython机器学习包,而NameError是指你没有安装实际的包。要安装它,使用pipeasy_install来安装Python包到你的电脑上…所以在你的命令行中,操作非常简单:

pip install sklearn

或者:

easy_install sklearn

然而,运行上述减法代码不需要scikit-learn。你确实需要NumPy,所以请确保你安装了这个包。

对于pip

pip install numpy

…对于easy_install

easy_install numpy

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注