% 批量方式训练BP网络,实现病症识别
%% 清理
clear all
clc
%% 读入数据
xlsfile='train_dataset_washed.xls';
[~,label] = xlsread(xlsfile,'DataSet','J1:J541');
[data,~] = xlsread(xlsfile,'DataSet','A1:I541');
l = zeros(size(label));
for i = 1:length(l)
if label{i} == 'C'
l(i,:) = 1;
end
if label{i} == 'D'
l(i,:) = 1;
end
end
label = l;
%% 划分数据
%正常与不正常各取81个,352个进行训练
TRAIN_NUM_N = 81;
TRAIN_NUM_U = 352;
%正常与不正常分开
n_data = data(label == 1,:);
u_data = data(label == 0,:);
NUM_N = length(n_data);%正常的个数
%正常
r = randperm(NUM_N);
traind(1:TRAIN_NUM_N,:) = n_data(r(1:TRAIN_NUM_N),:);
testd(1:NUM_N - TRAIN_NUM_N,:) = n_data(r(TRAIN_NUM_N + 1:NUM_N),:);
NUM_U = length(u_data);%不正常的个数
%不正常
r = randperm(NUM_U);
traind(TRAIN_NUM_N + 1:TRAIN_NUM_U + TRAIN_NUM_N,:) = u_data(r(1:TRAIN_NUM_U),:);
testd(NUM_N - TRAIN_NUM_N + 1:NUM_N - TRAIN_NUM_N + NUM_U - TRAIN_NUM_U,:) = u_data(r(TRAIN_NUM_U + 1:NUM_U),:);
% 赋值
trainl=zeros(1,TRAIN_NUM_N+TRAIN_NUM_U);
trainl(1:TRAIN_NUM_N)=1;
testl=zeros(1,NUM_N+NUM_U-TRAIN_NUM_N-TRAIN_NUM_U);
testl(1:NUM_N-TRAIN_NUM_N)=1;
%% 设置参数
rng('default')
rng(0)
nTrainNum = TRAIN_NUM_N + TRAIN_NUM_U; % 433个训练样本
%% 构造网络
net.nIn = 9;
net.nHidden1 = 12; % 第一个隐藏层有?个神经元
net.nHidden2 = 4; % 第二个隐藏层有?个神经元
net.nOut = 1; % 1x个输出层节点
w1 = rand(net.nHidden1,net.nIn);
b1 = rand(net.nHidden1,1);
net.w1 = [w1,b1];
w2 = rand(net.nHidden2,net.nHidden1);
b2 = rand(net.nHidden2,1);
net.w2 = [w2,b2];
W = rand(net.nOut,net.nHidden2);
B = rand(net.nOut,1);
net.w3 = [W,B];
%% 训练数据归一化
[traind_s,ps] = mapminmax(traind',0,1);
%% 训练
SampInEx = [traind_s;ones(1,nTrainNum)];
expectedOut = trainl;
eb = 0.01; % 误差容限
eta = 0.01; % 学习率
mc = 0.01; % 动量因子
maxiter = 1000; % 最大迭代次数
iteration = 0; % 第一代
errRec = zeros(1,maxiter);
outRec = zeros(nTrainNum, maxiter);
NET=[]; % 记录
% 开始迭代
for i = 1 : maxiter
hid1_input = net.w1 * SampInEx; % 第一层隐含层的输入
hid1_out = logsig(hid1_input); % 第一层隐含层的输出
hid2_input = [hid1_out;ones(1,nTrainNum)];
hid2_input2 = net.w2 * hid2_input; % 第二层隐含层的输入
hid2_out = logsig(hid2_input2); % 第二层隐含层的输出
ou_input1 = [hid2_out;ones(1,nTrainNum)]; % 输出层的输入
ou_input2 = net.w3 * ou_input1;
out_out = logsig(ou_input2); % 输出层的输出
outRec(:,i) = out_out'; % 记录每次迭代的输出
err = expectedOut - out_out; % 误差
sse = sumsqr(err);
errRec(i) = sse; % 保存误差值
fprintf('第 %d 次迭代 误差: %f\n', i, sse);
iteration = iteration + 1;
% 判断是否收敛
if sse <= eb
break;
end
% 误差反向传播
% 第二层隐含层与输出层之间的局部梯度
% DELTA = err;
DELTA = err.*dlogsig(ou_input2,out_out);
% 第一层隐含层与第二层隐含层之间的局部梯度
delta1 = net.w3(:,1:end-1)'*DELTA.*dlogsig(hid2_input2,hid2_out);
% 输入层与第一层隐含层之间的局部梯度
delta2 = net.w2(:,1:end-1)'* delta1.*dlogsig(hid1_input,hid1_out);
% 权值修改量
dWEX = DELTA * ou_input1';
dwex2 = delta1 * hid2_input';
dwex1 = delta2 * SampInEx';
% 修改权值,如果不是第一次修改,则使用动量因子
if i == 1
net.w3 = net.w3 + eta * dWEX;
net.w2 = net.w2 + eta * dwex2;
net.w1 = net.w1 + eta * dwex1;
else
net.w3 = net.w3 + (1 - mc) * eta * dWEX + mc * dWEXOld;
net.w2 = net.w2 + (1 - mc) * eta * dwex2 + mc * dwex2Old;
net.w1 = net.w1 + (1 - mc) * eta * dwex1 + mc * dwex1Old;
end
% 记录上一次的权值修改量
dWEXOld = dWEX;
dwex1Old = dwex1;
dwex2Old = dwex2;
end
训练得到的误差很大,改变隐藏层神经元数量,会导致把另1类完全判断成0类。数据集没有问题,已经通过matlab自带的工具箱达到90%以上的正确率。
你好,我是有问必答小助手,非常抱歉,本次您提出的有问必答问题,技术专家团超时未为您做出解答
本次提问扣除的有问必答次数,将会以问答VIP体验卡(1次有问必答机会、商城购买实体图书享受95折优惠)的形式为您补发到账户。
因为有问必答VIP体验卡有效期仅有1天,您在需要使用的时候【私信】联系我,我会为您补发。