在机器学习中,如果想对非线性函数进行建模,深度前馈网络能够实现这一目标。
在深度学习中,使用一个简单函数的深度链来学习输入数据。
线性函数的输入函数:
非线性函数的输入函数:
其中:
\phi 是输入数据 x 的学习表征,h(x) 是激活函数。
深度前馈网络
在深度前馈网络的每一层(Layer),使用一个简单的线性函数 W^{(l)} x^{(l-1)} 和后面的激活函数 h(x) 来表示网络结构。
网络的整体结构:
在每层中:
每一层都会使用一个简单的线性函数及一个权重矩阵 W。
隐藏单元的激活函数 Activation Functions
h(\cdot) 是激活函数。
ReLU
Figure 1 ReLU
LReLU
Figure 2 Leaky ReLU
Sigmoid
Figure 3 Sigmoid
Tangent (tanh)
Figure 4 Tangent
输出单元
回归问题,是线性输出:
分类(class > 2)问题,是 Softmax 输出,Softmax 的输出用来预测各个分类的可能性:
深度前馈网络是一个具有非线性激活函数的线性函数链,有一个专门用于任务的输出层,即回归或分类。
Figure 5 深度前馈网络结构
反向传播 Back Propagation
反向传播又被称为 BP,允许来自 loss function 的信息通过网络向后流动,以便计算梯度(Gradient)。实际上是loss 反向传播。该方法对网络中所有权重计算损失函数的梯度,用来更新权重以最小化 loss。
符号约定:全文统一使用 w_{ji}^{(l)} 表示从第 l-1 层神经元 i 到第 l 层神经元 j 的权重。前向传播为 z_j^{(l)} = \sum_i w_{ji}^{(l)} x_i^{(l-1)},反向传播为 \delta_j^{(l)} = \sum_k w_{kj}^{(l+1)} \delta_k^{(l+1)} h'(z_j^{(l)})。
SGD
用下面的公式不断更新 w 的值:
这里的 L_n 是一个 sample 的 Loss。
Figure 6 Back Propagation
对于深度前馈网络,\delta_j^{(l)} x_i^{(l-1)} 就是 \frac{\partial L_n}{\partial w_{ji}^{(l)}}。
推导过程如下
首先回想起在每个单元,前馈输出 z^{(l)} = W^{(l)} x^{(l-1)}。
根据链式法则:
由上面两个公式可以得到:
根据上面的公式,SGD 可以更新:
现在只要求出 \delta_j^{(l)} 就可以得到 BP 的完整表达式:
对隐藏层,由链式法则递推:
推导如下。第 l+1 层的前馈计算为 z_k^{(l+1)} = \sum_j w_{kj}^{(l+1)} x_j^{(l)},其中 x_j^{(l)} = h(z_j^{(l)}),因此:
代入链式法则即得上式。
反向传播算法
-
正向传播,估计 \forall l:
z_j^{(l)} = \sum_i w_{ji}^{(l)} x_i^{(l-1)}x_j^{(l)} = h\!\left(z_j^{(l)}\right) -
初始化 \delta^{(M)}:
\delta_j^{(M)} = \frac{\partial L_n}{\partial \hat{y}_j} f'\!\left(z_j^{(M)}\right)具体形式取决于输出层与损失函数的组合:
- MSE 回归 + 线性输出:\delta_j^{(M)} = \hat{y}_j - y_j
- Softmax + 交叉熵:\delta_j^{(M)} = \hat{y}_j - y_j,其中 y_j 为 one-hot 标签
- Sigmoid + 二元交叉熵:\delta_j^{(M)} = \hat{y}_j - y_j
后两种情形形式与 MSE 相同,但推导前提不同,不能混用损失函数。
-
反向传播,每层都计算一次:
\delta_j^{(l)} = \sum_k w_{kj}^{(l+1)} \delta_k^{(l+1)} h'\!\left(z_j^{(l)}\right) -
梯度:
\frac{\partial L_n}{\partial w_{ji}^{(l)}} = \delta_j^{(l)} x_i^{(l-1)}假设 \frac{\partial L_n}{\partial w_{ji}^{(l)}} 为 G,接下来在每层,w 会更新:
w^{(l)} = w^{(l)} - \epsilon G
maxIter = m;
for epoch = 1:maxEpochs % loop over number of epochs
loss = [];
for iter = 1:m % loop over all data samples
%% 1. forward propagation
net(1).x = x(r(iter)); % extract random input
for l = 2:M % loop over each layer
net(l).z = net(l).W*[1; net(l-1).x]; % weight & bias
net(l).x = max(net(l).z,0); % ReLU activation
end
net(M).yhat = net(M).z; % output activation
%% 2. initialise delta
net(M).delta = (net(M).yhat-y(r(iter)));
%% 3. backpropagation through all network layers
for l = M:-1:3
net(l-1).delta = net(l).W(:,2:end)'*net(l).delta.*(1.*(net(l-1).z>0));
end
%% 4. define loss function gradient
for l = 2:1:M
net(l).grad = [net(l).delta net(l).delta*net(l-1).x']; % additional layers
end
%% update parameters using SGD
for l = 2:M
G = net(l).grad; % error gradient matrix
net(l).W = net(l).W - epsilon.*G; % SGD update rule
end
%% plot results: evaluate and plot loss
for i = 1:m % forward propagate all data
net(1).x = x(i); % extract data input sample
for l = 2:M % loop over network layers
net(l).z=net(l).W*[1;net(l-1).x]; % weight and bias
net(l).x=max(net(l).z,0); % ReLU activation
end
net(M).yhat=net(M).z; % output
Yhat(i) = net(M).yhat; % store output
end
loss(iter) = sum((Yhat - y).^2); % evaluate loss
figure(101);subplot(1,2,1); cla; plot(loss); xlabel('Iteration'); ylabel('Loss');
title(['(a) Loss (Epoch: ' num2str(epoch) ')']); xlim([0 maxIter]);
subplot(1,2,2); cla; plot(x,y,'.'); hold on; plot(x,Yhat);
xlabel('x'); ylabel('y'); title('(b) Model Fit'); drawnow;
end
end
评论