反向传播的缩放
Scaling of backpropagation
我正在关注 this tutorial 神经网络和反向传播。
我是 python 的新手,我正在尝试将代码转换为 MATLAB。
有人可以解释以下代码行(来自教程):
delta3[range(num_examples), y] -= 1
简而言之,如果我没记错的话,delta3
和 y
是向量,num_examples
是整数。
Ii 是我对 delta3=probs-y
和 this math exchange entry 的理解(谢谢 @rayryeng)。为什么以及什么时候应该减去 1?
否则任何人都可以将我引导到一个在线站点,我可以简单地 运行 并按照代码进行操作吗?我到处都遇到错误 运行(包括我的家用电脑):
"NameError: name 'sklearn' is not defined"(可能是我遗漏的导入)
这一行:delta3[range(num_examples), y] -= 1
是计算softmax损失函数梯度的一部分。我建议您参考这个不错的 link,它为您提供了有关如何制定此损失函数及其背后直觉的更多信息:http://peterroelants.github.io/posts/neural_network_implementation_intermezzo02/.
此外,我建议您参考 Mathematics Stack Exchange 上的这个 post,它向您展示了如何导出 softmax 损失的梯度:https://math.stackexchange.com/questions/945871/derivative-of-softmax-loss-function。将第一个 link 视为深度潜水,而第二个 link 是第一个 link 的 tl;dr
。
softmax 损失函数的梯度是输出层的梯度,您需要向后传播到输出层之前的层以继续反向传播算法。
总结 post 我在上面 linked,如果你计算训练样本的 softmax 损失的梯度,对于每个 class 损失的梯度很简单为 class 评估的 softmax 值。您还需要将实际训练示例所属的 class 的损失值减去 1。请记住 class i
的示例梯度等于 p_i - y_i
其中 p_i
是 class i
的 softmax 分数例如,y_i
是使用 one-hot 编码方案的 classification 标签。具体来说 y_i = 0
如果 i
不是示例的真实 class,如果是 y_i = 1
。 delta3
包含 mini-batch 中每个示例的 softmax 损失函数的梯度。具体来说,它是一个二维矩阵,其中总行数等于训练示例数,即 num_examples
,而列数等于 classes 的总数。
首先,我们计算每个训练示例和每个 class 的 softmax 分数。接下来,对于梯度的每一行,我们确定对应于该示例所属的真实 class 的列位置,并将分数减去 1。range(num_examples)
将从 0
生成一个列表每个示例最多 num_examples - 1
和 y
包含真实的 class 标签。因此,对于每一对range(num_examples)
和y
,这里访问右边的行列位置减1,最终确定损失函数的梯度。
现在数学栈交换post以及你的理解,梯度是delta3 = probs - y
。这假设 y
是一个 one-hot 编码矩阵 ,这意味着 y
与 probs
具有相同的大小并且对于每一行y
它全为零 除了 包含正确 class 的列索引被设置为 1。因此,如果您考虑正确,如果您生成一个矩阵 y
,其中除了示例所属的 class 数字外,每一行的列都为零,它等效于简单地访问每一行的右列并将分数减去 1。
在 MATLAB 中,您实际上需要创建线性索引以便于执行此减法。具体来说,需要使用sub2ind
将这些行和列位置转换为线性索引,然后我们可以访问梯度矩阵并将值减1。
因此:
ind = sub2ind(size(delta3), 1 : num_examples, y + 1);
delta3(ind) = delta3(ind) - 1;
在您 link 编辑的 Python 教程中,假定 class 标签从 0
到 N-1
,其中 N
是 class 的总数。在 MATLAB 中你必须小心,我们从 1
开始索引数组,所以我在上面的代码中添加了 1
到 y
以确保你的标签从 1
开始而不是 0
。 ind
包含我们需要访问的行和列位置的线性索引,因此我们使用这些索引完成减法。
如果您要使用从编辑中获得的知识来制定这个,您会这样做:
ymatrix = full(sparse(1 : num_examples, y + 1, 1, size(delta3, 1), size(delta3, 2));
delta3 = probs - ymatrix;
ymatrix
包含我谈到的矩阵,其中每一行对应一个全为零的示例,但属于示例所属的 class 的列除外,即 1。什么你以前可能没见过的是 sparse
and full
函数。 sparse
允许您创建一个零矩阵,您可以指定 non-zero 的行和列位置以及每个位置所采用的值。在这种情况下,我准确地每行访问一个元素,并使用示例中的 class ID 来访问列并将这些位置中的每一个设置为 1。还请记住,我在添加 1 时m 假设你的 class ID 从 0 开始。因为这是一个 sparse
矩阵,我然后将其转换为 full
给你一个数字矩阵而不是用 sparse
表示它形式。因此,这段代码在操作上等同于我之前展示的代码片段。但是,第一种方法效率更高,因为您不会创建额外的矩阵来促进梯度计算。您正在就地修改渐变。
作为旁注,sklearn
是 scikit-learn Python machine learning package, and the NameError
is in reference to you not having the actual package installed. To install it, use pip
or easy_install
用于将 Python 软件包安装到您的计算机....所以在您的命令 l没关系,就这么简单:
pip install sklearn
或:
easy_install sklearn
不过,scikit-learn应该不需要你运行上面的减法代码。不过您确实需要 NumPy,因此请确保您已安装该软件包。
对于pip
:
pip install numpy
... 对于 easy_install
:
easy_install numpy
我正在关注 this tutorial 神经网络和反向传播。
我是 python 的新手,我正在尝试将代码转换为 MATLAB。 有人可以解释以下代码行(来自教程):
delta3[range(num_examples), y] -= 1
简而言之,如果我没记错的话,delta3
和 y
是向量,num_examples
是整数。
Ii 是我对 delta3=probs-y
和 this math exchange entry 的理解(谢谢 @rayryeng)。为什么以及什么时候应该减去 1?
否则任何人都可以将我引导到一个在线站点,我可以简单地 运行 并按照代码进行操作吗?我到处都遇到错误 运行(包括我的家用电脑):
"NameError: name 'sklearn' is not defined"(可能是我遗漏的导入)
这一行:delta3[range(num_examples), y] -= 1
是计算softmax损失函数梯度的一部分。我建议您参考这个不错的 link,它为您提供了有关如何制定此损失函数及其背后直觉的更多信息:http://peterroelants.github.io/posts/neural_network_implementation_intermezzo02/.
此外,我建议您参考 Mathematics Stack Exchange 上的这个 post,它向您展示了如何导出 softmax 损失的梯度:https://math.stackexchange.com/questions/945871/derivative-of-softmax-loss-function。将第一个 link 视为深度潜水,而第二个 link 是第一个 link 的 tl;dr
。
softmax 损失函数的梯度是输出层的梯度,您需要向后传播到输出层之前的层以继续反向传播算法。
总结 post 我在上面 linked,如果你计算训练样本的 softmax 损失的梯度,对于每个 class 损失的梯度很简单为 class 评估的 softmax 值。您还需要将实际训练示例所属的 class 的损失值减去 1。请记住 class i
的示例梯度等于 p_i - y_i
其中 p_i
是 class i
的 softmax 分数例如,y_i
是使用 one-hot 编码方案的 classification 标签。具体来说 y_i = 0
如果 i
不是示例的真实 class,如果是 y_i = 1
。 delta3
包含 mini-batch 中每个示例的 softmax 损失函数的梯度。具体来说,它是一个二维矩阵,其中总行数等于训练示例数,即 num_examples
,而列数等于 classes 的总数。
首先,我们计算每个训练示例和每个 class 的 softmax 分数。接下来,对于梯度的每一行,我们确定对应于该示例所属的真实 class 的列位置,并将分数减去 1。range(num_examples)
将从 0
生成一个列表每个示例最多 num_examples - 1
和 y
包含真实的 class 标签。因此,对于每一对range(num_examples)
和y
,这里访问右边的行列位置减1,最终确定损失函数的梯度。
现在数学栈交换post以及你的理解,梯度是delta3 = probs - y
。这假设 y
是一个 one-hot 编码矩阵 ,这意味着 y
与 probs
具有相同的大小并且对于每一行y
它全为零 除了 包含正确 class 的列索引被设置为 1。因此,如果您考虑正确,如果您生成一个矩阵 y
,其中除了示例所属的 class 数字外,每一行的列都为零,它等效于简单地访问每一行的右列并将分数减去 1。
在 MATLAB 中,您实际上需要创建线性索引以便于执行此减法。具体来说,需要使用sub2ind
将这些行和列位置转换为线性索引,然后我们可以访问梯度矩阵并将值减1。
因此:
ind = sub2ind(size(delta3), 1 : num_examples, y + 1);
delta3(ind) = delta3(ind) - 1;
在您 link 编辑的 Python 教程中,假定 class 标签从 0
到 N-1
,其中 N
是 class 的总数。在 MATLAB 中你必须小心,我们从 1
开始索引数组,所以我在上面的代码中添加了 1
到 y
以确保你的标签从 1
开始而不是 0
。 ind
包含我们需要访问的行和列位置的线性索引,因此我们使用这些索引完成减法。
如果您要使用从编辑中获得的知识来制定这个,您会这样做:
ymatrix = full(sparse(1 : num_examples, y + 1, 1, size(delta3, 1), size(delta3, 2));
delta3 = probs - ymatrix;
ymatrix
包含我谈到的矩阵,其中每一行对应一个全为零的示例,但属于示例所属的 class 的列除外,即 1。什么你以前可能没见过的是 sparse
and full
函数。 sparse
允许您创建一个零矩阵,您可以指定 non-zero 的行和列位置以及每个位置所采用的值。在这种情况下,我准确地每行访问一个元素,并使用示例中的 class ID 来访问列并将这些位置中的每一个设置为 1。还请记住,我在添加 1 时m 假设你的 class ID 从 0 开始。因为这是一个 sparse
矩阵,我然后将其转换为 full
给你一个数字矩阵而不是用 sparse
表示它形式。因此,这段代码在操作上等同于我之前展示的代码片段。但是,第一种方法效率更高,因为您不会创建额外的矩阵来促进梯度计算。您正在就地修改渐变。
作为旁注,sklearn
是 scikit-learn Python machine learning package, and the NameError
is in reference to you not having the actual package installed. To install it, use pip
or easy_install
用于将 Python 软件包安装到您的计算机....所以在您的命令 l没关系,就这么简单:
pip install sklearn
或:
easy_install sklearn
不过,scikit-learn应该不需要你运行上面的减法代码。不过您确实需要 NumPy,因此请确保您已安装该软件包。
对于pip
:
pip install numpy
... 对于 easy_install
:
easy_install numpy