BP神经网络基础理论
BP模型训练
【代码】梯度下降法求解BP的简单Demo代码
作者 : 老饼 日期 : 2022-06-13 02:57:45 更新 : 2022-11-02 13:02:48
本站原创文章,转载请说明来自《老饼讲解-BP神经网络》bp.bbbdata.com



本文展示一个梯度下降法求解BP神经网络的例子,包括思路、代码等,

通过本实例具体地学习和理解BP神经网络的训练过程



   问题    


现有如下数据: 

y实际是由 
生成
现在需要利用数据训练一个BP神经网络,对其进行拟合,
并测试网络的预测结果与真实结果 
 的差异




  01. BP神经网络建模思路  


整体的建模思路为,先设置一个BP神经网络结构,再采用梯度下降法进行训练


   设置BP神经网络结构   


对于本问题,
我们采用三层结构,其中隐层包含3个隐神经元,
隐层激活函数为tansig,输出层激活函数为purelin的结构
则对应的网络拓扑如下:
  
 对应的模型数学表达式为: 
 



   BP神经网络训练   


采用梯度下降法对BP神经网络进行训练,
 
算法流程如下:
 先初始化W,b,
(1) 按照梯度公式算出梯度
(2) 将W往负梯度方向调整
不断循环(1)和(2),直到达到终止条件(例如达到最大迭代次数,或误差足够小)




    三层BP神经网络梯度公式    


输出层梯度公式
输出层权重梯度:                                         
输出层阈值梯度:                                               
隐层梯度公式
隐层权重梯度:     
隐层阈值梯度:             
✍️符号说明
 为样本个数、输出个数                                               
是第m个样本第k个输出的误差        
是第m个样本第i个隐节点的激活值           
是第m个样本第i个输入                                                  





  02. 代码实现  


   代码实现   


下面是 梯度下降法 求解 BP神经网络 的代码实现
  matlab2014已新测跑通
close all;clear all;
%-----------数据----------------------
x1 = [-3,-2.7,-2.4,-2.1,-1.8,-1.5,-1.2,-0.9,-0.6,-0.3,0,0.3,0.6,0.9,1.2,1.5,1.8];% x1:x1 = -3:0.3:2;
x2 = [-2,-1.8,-1.6,-1.4,-1.2,-1,-0.8,-0.6,-0.4,-0.2,-2.2204,0.2,0.4,0.6,0.8,1,1.2]; % x2:x2 = -2:0.2:1.2;
X  = [x1;x2];      % 将x1,x2作为输入数据
y  = [0.6589,0.2206,-0.1635,-0.4712,-0.6858,-0.7975,-0.8040,...
    -0.7113,-0.5326,-0.2875 ,0.9860,0.3035,0.5966,0.8553,1.0600,1.1975,1.2618];    % y: y = sin(x1)+0.2*x2.*x2;

%--------参数设置与常量计算-------------
setdemorandstream(88);
hide_num = 3;
lr = 0.05;
[in_num,sample_num] = size(X);
[out_num,~] =  size(y);

%--------初始化w,b和预测结果-----------
w_ho = rand(out_num,hide_num);   % 隐层到输出层的权重 
b_o  = rand(out_num,1);          % 输出层阈值
w_ih = rand(hide_num,in_num);    % 输入层到隐层权重
b_h  = rand(hide_num,1);         % 隐层阈值
simy = w_ho*tansig(w_ih*X+repmat(b_h,1,size(X,2)))+repmat(b_o,1,size(X,2)); % 预测结果
mse_record = [sum(sum((simy - y ).^2))/(sample_num*out_num)];  % 预测误差记录

% ---------用梯度下降训练------------------
for i = 1:5000
    %计算梯度
    hide_Ac = tansig(w_ih*X+repmat(b_h,1,sample_num)); % 隐节点激活值
    dNo     = 2*(simy - y )/(sample_num*out_num);      % 输出层节点梯度
    dw_ho   = dNo*hide_Ac';                            % 隐层-输出层权重梯度
    db_o    = sum(dNo,2);                              % 输出层阈值梯度
    
    dNh     = (w_ho'*dNo).*(1-hide_Ac.^2);             % 隐层节点梯度
    dw_ih   = dNh*X';                                  % 输入层-隐层权重梯度
    db_h    = sum(dNh,2);                              % 隐层阈值梯度

    %往负梯度更新w,b
    w_ho = w_ho - lr*dw_ho;                            % 更新隐层-输出层权重 
    b_o  = b_o  - lr*db_o;                             % 更新输出层阈值
    w_ih = w_ih - lr*dw_ih;                            % 更新输入层-隐层权重 
    b_h  = b_h  - lr*db_h;                             % 更新隐层阈值
    
    % 计算网络预测结果与记录误差
    simy = w_ho*tansig(w_ih*X+repmat(b_h,1,size(X,2)))+repmat(b_o,1,size(X,2));
    mse_record =[mse_record, sum(sum((simy - y ).^2))/(sample_num*out_num)];
end

% -------------绘制训练结果与打印模型参数-----------------------------
h = figure;
subplot(1,2,1)
plot(mse_record)
subplot(1,2,2)
plot(1:sample_num,y);
hold on
plot(1:sample_num,simy,'-r');
set(h,'units','normalized','position',[0.1 0.1 0.8 0.5]);
%--模型参数--
w_ho   % 隐层到输出层的权重 
b_o    % 输出层阈值
w_ih   % 输入层到隐层权重
b_h    % 隐层阈值



  03. 代码运行结果  


运行上述代码,得到BP神经网络的训练误差曲线和网络的拟合结果,

并由训练好的系数,得到最终的BP神经网络表达式

 


    训练误差曲线和网络的拟合效果    





    训练好的BP神经网络    





  04. 检验模型效果  


下面测试构建好的BP神经网络的实际预测效果 


   BP神经网络的预测结果和真实结果    


不妨使用x =[0.5,0.5]进行测试, 
  BP神经网络的预测结果   
 
将 x =[0.5,0.5] 代入以上网络模型表达式
 
 
 得到BP神经网络的预测结果是0.6241
  真实结果   
 
将 x =[0.5,0.5] 代入真实的关系
     
 
可知真实结果为0.5294



  预测结果分析   


网络的预测值0.6241与真实值0.5294 误差0.0946。
这个误差不算太大,但也不算小。
  整体来说,训练的BP神经网络模型已具有一定的效果,说明算法是可行的。

 PASS:为什么训练数据这么好,而预测值仍然有这么大的差距?
读者们能想明白吗?能改善吗?要怎么才能改善?



特别声明:以上梯度下降法整个求解BP神经网络过程的实现,是非常粗糙的,仅是作为入门参考。






 End 




联系老饼