BP神经网络模型(多输入多输出)回归模型
神经网络回归模型原理讲解
该模型是一个典型的多层前馈神经网络(Feedforward Neural Network,FFNN),应用于回归问题。其基本原理包括数据输入、隐藏层神经元的处理、输出层的预测、以及通过反向传播算法优化权重和偏置的过程。下面将详细介绍该模型的工作原理。
1. 神经网络基础结构
神经网络的基本结构由以下几个部分组成:
-
输入层:神经网络的输入层接受外部数据,传递给网络进行处理。在该模型中,输入层包含了五个特征变量。
-
隐藏层:在输入和输出之间的中间层,负责提取数据中的复杂模式和非线性关系。在该模型中,隐藏层包含4个神经元。每个神经元接收输入,并对其进行处理,输出信号传递到下一个层。
-
输出层:输出层负责将网络的最终预测结果输出。在该模型中,输出层有两个神经元,分别对应两个目标输出变量。这是一个回归任务,因此输出层的激活函数通常采用线性激活函数(
purelin
),它允许网络输出任意实数值。
2. 激活函数
-
隐藏层的激活函数:tansig(双曲正切函数)
隐藏层的每个神经元使用tansig激活函数,该函数的公式为:
tansig ( x ) = 2 1 + e − 2 x − 1 \text{tansig}(x) = \frac{2}{1 + e^{-2x}} - 1 tansig(x)=1+e−2x2−1
tansig
函数的输出范围是 [-1, 1],通过该函数,神经网络可以捕捉输入数据的非线性特征。它通常用于隐藏层,因为它能够提供足够的非线性变换。 -
输出层的激活函数:purelin(线性函数)
输出层使用 purelin 激活函数,其公式为:
purelin ( x ) = x \text{purelin}(x) = x purelin(x)=x
线性激活函数适用于回归任务,因为输出值不需要进行任何非线性变换,允许模型输出任意范围的实数值。
3. 前向传播
在前向传播过程中,数据从输入层传递到输出层,每一层的神经元都会对输入信号进行加权求和,并通过激活函数产生输出信号。
-
输入信号到隐藏层的传播:
对于输入层和隐藏层之间的连接,每个输入信号(例如 (x_1, x_2, …, x_n))都会与相应的权重(例如 (w_1, w_2, …, w_n))相乘,然后加上偏置项((b))。这称为加权和。
隐藏层的神经元输出通过激活函数处理,公式为:
h = tansig ( w 1 x 1 + w 2 x 2 + . . . + w n x n + b ) h = \text{tansig}(w_1 x_1 + w_2 x_2 + ... + w_n x_n + b) h=tansig(w1x1+w2x2+...+wnxn+b) -
隐藏层到输出层的传播:
输出层神经元同样通过加权和处理隐藏层的输出信号,最后通过线性激活函数得到预测值。
输出层的预测值为:
y pred = w h ⋅ h + b o y_{\text{pred}} = w_h \cdot h + b_o ypred=wh⋅h+bo
4. 损失函数(误差函数)
回归模型的目标是最小化预测值与真实值之间的误差。常见的损失函数是均方误差(Mean Squared Error,MSE),即:
MSE
=
1
n
∑
i
=
1
n
(
y
pred
,
i
−
y
true
,
i
)
2
\text{MSE} = \frac{1}{n} \sum_{i=1}^{n} (y_{\text{pred}, i} - y_{\text{true}, i})^2
MSE=n1i=1∑n(ypred,i−ytrue,i)2
通过最小化均方误差,神经网络会逐步调整权重和偏置,使得网络的预测越来越精确。
5. 训练过程:反向传播与权重更新
神经网络通过反向传播算法(Backpropagation)来训练模型。其过程如下:
-
计算误差:首先,通过前向传播计算每个输出层神经元的预测值 (y_{\text{pred}}),并与真实值 (y_{\text{true}}) 进行比较,计算误差(例如 MSE)。
-
反向传播:误差计算后,通过反向传播算法将误差从输出层逐层传递到输入层。每一层的权重和偏置都会根据误差的大小进行更新,以便减少整体误差。反向传播的核心是梯度下降算法,它通过计算损失函数的梯度来更新权重和偏置。
更新规则为:
w = w − η ⋅ ∂ E ∂ w w = w - \eta \cdot \frac{\partial E}{\partial w} w=w−η⋅∂w∂E -
迭代优化:这个过程会迭代多次(在代码中是通过设置最大训练次数),每次迭代都会对网络的权重进行微小的调整,最终使得网络的误差达到最小。
6. 训练与预测
在该模型中,训练集数据用于优化神经网络的权重和偏置,而测试集数据用于评估训练后的模型性能。模型的输出是对于目标变量的预测值,训练过程中的误差指标(如均方根误差、R²、MAE)能够帮助判断模型的预测效果。
总结
- 该模型是一个标准的多层前馈神经网络(FFNN),用于回归问题。
- 输入数据通过隐藏层的激活函数进行非线性变换,最终在输出层得到预测值。
- 网络通过反向传播算法来调整权重和偏置,使得误差最小化。
- 该模型适用于预测连续值,能够学习复杂的非线性关系。
神经网络回归模型原理讲解(结合代码)
该代码实现了一个多层前馈神经网络(Feedforward Neural Network,FFNN)用于回归任务,目标是基于给定的特征数据(输入)预测两个连续的输出。下面详细讲解每个部分的原理,并结合代码进行解释。
1. 导入数据并归一化处理
res = readmatrix('回归数据.xlsx'); % 导入数据
X = res(:, 1:5); % 特征变量
Y = res(:, 6:7); % 目标变量
x = mapminmax(X', 0, 1); % 对特征变量归一化
[y, psout] = mapminmax(Y', 0, 1); % 对目标变量归一化
- 数据导入:首先通过
readmatrix
导入回归数据集,其中X
是输入特征(例如,5个特征变量),Y
是目标输出(例如,2个回归输出变量)。 - 数据归一化:使用
mapminmax
函数对输入特征和目标输出进行归一化处理,使得数据都映射到[0, 1]范围内。这是神经网络中常见的数据预处理方式,能够加速训练过程,避免某些特征值过大导致梯度消失或梯度爆炸的问题。
2. 划分训练集与测试集
num = size(res, 1); % 获取数据的总行数
state = randperm(num); % 随机打乱样本的索引
ratio = 0.8; % 训练集占比
train_num = floor(num * ratio); % 计算训练集的样本数量
x_train = x(:, state(1:train_num)); % 训练集特征
y_train = y(:, state(1:train_num)); % 训练集目标
x_test = x(:, state(train_num+1:end)); % 测试集特征
y_test = y(:, state(train_num+1:end)); % 测试集目标
- 随机打乱数据:
randperm(num)
生成一个随机排列的索引,然后使用这些索引来打乱数据。这样可以避免因数据顺序性带来的偏差。 - 划分数据集:通过设定 80% 的数据用于训练,20% 的数据用于测试,分割训练集和测试集。
3. 创建神经网络
hiddens = 4; % 隐藏层神经元个数
tf = {'tansig', 'purelin'}; % 激活函数,隐藏层用tansig,输出层用purelin
net = newff(x_train, y_train, hiddens, tf); % 创建神经网络
- 神经网络结构:代码使用
newff
函数来创建一个前馈神经网络。该函数是 MATLAB 中用于创建多层前馈神经网络的标准函数。网络结构包含:- 输入层:有5个节点,对应5个输入特征。
- 隐藏层:一个隐藏层,包含4个神经元(在代码中由
hiddens = 4
设置)。该层使用tansig
(双曲正切)作为激活函数,它能提供非线性映射,从而帮助网络捕捉复杂的关系。 - 输出层:使用
purelin
作为激活函数,这表示输出层是线性的,适合回归任务。
4. 设置训练参数
net.trainParam.epochs = 1000; % 训练迭代次数MAX
net.trainParam.goal = 1e-6; % 目标误差
net.trainParam.lr = 0.01;
- 训练参数:
epochs
:设置网络的最大迭代次数,即最多训练1000次。goal
:指定目标误差,当网络的均方误差(MSE)小于1e-6
时,训练就会停止。lr
:学习率,决定了每次参数更新时步长的大小。
5. 训练神经网络
net = train(net, x_train, y_train); % 训练神经网络
- 训练过程:
train
函数使用训练数据(x_train
和y_train
)来优化神经网络的权重和偏置。通过多次迭代,网络学习到输入特征与输出目标之间的关系。
6. 仿真测试
re1 = sim(net, x_train);
re2 = sim(net, x_test);
- 仿真预测:通过
sim
函数,在训练集和测试集上分别进行预测,得到网络输出的预测结果。
7. 数据反归一化
pre1 = mapminmax('reverse', re1, psout);
pre2 = mapminmax('reverse', re2, psout);
- 反归一化:将归一化的预测结果通过
mapminmax('reverse', ...)
转换回原始的尺度,得到实际的预测值。
8. 评估模型性能
% 计算误差和相关指标
error1 = sqrt(mean((p1 - Y_tr).^2)); % RMSE
R1 = 1 - norm(Y_tr - p1)^2 / norm(Y_tr - mean(Y_tr))^2; % R2
mae1 = mean(abs(Y_tr - p1)); % MAE
- 误差计算:计算了多个回归模型的性能指标:
- RMSE(均方根误差):反映了预测值与真实值之间的差异,值越小表示模型性能越好。
- R²(决定系数):表示模型的拟合优度,R² 越接近 1,表示模型拟合得越好。
- MAE(平均绝对误差):计算预测值与真实值之间的平均绝对差异。
9. 绘图与结果展示
plot(1: trainnum, Y_tr, 'r-^', 1: trainnum, p1, 'b-+', 'LineWidth', 1)
plot(1: testnum, Y_te, 'r-^', 1: testnum, p2, 'b-+', 'LineWidth', 1)
- 结果对比图:通过
plot
函数绘制训练集和测试集的真实值与预测值的对比图,以及误差曲线图和拟合图,直观地展示模型的预测效果。
总结:
该神经网络回归模型的流程包括:
- 数据预处理:对输入特征和目标进行归一化。
- 网络构建:使用
newff
创建一个具有1个隐藏层的多层前馈神经网络。 - 训练过程:使用训练集数据训练神经网络,学习输入和输出之间的关系。
- 仿真与预测:在训练集和测试集上进行预测,反归一化得到实际预测值。
- 模型评估:通过计算误差指标(RMSE、R²、MAE)来评估模型的性能,并通过图表展示结果。
该模型适用于需要回归预测的任务,可以通过调整网络的隐藏层神经元数、学习率等超参数来优化模型性能。
Matlab代码手把手教运行
为了帮助更多的萌新更快上手数学建模建等竞赛,这里直接手把手教会如何直接使用本文中的BP神经网络代码:
close all;clear;clc;
rng(5676)
res = readmatrix('回归数据.xlsx');
X = res(:,1:5);
Y = res(:,6:7);
x = mapminmax(X', 0, 1);
[y, psout] = mapminmax(Y', 0, 1);
num = size(res,1);
state = randperm(num);
ratio = 0.8;
train_num = floor(num*ratio);
x_train = x(:,state(1: train_num));
y_train = y(:,state(1: train_num));
trainnum = size(x_train, 2);
x_test = x(:,state(train_num+1: end));
y_test = y(:,state(train_num+1: end));
testnum = size(x_test, 2);
hiddens = 4; %隐藏层个数
tf = {'tansig', 'purelin'};
net = newff(x_train, y_train, hiddens,tf);
%% 设置参数
net.trainParam.epochs = 1000;
net.trainParam.goal = 1e-6;
net.trainParam.lr = 0.01;
%% 训练网络
net= train(net, x_train, y_train);
re1 = sim(net, x_train);
re2 = sim(net, x_test );
Y_train = Y(state(1: train_num),:)';
Y_test = Y(state(train_num+1:end),:)';
pre1 = mapminmax('reverse', re1, psout);
pre2 = mapminmax('reverse', re2, psout);
for i=1:2
disp(' ')
disp(' ')
disp(['第',num2str(i),'个输出指标'])
p1 = pre1(i,:);
p2 = pre2(i,:);
Y_tr = Y_train(i,:);
Y_te = Y_test(i,:);
error1 = sqrt(mean((p1 - Y_tr).^2));
error2 = sqrt(mean((p2 - Y_te).^2));
R1 = 1 - norm(Y_tr - p1)^2 / norm(Y_tr - mean(Y_tr))^2;
R2 = 1 - norm(Y_te - p2)^2 / norm(Y_te - mean(Y_te ))^2;
mae1 = mean(abs(Y_tr - p1 ));
mae2 = mean(abs(p2 - Y_te ));
disp('训练集预测精度指标如下:')
disp(['训练集数据的R2为:', num2str(R1)])
disp(['训练集数据的MAE为:', num2str(mae1)])
disp(['训练集数据的RMSE为:', num2str(error1)])
disp('测试集预测精度指标如下:')
disp(['测试集数据的R2为:', num2str(R2)])
disp(['测试集数据的MAE为:', num2str(mae2)])
disp(['测试集数据的RMSE为:', num2str(error2)])
figure
plot(1: trainnum, Y_tr, 'r-^', 1: trainnum, p1, 'b-+', 'LineWidth', 1)
legend('真实值','预测值')
xlabel('样本点')
ylabel('预测值')
title('训练集预测结果对比')
figure
plot(1: testnum, Y_te, 'r-^', 1: testnum, p2, 'b-+', 'LineWidth', 1)
legend('真实值','预测值')
xlabel('样本点')
ylabel('预测值')
title('测试集预测结果对比')
figure
plot((p1 - Y_tr )./Y_tr, 'b-o', 'LineWidth', 1)
legend('百分比误差')
xlabel('样本点')
ylabel('误差')
title('训练集百分比误差曲线')
figure
plot((p2 - Y_te )./Y_te, 'b-o', 'LineWidth', 1)
legend('百分比误差')
xlabel('样本点')
ylabel('误差')
title('测试集百分比误差曲线')
figure;
plotregression(Y_tr, p1, '训练集', ...
Y_te, p2, '测试集');
set(gcf,'Toolbar','figure');
end
回归数据.xlsx:
x1 | x2 | x3 | x4 | x5 | y1 | y2 |
---|---|---|---|---|---|---|
3.036226 | 5613.881 | 217.475 | 68.43483 | 16.82093 | 48.47907612 | 39.33407612 |
4.391658 | 8450.278 | 231.6231 | 60.47683 | 10.7205 | 64.12185185 | 54.97685185 |
5.248597 | 8634.475 | 232.9854 | 68.74011 | 11.54856 | 67.67148734 | 58.52648734 |
5.121236 | 7253.694 | 244.4692 | 65.36061 | 14.36191 | 59.32753057 | 50.18253057 |
4.649021 | 8647.125 | 268.3052 | 63.80132 | 12.04857 | 67.98570391 | 58.84070391 |
4.267209 | 5445.033 | 257.7701 | 61.68997 | 7.055625 | 46.47506598 | 37.33006598 |
4.804512 | 5848.875 | 234.0968 | 67.14467 | 7.656134 | 47.18442579 | 38.03942579 |
3.825803 | 6583.543 | 270.7575 | 61.44453 | 16.65654 | 54.0487296 | 44.9037296 |
4.787534 | 9546.304 | 225.8279 | 67.89351 | 11.43665 | 69.90372309 | 60.75872309 |
5.580797 | 5481.803 | 287.9043 | 62.20432 | 11.26927 | 47.32012957 | 38.17512957 |
3.658919 | 9482.116 | 278.8093 | 61.20217 | 12.37418 | 71.68429695 | 62.53929695 |
3.829985 | 9128.034 | 225.2187 | 64.81423 | 16.70461 | 68.18735427 | 59.04235427 |
5.295785 | 6804.695 | 282.6947 | 67.13434 | 13.61871 | 58.0309376 | 48.8859376 |
替换数据只需将特征值放入前几列(第一行为列名),因变脸放在后面即可,接下来调整一下代码即可:
X = res(:,1:5);
Y = res(:,6:7);//在第几列就写几到几
后续继续免费更新模型代码,祝好运!
标签:输出,num,函数,训练,模型,神经网络,train,BP,Matlab From: https://blog.csdn.net/2401_82466443/article/details/143568150