我有一个简单的神经网络,它有一个隐藏层,softmax作为输出层的激活函数。隐藏层使用各种激活函数,因为我正在尽可能多地测试和实现它们。
对于目前的训练和测试,我使用的是手写数字的 MNIST 数据集,因此我的输入数据是一个矩阵,在每一行中都有不同的图像,在每一列中,该图像的一个像素已被重新整形为向量。
当我对两个层都使用sigmoid激活函数时,计算的梯度和分析梯度似乎一致,但是当我尝试其他方法时,例如隐藏层的tanh或softplus以及输出层的softmax,从数据中可以看出存在很大的差异下面(左->数值梯度,右->解析梯度)
(1)sigmoid (2)softmax
-9.4049e-04 -6.4143e-04
-6.2623e-05 -2.5895e-05
1.0676e-03 6.9474e-04
-2.0473e-03 -1.3471e-03
2.9846e-03 1.9716e-03
4.0945e-05 2.7627e-05
-2.5102e-05 -1.7017e-05
8.8054e-06 6.0967e-06
7.8509e-06 5.0682e-06
-2.4561e-05 -1.6270e-05
5.6108e-05 3.8449e-05
2.0690e-05 1.2590e-05
-9.7665e-05 -6.3771e-05
1.7235e-04 1.1345e-04
-2.4335e-04 -1.6071e-04
(1)tanh (2)softmax
-3.9826e-03 -2.7402e-03
4.6667e-05 1.1115e-04
3.9368e-03 2.5504e-03
-7.7824e-03 -5.1228e-03
1.1451e-02 7.5781e-03
1.5897e-04 1.0734e-04
-9.6886e-05 -6.5701e-05
3.3560e-05 2.3153e-05
3.3344e-05 2.1786e-05
-1.0282e-04 -6.8409e-05
2.1185e-04 1.4774e-04
9.0293e-05 5.3752e-05
-4.0012e-04 -2.6047e-04
6.9648e-04 4.5839e-04
-9.7518e-04 -6.4468e-04
(1)乙状结肠 (2)乙状结肠
-9.2783e-03 -9.2783e-03
8.8991e-03 8.8991e-03
-8.3601e-03 -8.3601e-03
7.6281e-03 7.6281e-03
-6.7480e-03 -6.7480e-03
-3.0498e-06 -3.0498e-06
1.4287e-05 1.4287e-05
-2.5938e-05 -2.5938e-05
3.6988e-05 3.6988e-05
-4.6876e-05 -4.6876e-05
-1.7506e-04 -1.7506e-04
2.3315e-04 2.3315e-04
-2.8747e-04 -2.8747e-04
3.3532e-04 3.3532e-04
-3.7622e-04 -3.7622e-04
-9.6266e-05 -9.6266e-05
我实现反向传播的方式如下:
变量->
Theta1 , Theta2:第一层和第二层具有不同权重的表格。
m :我的训练集的大小
y:每个输入样本具有正确类别的向量
Y:一个矩阵,每个输入样本的类别都有一个热编码
X :带有输入数据的矩阵,每一行是一个不同的训练样本
% Feedforward
a1 = [ones(m, 1) X];
z2 = a1*Theta1';
a2 = [ones(m, 1) activation(z2, activation_type)];
z3 = a2*Theta2';
a3 = activation(z3, 'softmax');
h = a3;
% Calculate J
J = sum(sum((-Y).*log(h) - (1-Y).*log(1-h), 2))/m + lambda*p/(2*m); # sigmoid
%J = -(sum(sum((Y).*log(h))) + lambda*p/(2*m)); # softmax
% Calculate sigmas
sigma3 = a3.-Y;
sigma2 = (sigma3*Theta2).*activationGradient([ones(m, 1) z2], 'sigmoid');
sigma2 = sigma2(:, 2:end);
% Accumulate gradients
delta_1 = (sigma2'*a1);
delta_2 = (sigma3'*a2);
第一个成本计算J是为sigmoid计算的,下面的一个是为softmax计算的(见评论),所以我在两者之间切换。
我在反向传播过程中是否遗漏了一些东西,为什么它在sigmoids中按预期工作,但在sofmax中没有按预期工作?