BP神经网络

【案例】使用逐步回归选择BP的入模变量

作者 : 老饼 发表日期 : 2022-11-23 03:49:24 更新日期 : 2024-12-06 12:17:29
本站原创文章,转载请说明来自《老饼讲解-BP神经网络》www.bbbdata.com



变量过多时,不仅会令BP神经网络易过于过拟合,同时也增加了模型的训练难度

而通过逐步回归选择变量可以有效地减少最终建模变量的个数,从而提高模型的精度与泛化能力

本文讲解如何使用逐步回归的方式来筛选BP神经网络的入模变量,以及示具体的代码实现





    01. 噪声变量对BP神经网络的影响   




本节展示在BP神经网络中添加噪声变量所带来的危害




      变量"过多"对BP神经网络的影响      


什么是变量过多
 
变量的信息越精准有效,那么越有利于建模,
但往往建模中会出现变量过多,建模中变量过多理解为两种场情:
👉1. 变量中包含了没有用的变量,例如噪声变量  
👉2. 变量之间存在严重的信息冗余                      
 变量过多对BP神经网络的危害
BP神经网络是一个极易过拟合的模型,在BP神经网络建模时,变量过多则会:
 一、增强模型的复杂度:                                                                                                     
由入输入变量更多,往往需要设置更多的隐节点,将增大模型的复杂度                   
 二、增加了模型的训练难度:                                                                                               
由于模型的解空间更大,求解难度增大,往往会降低模型的训练精度                       
 三、引起模型过拟合:                                                                                                        
                 由于输入变量过多,会使模型更容易过拟合,在同样的训练误差下,模型的测试误差往往会更高
 特别是噪声变量,每个噪声变量可能会降低训练数据的误差,但这些贡献只是一种错觉,在测试数据中是无效的






         噪声变量对BP神经网络建模效果     


下面以matlab自带的acetylene为例,展示噪声变量对BP神经网络的影响
 acetylene化学反应数据示例如下:
  acetylene化学反应数据
我们先用acetylene数据的三个变量进行建模,再添加两噪声变量进行建模,然后比对结果
 具体实验代码和效果如下:
load acetylene.mat                                                % 加载matlab自带的"化学反应数据"
setdemorandstream(666);                                           % 老饼为了每次运行的结果一致设定随机种子,实际中可以去掉
% -------------没有噪声变量时的建模效果----------------                                 
disp('没有噪声变量时的建模效果')   
x      = [x1,x2,x3]';                                             % x1:反应器温度, x2:H2与正庚烷的比率, x3:接触时间
[y,PS] = mapminmax(y',-1,1);                                      % y:正庚烷制乙炔的转化率。这里对y进行归一化是为了方便看误差
net    = newff(x,y,5,{'tansig','purelin'},'trainlm');             % 构建BP神经网络
[net,tr,py] = train(net,x,y);                                     % 训练网络       
train_err   = mean(abs(py(:,tr.trainInd)-y(:,tr.trainInd)))       % 训练数据的误差
test_err    = mean(abs(py(:,tr.testInd)-y(:,tr.testInd)))         % 测试数据的误差

% -----------添加两个噪声变量时的建模效果--------------
disp('添加噪声变量时的建模效果')
x      = [x1,x2,x3,rand(length(x1),2)]';                          % 增加了两个随机变量作为噪声
net    = newff(x,y,5,{'tansig','purelin'},'trainlm');             % 构建BP神经网络
[net,tr,py] = train(net,x,y);                                     % 训练网络                                                           
train_err   = mean(abs(py(:,tr.trainInd)-y(:,tr.trainInd)))       % 训练数据的误差
test_err    = mean(abs(py(:,tr.testInd)-y(:,tr.testInd)))         % 测试数据的误差
运行结果如下: 
 
噪声变量对BP神经网络建模效果
没有噪声变量时预测误差为0.09,有噪声变量时0.45
可以看到,噪声变量会大大影响BP神经网络模型的效果






    02. 什么是逐步回归   




本节简单讲解什么逐步回归建模,以及向前选择逐步回归的流程




    什么是逐步回归   


逐步回归建模是一种常用的建模方式,它可以有效地减少入模变量个数,加强模型的泛化能力
逐步回归分为"向前选择"与"向后删除"两种方式

向前选择:向前选择就是逐个添加变量进行建模,直到新添加变量不再对模型有所贡献时,则停止添加变量       
向后删除:向后删除则是先将所有变量进行建模,然后逐个变量删除,直到满足删除变量会对模型性能有所影响
逐步回归的具体流程(向前选择)   
 
向前选择逐步回归采用逐个变量入模的方式进行建模,具体流程如下:
 向前选择逐步回归的流程
1. 历遍所有变量,将单个变量与目标建模,把模型结果最好的变量作为第一轮选择变  
2. 在第一轮选择变量的基础上,添加第二个变量,                                                    
历遍剩余变量,添加哪个变量能令模型结果最好,就将其作为第二轮选择变量    
3. 在第二轮的基础上,添加第三个变量......                                                                
......
直到变量不再对拟合结果带来明显贡献时,就不再添加变量                               
 向后删除逐步回归是类似的,只是采用逐个减少变量的方式进行建模








    03. BP神经网络-逐步回归建模实例   




本节展示如何使用逐步回归来减少BP神经网络建模的变量个数




       BP神经网络-逐步回归建模实例与代码         


 通过逐步回归来减少BP神经网络建模变量个数,往往能降低模型的训练误差、提高模型的泛化能力
下面仍然以acetylene化学数据作为示例,并添加两个噪声变量,以展示BP神经网络逐步回归建模的效果
 BP神经网络-逐步回归具体实现代码如下:
% 本代码用于展示如何使用逐步回归来选择BP神经网络的建模变量
% 本代码来自《老饼讲解-BP神经网络》www.bbbdata.com
% ----------------加载数据---------------------------------                                           
setdemorandstream(999);                                              % 老饼为了每次运行的结果一致设定随机种子,实际中可以去掉
load acetylene.mat                                                   % 加载matlab自带的"化学反应数据"
x      = [x1,x2,x3,rand(length(x1),2)]';                             % x1:反应器温度,x2:H2与正庚烷的比率,x3:接触时间,并增加了两个随机变量作为噪声
[y,PS] = mapminmax(y',-1,1);                                         % y:正庚烷制乙炔的转化率。这里对y进行归一化是为了方便看误差

% ------------使用逐步回归选择建模变量---------------------    
var_num    = size(x,1);                                              % 变量个数
select_var = [];                                                     % 已选择的变量
res_var    = 1: var_num;                                             % 未使用的变量
try_num    = 10 ;                                                    % 尝试的次数
err_record = [mean(abs(mean(y)-y))];
for i = 1:var_num                                                    % 逐个变量进行选择
    err_list =[];                                                    % 初始化本次各个变量的误差
    for cur_var = res_var                                            % 计算添加各个变量后模型的误差            
        var = [select_var,cur_var];                                  % 本次用于建模的变量(已选择的变量+本次的变量)
        err = 0;                                                     % 初始化模型的误差
        cur_x = x(var,:);                                            % 本次用于建模的x
        for k = 1: try_num                                           % 尝试try_num次,取误差均值作为本变量的模型误差
            net = newff(cur_x,y,5,{'tansig','purelin'},'trainlm');   % 构建BP神经网络
            net.divideParam.trainRatio = 0.85;                       % 用于训练的数据比例
            net.divideParam.valRatio   = 0.15 ;                      % 用于验证过拟合的数据比例
            net.divideParam.testRatio  = 0;                          % 用于测试的数据的比例(不需要测试数据,所以设为0)
            [net,tr,py] = train(net,cur_x,y);                        % 训练网络
            err = err + mean(abs(py(:)-y(:)))/try_num;               % 更新模型的训练误差
        end
        err_list = [err_list,err];                                   % 记录该变量对应的模型误差
    end
    % 判断本次应该选择哪个变量
    [err,idx] = min(err_list);                                       % 找出差误最小的变量
    if((err_record(end)-err)<0.01)                                   % 如果加入变量后,误差下降并不明显,则停止添加变量
        break
    end
    err_record=[err_record,err];
    select_var  = [select_var,res_var(idx)];                         % 将本次选出的变量添加到已选变量池中
    res_var(idx)=[];                                                 % 从剩余变量池中移除将本次选出的变量
end
select_var   % 打印最后选出用于建模的变量

% ---------------使用选出的变量进行建模--------------------
% 这里老饼为了结果的可复现性,设置了随机种子,实际中应该使用选择好的变量多训练几次,选择较好的结果
setdemorandstream(999);                                              
select_x    = x(select_var,:);                                       % 用于建模的x
net         = newff(select_x,y,5,{'tansig','purelin'},'trainlm');    % 构建BP神经网络
[net,tr,py] = train(net,select_x,y);                                 % 训练网络

% 计算模型预测指标
train_err   = mean(abs(py(:,tr.trainInd)-y(:,tr.trainInd)))          % 训练数据的误差
test_err    = mean(abs(py(:,tr.testInd)-y(:,tr.testInd)))            % 测试数据的误差
代码运行结果如下:
 BP神经网络-逐步回归代码运行结果 
在逐步回归中依次选出的变量为x1,x2,x3,可见逐步回归成功地排除了噪声变量x4,x5
最终,使用x1,x2,x3进行建模的结果为:训练误差0.0730,测试误差0.0901






好了,以上就是使用逐步回归来选择BP神经网络入模变量的方法与代码了~







 End 





联系老饼