从0开始编写BP,自适应学习率的BP神经网络,不使用MATLAB工具箱,纯手写matlab代码,以BP分类为例...

与上篇文章不同,仔细读了上篇文章的小伙伴应该知道,BP神经网络是有一个学习率的,而这个学习率很大程度上决定着神经网络的效果。这里采用自适应学习率,实现纯手写BP神经网络。

编程时,激活函数选择Sigmoid函数,使用者也可以根据需要自行更改!

以经典的红酒数据分类为例,红酒数据大小为178*14,最后一列为标签列。随机取数据的百分之70作为训练集,百分之30作为测试集。

红酒数据的获取可以参考常用UCI数据集,链接放在文末,其中的Wine.mat即为红酒数据。

废话不多说,接下来直接上代码!

首先是主程序代码:

close all
warning off
%% 数据读取
clc
clear
load Wine
%% 数据载入
data=Wine;
data=data(randperm(size(data,1)),:);    %此行代码用于打乱原始样本,使训练集测试集随机被抽取,有助于更新预测结果。
input=data(:,1:end-1);
output1 =data(:,end);
%把输出从1维变成3维
for i=1:size(data,1)
    switch output1(i)
        case 1
            output(i,:)=[1 0 0];
        case 2
            output(i,:)=[0 1 0];
        case 3
            output(i,:)=[0 0 1];
     end
end
 
%% 选取训练数据和测试数据
m=fix(size(data,1)*0.7);    %训练的样本数目
input_train=input(1:m,:)';
output_train=output(1:m,:)';
input_test=input(m+1:end,:)';
output_test=output(m+1:end,:)';
%% 数据归一化
[inputn,inputps]=mapminmax(input_train,0,1);
% [outputn,outputps]=mapminmax(output_train);
inputn_test=mapminmax('apply',input_test,inputps);
%网络结构
innum=size(input,2);
midnum=20;
outnum=size(output,2);
%权值阈值初始化
w1=rand(midnum,innum);
b1=rand(midnum,1);
w2=rand(midnum,outnum);
b2=rand(outnum,1);
w2_1=w2;w2_2=w2_1;
w1_1=w1;w1_2=w1_1;
b1_1=b1;b1_2=b1_1;
b2_1=b2;b2_2=b2_1;
xite=0.0002;
xite2 =  0.001;


I=zeros(1,midnum);
Iout=zeros(1,midnum);
FI=zeros(1,midnum);
dw1=zeros(innum,midnum);
db1=zeros(1,midnum);
loopNumber = 2000;
fprintf('自适应学习率,training is begining……\n');
tic
for ii=1:loopNumber
  SSE(ii)=0; %训练误差
   for i=1:1:size(inputn,2)
    %选择本次训练数据
     x=inputn(:,i);
%      隐含层输出
    for j=1:1:midnum
          I(j)=inputn(:,i)'*w1(j,:)'+b1(j);
          Iout(j)=1/(1+exp(-I(j)));
    end
    %输出层输出
    yn=w2'*Iout'+b2;
    %预测误差
    e=output_train(:,i)-yn;
    SSE(ii)=SSE(ii)+1/2*sum(e.^2);
    %计算w2.b2调整量
    dw2=e*Iout;
    db2=e';
    %计算w1 b1调整量
    for j=1:1:midnum
      S=1/(1+exp(-I(j)));
      FI(j)=S*(1-S);
    end
    for k=1:1:innum
      for j=1:1:midnum
          hh = 0;
          for ij = 1:size(e,1)
              hh = hh +e(ij)*w2(j,ij);
          end
          dw1(k,j)=FI(j)*x(k)*hh;
          db1(j)=FI(j)*hh;
      end
    end




    %权值阈值更新
        ff(ii) = xite2-ii*(xite2-xite)/loopNumber; %自适应学习率核心公式
        w1=w1_1+ff(ii)*dw1';
        b1=b1_1+ff(ii)*db1';
        w2=w2_1+ff(ii)*dw2';
        b2=b2_1+ff(ii)*db2';
        
        w1_2=w1_1;w1_1=w1;
        w2_2=w2_1;w2_1=w2;
        b1_2=b1_1;b1_1=b1;
        b2_2=b2_1;b2_1=b2;  
   end
     SSE(ii) = SSE(ii)/size(inputn,2);
    if mod(ii,500)== 0
       disp(['训练过程:',num2str(ii), '/', num2str(loopNumber),'误差为:',num2str(SSE(ii))])
   end
end
disp( ['训练时间: ',num2str(toc) ] );


%% 将优化的权值阈值带入,用测试集求解
for i=1:1:size(inputn_test,2)
    for j=1:1:midnum
          I(j)=inputn_test(:,i)'*w1(j,:)'+b1(j);
          Iout(j)=1/(1+exp(-I(j)));
    end
    %输出层输出
    yn=w2'*Iout'+b2;
    an0(:,i) = yn;
end


predict_label=zeros(1,size(an0,2));
for i=1:size(an0,2)
    predict_label(i)=find(an0(:,i)==max(an0(:,i)));
end
outputt=zeros(1,size(output_test,2));
for i=1:size(output_test,2)
    outputt(i)=find(output_test(:,i)==max(output_test(:,i)));
end
fprintf('test is over and plot begining……\n');
accuracy=sum(outputt==predict_label)/length(predict_label);   %计算预测的确率
disp(['准确率:',num2str(accuracy*100),'%'])
% 作图
figure
stem(1:length(predict_label),predict_label,'b^')
hold on
stem(1:length(predict_label),outputt,'r*')
legend('预测类别','真实类别','NorthWest')
title({'BP神经网络的预测效果',['测试集正确率 = ',num2str(accuracy*100),' %']})
xlabel('预测样本编号')
ylabel('分类结果')
set(gca,'fontsize',10)
%输出准确率
disp('---------------------------测试准确率-------------------------')
 disp(['准确率:',num2str(accuracy*100),'%'])
% 画方框图
confMat = confusionmat(outputt,predict_label);  %output_test是真实值标签
figure;
set(gcf,'unit','centimeters','position',[15 5 20 15])
yanseplot(confMat.');  
xlabel('Predicted label')
ylabel('Real label')
set(gca,'fontsize',10)
hold off


%% 对训练集进行测试


for i=1:1:size(inputn,2)
    for j=1:1:midnum
          I(j)=inputn(:,i)'*w1_1(j,:)'+b1_1(j);
          Iout(j)=1/(1+exp(-I(j)));
    end
    %输出层输出
    yn=w2_1'*Iout'+b2_1;
    an1(:,i) = yn;
end


predict_label2=zeros(1,size(an1,2));
for i=1:size(an1,2)
    predict_label2(i)=find(an1(:,i)==max(an1(:,i)));
end
outputt2=zeros(1,size(output_train,2));
for i=1:size(output_train,2)
    outputt2(i)=find(output_train(:,i)==max(output_train(:,i)));
end
fprintf('test is over and plot begining……\n');
accuracy=sum(outputt2==predict_label2)/length(predict_label2);   %计算预测的确率
 % 作图
figure
stem(1:length(predict_label2),predict_label2,'b^')
hold on
stem(1:length(predict_label2),outputt2,'r*')
legend('预测类别','真实类别','NorthWest')
title({'BP神经网络的预测效果',['训练集正确率 = ',num2str(accuracy*100),' %']})
xlabel('预测样本编号')
ylabel('分类结果')
set(gca,'fontsize',12)
%输出准确率
disp('---------------------------训练集准确率-------------------------')
 disp(['训练集准确率:',num2str(accuracy*100),'%'])
% 画方框图
confMat = confusionmat(outputt2,predict_label2);  %output_test是真实值标签
figure;
set(gcf,'unit','centimeters','position',[15 5 13 9])
yanseplot(confMat.');  
xlabel('Predicted label')
ylabel('Real label')
hold off




figure
plot(SSE)
title('误差曲线')
ylabel('误差')
xlabel('迭代次数')


figure
plot(ff)
title('自适应学习率变化曲线')
ylabel('学习速度')
xlabel('迭代次数')

下面直接上结果图。

首先是训练集的测试结果图:

b09520da17a8763cc1f5c64abb419b6e.png

测试集的训练结果图:

8b330984365ccfaeecaa48eb8cef24b9.png

同样,再附一张训练集的热力图。(热力图的效果和第一张图是一致的,在类别情况较多时,多采用热力图)

dc5c6ad0b396d4ffff4a11120d0408fc.png

可以看到,手写的附加动量因子的BP神经网络matlab代码,可以实现对红酒数据的精准识别,测试集的识别率高达98.14%。

由于BP神经网络的偶然性,建议大家多运行几次,除此之外,隐含层节点个数,自适应学习率的上下限值,都是可以自行调整的。大家根据自己的项目随意调整即可。

UCI常用数据集链接

https://pan.baidu.com/s/10gYszv5_BCfr43RMLOVXVQ?pwd=8888

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
以下是一个基本的 MATLAB 代码,用于创建和训练一个简单的 BP 神经网络,不使用工具箱: 1. 创建网络结构 ```matlab inputSize = 4; % 输入层大小 hiddenSize = 5; % 隐藏层大小 outputSize = 3; % 输出层大小 % 随机初始化权重和阈值 W1 = rand(hiddenSize, inputSize); % 输入层到隐藏层的权重矩阵 b1 = rand(hiddenSize, 1); % 隐藏层的偏置向量 W2 = rand(outputSize, hiddenSize); % 隐藏层到输出层的权重矩阵 b2 = rand(outputSize, 1); % 输出层的偏置向量 ``` 2. 设置训练参数 ```matlab learning_rate = 0.1; % 学习率 epochs = 1000; % 迭代次数 goal = 0.01; % 训练误差目标 ``` 3. 准备数据集 ```matlab load iris_dataset.mat % 载入数据集 inputs = irisInputs; % 输入数据 targets = irisTargets; % 目标数据 ``` 4. 训练网络 ```matlab for epoch = 1:epochs % 随机打乱数据集 order = randperm(size(inputs, 2)); inputs = inputs(:, order); targets = targets(:, order); % 前向传播 z1 = W1 * inputs + b1; a1 = sigmoid(z1); z2 = W2 * a1 + b2; a2 = sigmoid(z2); % 计算误差 error = targets - a2; mse(epoch) = mean(mean(error.^2)); % 反向传播 delta2 = error .* sigmoid_derivative(a2); delta1 = (W2' * delta2) .* sigmoid_derivative(a1); % 更新权重和阈值 W2 = W2 + learning_rate * delta2 * a1'; b2 = b2 + learning_rate * delta2; W1 = W1 + learning_rate * delta1 * inputs'; b1 = b1 + learning_rate * delta1; % 判断是否达到训练误差目标 if mse(epoch) < goal break; end end ``` 5. 测试网络 ```matlab outputs = zeros(outputSize, size(inputs, 2)); for i = 1:size(inputs, 2) z1 = W1 * inputs(:, i) + b1; a1 = sigmoid(z1); z2 = W2 * a1 + b2; a2 = sigmoid(z2); outputs(:, i) = a2; end ``` 其中,sigmoid 函数和其导数的实现如下: ```matlab function y = sigmoid(x) y = 1 ./ (1 + exp(-x)); end function y = sigmoid_derivative(x) y = sigmoid(x) .* (1 - sigmoid(x)); end ``` 这是一个简单的示例,您可以根据您的具体应用程序进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天吃饺子

不想刀我的可以选择爱我

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值