在讲解之前,我们还是首先将基础知识回顾一下,因为我认为基础知识扎实了,才能更快的进步与理解相关的知识,从而可以在相关领域有所突破。1943年,[McCulloch and Pitts]提出了“M-P神经元模型”,如下图所示:
在这个模型中,神经元接受到来自n个其他神经元传递过来的输入信号,这些输入信号通过带权重的连接(connection)进行传递,神经元接收到的总输入值将与神经元的阈值进行比较,然后通过“激活函数”(activation function)处理以产生神经元的输出.
而下面采用的为实际常用的Sigmoid函数 s i g m o i d ( x ) = 1 1 + e − x sigmoid(x)=\frac{1}{1+e^{-x}} sigmoid(x)=1+e−x1作为激活函数.
对于下面的讲解,公式以及算法都是基于西瓜书的,所以大家可以先认真看一看西瓜书上关于这一小节的内容,这里主要讲解如何通过简单的示例更快的理解这个算法,首先给出了误差逆传播算法:
在后面的程序以及例子讲解过程中,需要结合上述算法进行认真分析,才能了解其中的原理.对于神经网络逆传播算法的推导就不在这里赘述了,因为推导相对容易,大家认真对书上公式结合自己的数学知识推导就可以了,主要是明确一些基本的输入量、输出量是什么,而不能只是一味的进行推导,而不懂基本参数的意义,这样是非常不利于学习的;BP算法是在给定训练集 D = ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . ( x m , y m ) , x i ∈ R d , y i ∈ R l D={(x_1,y_1),(x_2,y_2),...(x_m,y_m)},x_i \in R^d,y_i\in R^l D=(x1,y1),(x2,y2),...(xm,ym),xi∈Rd,yi∈Rl,即输入示例有 d d d个属性描述,输出 l l l维实值向量,下图给出了一个拥有 d d d个输入神经元、 l l l个输出神经元、 q q q个隐层神经元的多层前馈网络结构,其中输出层第 j j j个神经元的阈值用 θ j \theta_j θj表示,隐层第 h h h个神经元的阈值用 γ h \gamma_h γh表示,输入层第 i i i个神经元与隐层第 h h h个神经元之间的连接权为 ν i h \nu_{ih} νih,隐层第 h h h个神经元与输出层第 j j j个神经元之间的连接权为 ω h j \omega_{hj} ωhj.记隐层第 h h h个神经元接受到的输入为 α h = ∑ i = 1 d ν i h x i \alpha_h = \sum_{i=1}^d \nu_{ih}x_i αh=∑i=1dνihxi,输出层第 j j j个神经元接受到的输入为 β j = ∑ h = 1 q ω h j b h \beta_j = \sum_{h=1}^q \omega_{hj}b_h βj=∑h=1qωhjbh,其中 b h b_h bh为隐层第 h h h个神经元的输出.假设隐层和输出层神经元都使用sigmoid函数.
对于上述BP算法中需要用到的公式在下面简单罗列一下,方便按照算法和公式对程序进行编写:
(5.3) y ^ j k = f ( β j − θ j ) \hat{y}_j^k = f(\beta_j-\theta_j) \tag{5.3} y^jk=f(βj−θj)(5.3)
(5.10) g j = y ^ j k ( 1 − y ^ j k ) ( y j k − y ^ j k ) g_j = \hat{y}_j^k(1- \hat{y}_j^k)(y_j^k- \hat{y}_j^k) \tag{5.10} gj=y^jk(1−y^jk)(yjk−y^jk)(5.10)
(5.15) e h = b h ( 1 − b h ) ∑ j = 1 l ω h j g j e_h = b_h(1-b_h)\sum_{j=1}^l \omega_{hj}g_j \tag{5.15} eh=bh(1−bh)j=1∑lωhjgj(5.15)
(5.11) Δ ω h j = η g j b h \Delta\omega_{hj}=\eta g_jb_h \tag{5.11} Δωhj=ηgjbh(5.11)
(5.12) Δ θ j = − η g j \Delta\theta_j = -\eta g_j \tag{5.12} Δθj=−ηgj(5.12)
(5.13) Δ ν i h = η e h x i \Delta\nu_{ih}=\eta e_h x_i \tag{5.13} Δνih=ηehxi(5.13)
(5.14) Δ γ h = − η e h \Delta\gamma_h = -\eta e_h \tag{5.14} Δγh=−ηeh(5.14)
Example practise(实践):
好了准备工作差不多了,接下来就以单层隐层,输入层二层,输出层一层来进行数据的学习预测,示意图如下图所示:
相应的matlab代码如下所示:
function BP_network()
x = [0.35; 0.9]; % 输入的数据集
y_real=0.5;
eta = 0.1; % 学习率
num_iters = 1500;
% 在(0,1)范围内随机初始化网络中所有连接权和阈值
% Layers : Layer1 = 2 Layer2 = 2 Layer3 = 1
% 初始化连接权
layer1 = 2;
layer2 = 2;
layer3 = 1;
v_weight0 = reshape(rand(1,4),[2,2]);
w_weight0 = rand(2,1);
% 初始化阈值
y_threshold =reshape(rand(1,2),[2,1]);
theta_threshold = rand();
% repeat
for i=1:num_iters % 随机梯度下降算法
%根据当前参数和式(5.3)计算当前样本的输出yk
alpha_input = v_weight0*x; % 隐藏层第h个神经元接受到的输入值
x1 = alpha_input-y_threshold;
b_h = sigmoid_array(x1); % 隐藏层第h个神经元的输出
beta_j =b_h'* w_weight0; %输出层的输入值
x2 = beta_j-theta_threshold;
f_output = sigmoid_array(x2);
% 根据式子计算输出层神经元的梯度项g_j
g_j = f_output*(1-f_output)*(y_real-f_output);
% 根据式子计算隐藏层神经元的梯度项e_h
E_one = zeros(2,1);
e_h = b_h.*(E_one-b_h).*w_weight0'*g_j;
% 根据式子更新连接权delta_w_hj,delta_v_ih
delta_v_h = eta*e_h'.*x;
delta_w_h = eta*g_j*b_h;
v_weight0 = v_weight0 + delta_v_h;
w_weight0 = w_weight0 +delta_w_h;
%更新阈值 theta_j,gamma_h
delta_theta_j = -eta*g_j;
delta_y_h = -eta*e_h;
y_threshold = y_threshold+delta_y_h;
theta_threshold = theta_threshold+delta_theta_j;
number_iters(i) = i;
f_values(i) = f_output;
gamma_output(i) = theta_threshold;
end
plot(number_iters,gamma_output,'b','LineWidth',2);
xlabel('number of iterations')
ylabel('Threshold value in the output layer');
% ylim([0.48, 0.54])
end
% 计算输出值得矩阵
function sigarray = sigmoid_array(array)
number = size(array,1);
sigarray = zeros(number,1);
for i = 1:number
sigarray(i) = sigmoid(array(i));
end
end
% 神经元函数sigmoid函数
function sigf = sigmoid(x)
sigf = 1/(1+exp(-x));
end
结合上图和matlab程序简要说一下过程,因为对于上述程序的编写和实现完全是基于BP算法和梯度下降(gradient descent)策略进行迭代实现的:
相应的一次学习效果以及输出层的阈值随着迭代次数的变化如下图所示:
对于神经网络的学习还是多加强图、参数和过程的理解,举一反三,这样对于学习会大有裨益.