本站原创文章,转载请说明来自《老饼讲解-BP神经网络》www.bbbdata.com
在BP神经网络的实际建模中,往往需要比较细致地处理数据,以及打印评估指标
本文讲解BP神经网络的完整建模流程步骤,包括数据预处理、训练、评估等,并展示一个具体的例子
通过本文,可以了解BP神经网络的建模需要哪些步骤、各个步骤的具体操作,以及matlab具体代码实现
本节讲解BP神经网络建模的标准完整步骤,和每个步骤的内容
BP神经网络建模-完整步骤
BP神经网络的建模流程主要步骤如下:
总的来说,主流程共有3个大步骤,6个小步骤,如下
👉 数据预处理 :数据归一化、数据划分
👉 网络构建 :网络结构设置、网络训练
👉 效果评估 :模型训练效果评估、模型预测效果评估
BP神经网络建模-完整步骤-详述
BP神经网络建模完整的各个步骤细节如下:
步骤一、BP神经网络数据预处理
1.1. 数据归一化
在模型训练之前,需要把所有数据(X和y)都进行归一化
其中,归一化公式如下:
是原始数据,是归一化后的数据
1.2. 数据划分
一般将数据划分成三部分,训练数据、验证数据、检验数据
可以按训练数据70%、验证数据15%、检验数据15%的比例随机分割
每份数据的作用如下:
训练数据:用于求解(调整w,b)
验证数据:验证数据主要用于防止训练走向过拟合
测试数据:不参与任何训练过程,纯粹用于检验模型最后的测试效果
步骤二、BP神经网络构建
2.1. BP神经网络结构设置
设置BP神经网络隐层层数(一般都是一个隐层),和隐层神经元个数
2.2. BP神经网络训练(求解w,b)
用训练数据对BP神经网络进行训练,可采用梯度下降法、LM法等等
在训练过程中,需要不断用验证数据检验模型的泛化能力
如果训练数据效果越来越好,而验证数据越来越差,则说明开始过拟合了,就停止训练
步骤三、BP神经网络效果评估
3.1. 模型训练效果评估
检验模型对训练数据的预测效果
一个BP神经网络训练成功的表现就是训练数据误差达到要求
3.2. 模型预测效果评估
检验模型对检验数据(未参与训练的数据)的预测效果
一个BP神经网络可用的表现就是模型测试数据误差达到要求
模型的评估指标,一般依据实际问题进行设计
对于数值问题,可以使用平均绝对误差MAE,如下:
其中是BP神经网络对样本的预测值
总的来说,先将数据归一化,然后划分为训练数据、验证数据和测试数据
再设置好网络,将训练数据投到网络中训练权重阈值,并用验证数据预防过拟合
最后,检查BP神经网络的训练误差,并用测试数据评估模型的预测能力
本节展示BP神经网络建模的完整代码,以供使用时进行借鉴与复制
BP神经网络建模代码-具体代码
本文展现一个按照标准建模流程来实现BP神经网络的DEMO,
包含归一化、训练与测试数据分割、BP网络设置与训练、
训练结果与测试结果展示、模型的使用、提取数学公式等
在实际建模中,复制该代码进行修改即可,代码较为全面,可依需要进行删减
本例从 中采取100个样本,
利用生成的100个样本建立BP神经网络,然后与原函数进行比较
步骤包括如下:
👉 数据 (0) 数据生成
👉 建模 (1) 数据归一化
(2) 训练测试数据分割
(3) 网络设置
(4) 网络训练
(5) 展示训练结果
(6) 测试数据的预测结果
👉 应用 (7) 模型的使用
(8) 提取模型的表达式
具体代码实现如下:
% 本代码是matlab工具箱训练BP神经网络的完整实际使用代码,包括了归一化、训练、测试与提取模型表达式等内容
% 本代码旨在学习与平时使用时方便copy使用(笔者测试代码的版本:matlab2018a)
% 转载请说明来自 《老饼讲解神经网络》 www.bbbdata.com
clear all;close all ;
setdemorandstream(888); % 随机种子,实际使用时应该去掉
%------------------原始数据---------------------
x1 = linspace(-3,3,100); % 在[-3,3]之间线性生成100个数据
x2 = linspace(-2,1.5,100); % 在[-2,1.5]之间线性生成100个数据
X = [x1;x2]; % 将x1,x2作为输入数据
y = 10*sin(x1)+0.2*x2.*x2; % 生成y
%-------数据预处理:预留检验数据与数据归一化------
randIndex = randperm(100);
trainIndex = sort(randIndex(1:80)); % 随机选出80个数据作为训练数据(这里先选出数据的序号)
testIndex = sort(randIndex(81:100)); % 将剩下的20个数据作为检验数据(这里先选出数据的序号)
%由于需要归一化,先将归一化信息抓取出来
%(这里获取训练数据的最大最小值,因为只有训练数据投到网络中进行)
iMax = max(X(:,trainIndex),[],2); % 训练数据X的最大值
iMin = min(X(:,trainIndex),[],2); % 训练数据X的最小值
oMax = max(y(:,trainIndex),[],2); % 训练数据Y的最大值
oMin = min(y(:,trainIndex),[],2); % 训练数据Y的最小值
%对数据进行归一化
normX=2*(X -repmat(iMin,1,size(X,2)))./repmat(iMax-iMin,1,size(X,2)) -1; % 对X归一化
normY=2*(y -repmat(oMin,1,size(y,2)))./repmat(oMax-oMin,1,size(y,2)) -1; % 对y归一化
% 从归一化后的数据中抽出训练数据与测试数据
X_train = normX(:,trainIndex); % 根据序号选出80个用于训练的输入
X_test = normX(:,testIndex); % 根据序号选出20个用于检验的输入
y_train = normY(:,trainIndex); % 根据序号选出80个用于训练的输出
t_test = normY(:,testIndex); % 根据序号选出20个用于检验的输出
%----------------网络训练 ---------------------
%使用用输入输出数据(X_train、y_train)建立网络,
%隐节点个数3,隐层、输出层的激活函数为tansig和purelin,方法训练为trainlm
net = newff(X_train,y_train,3,{'tansig','purelin'},'trainlm'); % 初始化BP神经网络
%设置一些常用参数
net.trainparam.goal = 0.00001; % 训练目标:均方误差低于0.0001
net.trainparam.show = 400; % 每训练400次展示一次结果
net.trainparam.epochs = 15000; % 最大训练次数:15000.
net.divideParam.trainRatio = 0.85; % 用于训练的数据比例
net.divideParam.valRatio = 0.15 ; % 用于验证过拟合的数据比例
net.divideParam.testRatio = 0; % 注意要关掉测试数据占比
[net,tr] = train(net,X_train,y_train); % 训练模型
%----------训练数据的拟合效果----------------
figure;
%训练数据的拟合效果
simout_train = sim(net,X_train); % 训练数据的预测值
subplot(2,1,1); % 第一个子图
title('训练数据的拟合效果') % 标题
hold on % hold on
t= 1 : length(simout_train); % 序号
plot(t,y_train,t,simout_train,'r') % 画图,对比原来的y和网络预测的y
%检验数据的拟合效果
simout_test = sim(net,X_test); % 测试数据的预测值
subplot(2,1,2); % 第二个子图
title('未训练数据的拟合效果') % 标题
hold on % hold on
t = 1:length(simout_test); % 序号
plot(t,t_test,t,simout_test,'r') % 画图,对比原来的y和网络预测的y
% 打印mae指标
mae_train = mean(abs(y_train -simout_train)) % 训练数据的MAE
mae_test = mean(abs(t_test -simout_test)) % 预测数据的MAE
%----------真正使用时的流程--------------------
X = [-2.9;-1.9]; % 要预测的X
normX = 2*(X -iMin)./(iMax-iMin) -1; % 对X归一化
normSimY = sim(net,normX); % 用网络预测
simy = (normSimY+1).*(oMax-oMin)./2 + oMin; % 对结果反归一
%-----------提取表达式(对应归一化数据)----
%提取权重
w12 = net.iw{1,1}; % 第1层(输入层)到第2层(隐层)的权值
b2 = net.b{1}; % 第2层(隐层)的神经元阈值
w23 = net.lw{2,1}; % 第2层(输入层)到第3层(输出层)的权值
b3 = net.b{2}; % 第3层(输出层)的神经元阈值
%对应的数学表达式(输入和输出都是归一化后的数据):
sim_y_norm = w23 *tansig( w12 *normX + repmat(b2,1,size(normX,2))) + repmat(b3,1,size(normX,2));
代码运行结果如下:
答疑:关于为什么要将数据进行归一化
有小伙伴提问,为什么工具箱明明归一化了,本篇代码为什么还要进行归一化呢?
说来都是泪,这纯粹出于matlab工具箱的BUG,如下:
matlab工具箱虽然对y作了归一化,但在训练时,计算梯度使用的误差并没有使用归一化后的误差
它引用的是原始y的误差,如此一来,如果y数量级很大,梯度的步幅就会很大,从而影响了训练效果
总的来说,一般不需要自行作归一化
但如果y的数值很大(也不用很大,例如100,就已经是1的100倍了),最好还是做一下归一化
其实只需要对y进行归一化就能消除这个BUG,本文干脆把X,Y都归一化算了,无他
好了,关于BP神经网络的建模完整代码实现就到这里了~
End