解决Matlab 调用训练好的BP网络的权值和阀值算出来的预测值和调用sim得到的值不一样的办法

您所在的位置:网站首页 matlab优化模型怎么导出结果数据 解决Matlab 调用训练好的BP网络的权值和阀值算出来的预测值和调用sim得到的值不一样的办法

解决Matlab 调用训练好的BP网络的权值和阀值算出来的预测值和调用sim得到的值不一样的办法

2024-03-17 15:55| 来源: 网络整理| 查看: 265

解决方法

解决方法很简单:自己通过训练好的权值和阈值计算时,归一化和反归一化的范围应该设为(-1,1),而不是(0,1)。

也就是从原来的:

[p_train, ps_input] = mapminmax(Id',0,1); [t_train, ps_output] = mapminmax(train_y',0,1);

改为:

[p_train, ps_input] = mapminmax(Id',-1,1); [t_train, ps_output] = mapminmax(train_y',-1,1);

本文在这篇论坛上得到提示:Matlab训练好BP神经网络后,怎么根据权值和阈值来计算呢? 此方法仅供参考,可能大家的情况有所不同,希望对大家有帮助。

以上为原回答 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 以下为10月10日更新 之前在评论区答应了过几天就补全回答,没想到一下子耽搁了3个月,实在是抱歉! 之前的答案这一句话“自己通过训练好的权值和阈值计算时”有误,应该是在一开始训练BP神经网络的时候就把归一化和反归一化的范围设为(-1,1),而不是采用(0,1),对了,我用的matlab版本为2019b。

以下将以经典的BP神经网络——基于近红外光谱的汽油辛烷值预测为例

原始的程序和数据集大家可以自行百度、google或者在github上寻找,我在文中也会给出程序,找不到数据集的人可以说自己邮箱,我看到的话会回,不过我后面也挺忙的,不保证及时性。 原始的BP神经网络程序如下:

%% I. 清空环境变量 clear all close all clc %% II. 训练集/测试集产生 %% % 1. 导入数据 load spectra_data.mat %% % 2. 随机产生训练集和测试集 temp = randperm(size(NIR,1)); % 训练集——50个样本 P_train = NIR(temp(1:50),:)'; T_train = octane(temp(1:50),:)'; % 测试集——10个样本 P_test = NIR(temp(51:end),:)'; T_test = octane(temp(51:end),:)'; N = size(P_test,2); %% III. 数据归一化 [p_train, ps_input] = mapminmax(P_train,0,1); p_test = mapminmax('apply',P_test,ps_input); [t_train, ps_output] = mapminmax(T_train,0,1); %% IV. BP神经网络创建、训练及仿真测试 %% % 1. 创建网络 net = newff(p_train,t_train,8); %% % 2. 设置训练参数 net.trainParam.epochs = 1000;%最大训练次数设置 net.trainParam.goal = 1e-3;%训练目标设置,及要求精度 net.trainParam.lr = 0.01;%学习率设置,应设置为较小值 %% % 3. 训练网络 net = train(net,p_train,t_train); %% % 4. 仿真测试 t_sim = sim(net,p_test); %% % 5. 数据反归一化 T_sim = mapminmax('reverse',t_sim,ps_output); %% V. 性能评价 %% % 1. 相对误差error error = abs(T_sim - T_test)./T_test; %% % 2. 决定系数R^2 R2 = (N * sum(T_sim .* T_test) - sum(T_sim) * sum(T_test))^2 / ((N * sum((T_sim).^2) - (sum(T_sim))^2) * (N * sum((T_test).^2) - (sum(T_test))^2)); %% % 3. 结果对比 result = [T_test' T_sim' error'] %% VI. 绘图 figure plot(1:N,T_test,'b:*',1:N,T_sim,'r-o') legend('真实值','预测值') xlabel('预测样本') ylabel('辛烷值') string = {'测试集辛烷值含量预测结果对比';['R^2=' num2str(R2)]}; title(string)

从上述程序中我们可以发现,在数据归一化的位置是将范围设定在(0,1)之间,但是我在实际操作中发现,在照搬根据(0,1)归一化的mapminmax函数的参数后,计算出来的神经网络输出值和原神经网络的不同,那么怎么解决这个问题呢,就像我前面说的,我们只需要将上面的原始BP神经网络的归一化范围改为(-1,1)。具体的原因我也没想明白,我猜也许matlab内部的调用函数不太一样,如果有大佬知道的请多多指教。 现在让我们将上述程序中的这部分:

%% III. 数据归一化 [p_train, ps_input] = mapminmax(P_train,0,1); p_test = mapminmax('apply',P_test,ps_input); [t_train, ps_output] = mapminmax(T_train,0,1);

改为

%% III. 数据归一化 [p_train, ps_input] = mapminmax(P_train,-1,1); p_test = mapminmax('apply',P_test,ps_input); [t_train, ps_output] = mapminmax(T_train,-1,1);

这样改变归一化范围并不会对神经网络预测精确度产生什么影响。 运行更改后的BP神经网络主程序之后,我们就可以得到如下的预测结果图: 在这里插入图片描述

同时我们在工作区中会得到大量的计算变量,如下图: 在这里插入图片描述 其中我们在后续需要用到的数据是红框中的三个,分别是训练好的神经网络和归一化反归一化的函数参数,其中需要我们自行提取的只有训练好的net变量中的网络权值和阈值参数。 这里有两种方法,参看如下程序:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %方法一: genFunction(net); %提取函数net %或者如下 %方法二: IW1_1 = net.iw{1,1}; b1 = net.b{1}; LW2_1 = net.lw{2,1}; b2 = net.b{2}; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

方法二就不细说了,其他文章中已经有提到过,想弄明白的同学可以参看help中“network”的文档。 方法一则是运行genFunction函数,然后点击命令行窗口的“edit neural_function”: 在这里插入图片描述 然后会跳出“neural_function”函数,其中就有已经训练好的权值和阈值,也就是其中的b和IW,LW,我们只需要将其复制过来: 在这里插入图片描述 IW为输出层到隐含层的权值,b1为输入层到隐含层的阈值;LW即为隐含层到输出层的权值,b2为隐含层到输出层的阈值。 同时,我们还能在“neural_function”函数中找到程序内部运行神经网络的循环计算代码:

for ts=1:TS % Input 1 Xp1 = mapminmax_apply(X{1,ts},x1_step1); % Layer 1 a1 = tansig_apply(repmat(b1,1,Q) + IW1_1*Xp1); % Layer 2 a2 = repmat(b2,1,Q) + LW2_1*a1; % Output 1 Y{1,ts} = mapminmax_reverse(a2,y1_step1); end

和sigmoid的传递函数:

% Sigmoid Symmetric Transfer Function function a = tansig_apply(n,~) a = 2 ./ (1 + exp(-2*n)) - 1; end

我在后续自行建立训练好的神经网络时既是参考的上图的循环算式。具体程序如下:

% clear all % close all % clc %% 创建神经网络参数 % Layer 1;b1:隐含层偏移量;IW1_1:隐含层权值 b1 = [1.3748057355138554314;-1.0270389076505417325]; IW1_1 = [-0.033329920682804686782 -0.046980249869347533165]; % Layer 2;b2:输出层偏移量;LW2_1:输出层权值 b2 = -0.70620702517192035508; LW2_1 = [-0.50069237473355243662 -0.31059943234833836678]; %% 计算 p_test1 = mapminmax('apply',P_test,ps_input); a1 = tansig(b1+IW1_1*p_test1); a2 =b2+LW2_1*a1; T_sim_t = mapminmax('reverse',a2,ps_output); %% 作图 figure(1) plot(1:N,T_sim,'r-o'); hold on plot(1:N,T_sim_t,'b-*');

上述代码中,前三行加引号是因为还需要使用之前得到的变量“ps_input”和“ps_output”,避免直接点运行按钮就把之前的变量都删除掉了,另外,这里的b1、b2、IW、LW这么短是因为本来的变量参数有401列,全部放出来太长了,在这里我就略去了,大家自己弄的时候注意。

以下是运行结果图,其中红色是原始神经网络的计算结果,蓝色是我们提取出训练好的net参数的计算结果: 在这里插入图片描述

可以看到和原始训练好的神经网络结果完全一致,但是假如我们还是采用(0,1)的归一化范围的话,得到的对比图则如下: 在这里插入图片描述 我也不明白为什么会出现这样的情况,希望有懂的大佬可以告知。 欢迎在评论区留言讨论,也欢迎指正错误。 有兴趣的同学也可以参看这一篇博客:MATLAB编写自己的BP神经网络程序 以上



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3