神经网络:连续输出变量的 Sigmoid 激活函数

Posted

技术标签:

【中文标题】神经网络:连续输出变量的 Sigmoid 激活函数【英文标题】:Neural Networks: Sigmoid Activation Function for continuous output variable 【发布时间】:2014-01-06 01:22:40 【问题描述】:

好的,所以我在 Andrew Ng's machine learning course on coursera 的中间,并且想要调整作为作业 4 的一部分完成的神经网络。

特别是,我作为作业的一部分正确完成的神经网络如下:

Sigmoid 激活函数:g(z) = 1/(1+e^(-z)) 10 个输出单元,每个单元可以取 0 或 1 1 个隐藏层 用于最小化成本函数的反向传播方法 成本函数:

在哪里L=number of layerss_l = number of units in layer lm = number of training examplesK = number of output units

现在我想调整练习,以便有一个连续输出单元可以取 [0,1] 之间的任何值,我正在尝试找出需要更改的内容,到目前为止我有

将数据替换为我自己的数据,即输出是 0 到 1 之间的连续变量 更新了对输出单元数量的引用 将反向传播算法中的成本函数更新为: 其中a_3 是前向传播确定的输出单元的值。

我确信其他一些东西必须改变,因为梯度检查方法显示了由反向传播确定的梯度,而数值近似值不再匹配。我没有改变 sigmoid 梯度;它留在f(z)*(1-f(z)),其中f(z) 是sigmoid 函数1/(1+e^(-z))),我也没有更新导数公式的数值近似;只需(J(theta+e) - J(theta-e))/(2e)

谁能告知还需要哪些其他步骤?

在matlab中编码如下:

% FORWARD PROPAGATION
% input layer
a1 = [ones(m,1),X];
% hidden layer
z2 = a1*Theta1';
a2 = sigmoid(z2);
a2 = [ones(m,1),a2];
% output layer
z3 = a2*Theta2';
a3 = sigmoid(z3);

% BACKWARD PROPAGATION
delta3 = a3 - y;
delta2 = delta3*Theta2(:,2:end).*sigmoidGradient(z2);
Theta1_grad = (delta2'*a1)/m;
Theta2_grad = (delta3'*a2)/m;

% COST FUNCTION
J = 1/(2 * m) * sum( (a3-y).^2 );

% Implement regularization with the cost function and gradients.
Theta1_grad(:,2:end) = Theta1_grad(:,2:end) + Theta1(:,2:end)*lambda/m;
Theta2_grad(:,2:end) = Theta2_grad(:,2:end) + Theta2(:,2:end)*lambda/m;
J = J + lambda/(2*m)*( sum(sum(Theta1(:,2:end).^2)) + sum(sum(Theta2(:,2:end).^2)));

我已经意识到这个问题与@Mikhail Erofeev on *** 提出的问题相似,但是在这种情况下,我希望连续变量介于 0 和 1 之间,因此使用 sigmoid 函数。

【问题讨论】:

您是否成功地实现了持续的结果?我让它运行,但它在第 40 次迭代左右停止并且没有产生好的结果。如果你能分享你最终得到的东西会很棒吗? 【参考方案1】:

首先,您的成本函数应该是:

J = 1/m * sum( (a3-y).^2 );

我认为您的 Theta2_grad = (delta3'*a2)/m; 预计将与更改为 delta3 = 1/2 * (a3 - y); 后的数值近似值匹配)。

查看slide了解更多详情。

编辑: 如果我们的代码之间存在一些细微的差异,我将我的代码粘贴在下面供您参考。该代码已经与数值逼近函数checkNNGradients(lambda);进行了比较,相对差异小于1e-4(虽然不符合Andrew Ng博士的1e-11要求)

function [J grad] = nnCostFunctionRegression(nn_params, ...
                                   input_layer_size, ...
                                   hidden_layer_size, ...
                                   num_labels, ...
                                   X, y, lambda)

Theta1 = reshape(nn_params(1:hidden_layer_size * (input_layer_size + 1)), ...
                 hidden_layer_size, (input_layer_size + 1));

Theta2 = reshape(nn_params((1 + (hidden_layer_size * (input_layer_size + 1))):end), ...
                 num_labels, (hidden_layer_size + 1));

m = size(X, 1);   
J = 0;
Theta1_grad = zeros(size(Theta1));
Theta2_grad = zeros(size(Theta2));


X = [ones(m, 1) X];   
z1 = sigmoid(X * Theta1');
zs = z1;
z1 = [ones(m, 1) z1];
z2 = z1 * Theta2';
ht = sigmoid(z2);


y_recode = zeros(length(y),num_labels);
for i=1:length(y)
    y_recode(i,y(i))=1;
end    
y = y_recode;


regularization=lambda/2/m*(sum(sum(Theta1(:,2:end).^2))+sum(sum(Theta2(:,2:end).^2)));
J=1/(m)*sum(sum((ht - y).^2))+regularization;
delta_3 = 1/2*(ht - y);
delta_2 = delta_3 * Theta2(:,2:end) .* sigmoidGradient(X * Theta1');

delta_cap2 = delta_3' * z1; 
delta_cap1 = delta_2' * X;

Theta1_grad = ((1/m) * delta_cap1)+ ((lambda/m) * (Theta1));
Theta2_grad = ((1/m) * delta_cap2)+ ((lambda/m) * (Theta2));

Theta1_grad(:,1) = Theta1_grad(:,1)-((lambda/m) * (Theta1(:,1)));
Theta2_grad(:,1) = Theta2_grad(:,1)-((lambda/m) * (Theta2(:,1)));


grad = [Theta1_grad(:) ; Theta2_grad(:)];

end

【讨论】:

感谢您的建议;我尝试按照您的建议更新 delta3 和 delta2,但渐变仍然不匹配。 @user1420372 您的成本函数应该是 a3-y 而不是 sigmoid(a3)-y,请参阅我在回答中的更新。 谢谢!实际上我刚刚注意到 - 但是渐变仍然不正确 - 将编辑有问题的代码以修复。 我在答案中添加了我的代码供您参考。它与数值近似匹配,虽然相对差异为 1e-4,大于 1e-11 非常感谢您的帮助。我还意识到,通过保留练习中的成本函数,即使用对数,梯度匹配得很好,并且输出看起来像预测的(初步 - 仍在测试)。【参考方案2】:

如果要连续输出,计算目标值时尽量不要使用sigmoid激活。

a1 = [ones(m, 1) X];   
a2 = sigmoid(X * Theta1');  
a2 = [ones(m, 1) z1];  
a3 = z1 * Theta2';  
ht = a3;

在 nnCostFunction 中使用之前标准化输入。其他一切都保持不变。

【讨论】:

以上是关于神经网络:连续输出变量的 Sigmoid 激活函数的主要内容,如果未能解决你的问题,请参考以下文章

激活函数 sigmoid、tanh、relu

sigmoid函数作用

神经网络为啥要用sigmoid函数?为啥要映射到0-1之间?求解释

神经网络为啥要用sigmoid函数?为啥要映射到0-1之间?求解释

激活函数总结

神经网络为什么要用sigmoid函数?为什么要映射到0-1之间?