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


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

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

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

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

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

    首先是主程序代码:

    1. close all
    2. warning off
    3. %% 数据读取
    4. clc
    5. clear
    6. load Wine
    7. %% 数据载入
    8. data=Wine;
    9. data=data(randperm(size(data,1)),:); %此行代码用于打乱原始样本,使训练集测试集随机被抽取,有助于更新预测结果。
    10. input=data(:,1:end-1);
    11. output1 =data(:,end);
    12. %把输出从1维变成3
    13. for i=1:size(data,1)
    14. switch output1(i)
    15. case 1
    16. output(i,:)=[1 0 0];
    17. case 2
    18. output(i,:)=[0 1 0];
    19. case 3
    20. output(i,:)=[0 0 1];
    21. end
    22. end
    23. %% 选取训练数据和测试数据
    24. m=fix(size(data,1)*0.7); %训练的样本数目
    25. input_train=input(1:m,:)';
    26. output_train=output(1:m,:)';
    27. input_test=input(m+1:end,:)';
    28. output_test=output(m+1:end,:)';
    29. %% 数据归一化
    30. [inputn,inputps]=mapminmax(input_train,0,1);
    31. % [outputn,outputps]=mapminmax(output_train);
    32. inputn_test=mapminmax('apply',input_test,inputps);
    33. %网络结构
    34. innum=size(input,2);
    35. midnum=20;
    36. outnum=size(output,2);
    37. %权值阈值初始化
    38. w1=rand(midnum,innum);
    39. b1=rand(midnum,1);
    40. w2=rand(midnum,outnum);
    41. b2=rand(outnum,1);
    42. w2_1=w2;w2_2=w2_1;
    43. w1_1=w1;w1_2=w1_1;
    44. b1_1=b1;b1_2=b1_1;
    45. b2_1=b2;b2_2=b2_1;
    46. xite=0.0002;
    47. xite2 = 0.001;
    48. I=zeros(1,midnum);
    49. Iout=zeros(1,midnum);
    50. FI=zeros(1,midnum);
    51. dw1=zeros(innum,midnum);
    52. db1=zeros(1,midnum);
    53. loopNumber = 2000;
    54. fprintf('自适应学习率,training is begining……\n');
    55. tic
    56. for ii=1:loopNumber
    57. SSE(ii)=0; %训练误差
    58. for i=1:1:size(inputn,2)
    59. %选择本次训练数据
    60. x=inputn(:,i);
    61. % 隐含层输出
    62. for j=1:1:midnum
    63. I(j)=inputn(:,i)'*w1(j,:)'+b1(j);
    64. Iout(j)=1/(1+exp(-I(j)));
    65. end
    66. %输出层输出
    67. yn=w2'*Iout'+b2;
    68. %预测误差
    69. e=output_train(:,i)-yn;
    70. SSE(ii)=SSE(ii)+1/2*sum(e.^2);
    71. %计算w2.b2调整量
    72. dw2=e*Iout;
    73. db2=e';
    74. %计算w1 b1调整量
    75. for j=1:1:midnum
    76. S=1/(1+exp(-I(j)));
    77. FI(j)=S*(1-S);
    78. end
    79. for k=1:1:innum
    80. for j=1:1:midnum
    81. hh = 0;
    82. for ij = 1:size(e,1)
    83. hh = hh +e(ij)*w2(j,ij);
    84. end
    85. dw1(k,j)=FI(j)*x(k)*hh;
    86. db1(j)=FI(j)*hh;
    87. end
    88. end
    89. %权值阈值更新
    90.         ff(ii) = xite2-ii*(xite2-xite)/loopNumber; %自适应学习率核心公式
    91. w1=w1_1+ff(ii)*dw1';
    92. b1=b1_1+ff(ii)*db1';
    93. w2=w2_1+ff(ii)*dw2';
    94. b2=b2_1+ff(ii)*db2';
    95. w1_2=w1_1;w1_1=w1;
    96. w2_2=w2_1;w2_1=w2;
    97. b1_2=b1_1;b1_1=b1;
    98. b2_2=b2_1;b2_1=b2;
    99. end
    100. SSE(ii) = SSE(ii)/size(inputn,2);
    101. if mod(ii,500)== 0
    102. disp(['训练过程:',num2str(ii), '/', num2str(loopNumber),'误差为:',num2str(SSE(ii))])
    103. end
    104. end
    105. disp( ['训练时间: ',num2str(toc) ] );
    106. %% 将优化的权值阈值带入,用测试集求解
    107. for i=1:1:size(inputn_test,2)
    108. for j=1:1:midnum
    109. I(j)=inputn_test(:,i)'*w1(j,:)'+b1(j);
    110. Iout(j)=1/(1+exp(-I(j)));
    111. end
    112. %输出层输出
    113. yn=w2'*Iout'+b2;
    114. an0(:,i) = yn;
    115. end
    116. predict_label=zeros(1,size(an0,2));
    117. for i=1:size(an0,2)
    118. predict_label(i)=find(an0(:,i)==max(an0(:,i)));
    119. end
    120. outputt=zeros(1,size(output_test,2));
    121. for i=1:size(output_test,2)
    122. outputt(i)=find(output_test(:,i)==max(output_test(:,i)));
    123. end
    124. fprintf('test is over and plot begining……\n');
    125. accuracy=sum(outputt==predict_label)/length(predict_label); %计算预测的确率
    126. disp(['准确率:',num2str(accuracy*100),'%'])
    1. % 作图
    2. figure
    3. stem(1:length(predict_label),predict_label,'b^')
    4. hold on
    5. stem(1:length(predict_label),outputt,'r*')
    6. legend('预测类别','真实类别','NorthWest')
    7. title({'BP神经网络的预测效果',['测试集正确率 = ',num2str(accuracy*100),' %']})
    8. xlabel('预测样本编号')
    9. ylabel('分类结果')
    10. set(gca,'fontsize',10)
    11. %输出准确率
    12. disp('---------------------------测试准确率-------------------------')
    13. disp(['准确率:',num2str(accuracy*100),'%'])
    14. % 画方框图
    15. confMat = confusionmat(outputt,predict_label); %output_test是真实值标签
    16. figure;
    17. set(gcf,'unit','centimeters','position',[15 5 20 15])
    18. yanseplot(confMat.');
    19. xlabel('Predicted label')
    20. ylabel('Real label')
    21. set(gca,'fontsize',10)
    22. hold off
    23. %% 对训练集进行测试
    24. for i=1:1:size(inputn,2)
    25. for j=1:1:midnum
    26. I(j)=inputn(:,i)'*w1_1(j,:)'+b1_1(j);
    27. Iout(j)=1/(1+exp(-I(j)));
    28. end
    29. %输出层输出
    30. yn=w2_1'*Iout'+b2_1;
    31. an1(:,i) = yn;
    32. end
    33. predict_label2=zeros(1,size(an1,2));
    34. for i=1:size(an1,2)
    35. predict_label2(i)=find(an1(:,i)==max(an1(:,i)));
    36. end
    37. outputt2=zeros(1,size(output_train,2));
    38. for i=1:size(output_train,2)
    39. outputt2(i)=find(output_train(:,i)==max(output_train(:,i)));
    40. end
    41. fprintf('test is over and plot begining……\n');
    42. accuracy=sum(outputt2==predict_label2)/length(predict_label2); %计算预测的确率
    43. % 作图
    44. figure
    45. stem(1:length(predict_label2),predict_label2,'b^')
    46. hold on
    47. stem(1:length(predict_label2),outputt2,'r*')
    48. legend('预测类别','真实类别','NorthWest')
    49. title({'BP神经网络的预测效果',['训练集正确率 = ',num2str(accuracy*100),' %']})
    50. xlabel('预测样本编号')
    51. ylabel('分类结果')
    52. set(gca,'fontsize',12)
    53. %输出准确率
    54. disp('---------------------------训练集准确率-------------------------')
    55. disp(['训练集准确率:',num2str(accuracy*100),'%'])
    56. % 画方框图
    57. confMat = confusionmat(outputt2,predict_label2); %output_test是真实值标签
    58. figure;
    59. set(gcf,'unit','centimeters','position',[15 5 13 9])
    60. yanseplot(confMat.');
    61. xlabel('Predicted label')
    62. ylabel('Real label')
    63. hold off
    64. figure
    65. plot(SSE)
    66. title('误差曲线')
    67. ylabel('误差')
    68. xlabel('迭代次数')
    69. figure
    70. plot(ff)
    71. title('自适应学习率变化曲线')
    72. ylabel('学习速度')
    73. xlabel('迭代次数')

    下面直接上结果图。

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

    b09520da17a8763cc1f5c64abb419b6e.png

    测试集的训练结果图:

    8b330984365ccfaeecaa48eb8cef24b9.png

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

    dc5c6ad0b396d4ffff4a11120d0408fc.png

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

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

    UCI常用数据集链接

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

  • 相关阅读:
    三面头条+四面阿里+五面腾讯拿offer分享面经总结,最终入职阿里
    React 中的 ref 如何操作 dom节点,使输入框获取焦点
    springfox-swagger2 2.9.2 POST方式 Description优化
    点云切片的实现(PCL)C++
    C#开发的OpenRA游戏之金钱系统(5)
    10、JAVA入门——多重循环及程序调试
    C++并发编程 - 同步并发操作
    一个很少见但很有用的SQL功能
    go操作mysql
    LeetCode_88_合并两个有序数组
  • 原文地址:https://blog.csdn.net/woaipythonmeme/article/details/133875102