fugarfield 2022-09-01 15:32 采纳率: 0%
浏览 131
已结题

用matlab写bp算法,遇到的问题

想自己用matlab写bp神经网络,看了好多网上bp算法的视频,自己写的思路和视频里基本一致,在这里叙述一下我自己写的过程。先说下我理解的bp算法,不知道是不是对的。
比如是2维输入,一层隐含层,6个隐含层单元,3个输出。
前向传播:输入单元接收输入,输入和权值相乘并加上对应隐含层的阈值,再经过激活函数,激活函数的输出再乘以权值并加上对应输出单元的阈值,再经过激活函数,这就是输出了。
bp反馈:用输出值和期望值做方差,得到误差函数,用每一个权值和阈值分别对误差函数求偏导,导数是正的就减小权值或阈值,导数是负的就增大权值或阈值。一直迭代,直到误差函数小于一定的值。
我想的bp算法应该在我输入第一组数据后,3个输出单元会输出1 0 0;第二组数据则会输出 0 1 0
第三组数据则输出 0 0 1;

一共写了两种方式。

第一种:总体结构是2个输入单元,一层隐含层,隐含层有6个单元,3个输出单元。先训练一组数据,直到误差函数的值很小后再换另一组数据训练,如此下去。

第一步
随机设置参数,0~1内。参数包括了,输入层到隐含层的权值v,隐含层的阈值r,隐含层到输出层的权值w,输出层的阈值h。学习率k=0.1,误差函数E。
第二步,前向传播,并反馈修改权值,每组数据迭代100次再换数据
第三步,直接查看输出的值y_hat
代码:

clear;clc
x=[17,17,17];
C=[41,42,43];
[r,h,v,w,E,y_hat]=standard_BP(x,C,1e-6);
function [r,h,v,w,E,y_hat]=standard_BP(x,C,eps)  %q为隐层单元数目,eps均方误差限
    q=6;    %隐含层单元数目
    L=3;    %输出单元数目
    n=2;  %获取数据的维度
    v=rand(n,q);  %初始化输入层到隐含层的权值
    r=rand(1,q);    %初始化隐含层的阀值
    w=rand(q,L);  %初始化隐含层到输出层的权值
    h=rand(1,L);    %初始化输出层的阀值
    k=0.1;        %学习率
    E=0;
for t=1:3           %每组数据训练多次,并多次修改权值,降低误差,一共三组数据
    Y=[1 0 0];
    Y1=[0 1 0];
    Y2=[0 0 1];
    Y3=[Y(t) Y1(t) Y2(t)];  %期望值
    N=100;  %迭代100次
while N>1
    a=[x(t) C(t) ];
    A=a*v;
    b=fc_sigmod(A-r);     %经过隐含层的激活函数的输出
    B=b*w;       %隐含层->输出层,各个输出层单元具有的权值
    y_hat=fc_sigmod(B-h); %经过输出层的激活函数的输出
    E=0.5*sum((y_hat-Y3).^2);  %求均方误差
    %yn=y_hat.*y(t);
    g=y_hat.*(Y3-y_hat).*(1-y_hat);
    e=b.*(1-b).*(w*g')';
          v=v+k*a'*e;     %输入层->隐含层的权值更新
    r=r-k*e;              %隐含层的阀值更新
          w=w+(k*g'*b)';  %隐含层->输出层的权值更新
    h=h-k*g; %隐含层的阀值更新
    N=N-1;
end
end
for t=1:3         %依次输入三组数据,检测输出
Y3=[Y(t) Y1(t) Y2(t)];
    a=[x(t) C(t) ];
    A=a*v;
    b=fc_sigmod(A-r);     
    B=b*w;       
    y_hat=fc_sigmod(B-h); 
    E=0.5*sum((y_hat-Y3).^2);
    y_hat
    E
end
function y=fc_sigmod(x)
y=1./(1+exp(-x));
end
end

程序结束。
如果训练成功,结果应该是输入第一组数据,输出则会输出y_hat=[1 0 0],但是实际情况是三组数据训练之后,无论怎么输入都会输出y_hat=[0 0 1],也就是只有最后一组的数据训练有效了,前面两组数据没有作用。

第二种,总体结构是2个输入单元,两层隐含层,每层隐含层有6个单元,3个输出单元。每组数据只训练一次,连续训练三组数据后再循环三次,如此下去。

第一步,初始化
第二步,前向传播,并反馈,每组数据训练一次,并修改一次权值,三组全训练后再重新进行一轮
第三步 看训练结果

clear;clc
x=[17,17,17];
C=[44,45,46];
y=[0.1,0.2,0.3];
[r,h,v,w,E]=standard_BP(x,C,1e-6);
function [r,h,v,w,E]=standard_BP(x,C,eps) 
q=6;    %隐层单元数目
L=3;%length(y);    %输出单元数目
n=2;%length(x);  %获取数据的维度
v=rand(n,q);    %初始化输入层到隐层的权值
r=rand(1,q);    %初始化隐层1的阀值
s=rand(q,q);     %隐层到隐层的权值
d=rand(1,q);   %隐层2的阈值
w=rand(q,L);   %初始化隐层2到输出层的权值
h=rand(1,L);   %初始化输出层的阀值
k=0.1;         %学习率
E=0;    
M=1000;
while M>1
for t=1:3        %每组数据训练一次,并修改一次权值,三组数据全训练后多次循环降低误差
   Y = [1 0 0];
  Y1= [0 1 0];
   Y2= [0 0 1];
   Y3=[Y(t) Y1(t) Y2(t)]; %期望值
   N=2;
while N>1
    a=[x(t) C(t)];
    A=a*v+r;               
    b=fc_sigmod(A);     
    F=b*s+d;                  
    u=fc_sigmod(F);     
    B=u*w+h;              
    y_hat=fc_sigmod(B); 
    E=0.5*sum((y_hat-Y3).^2);   %误差函数
    g=y_hat.*(Y3-y_hat).*(1-y_hat);
    eb=b.*(1-b).*(w*g')';
    eu=u.*(1-u).*(w*g')';
    v=v+k*a'*eb*s.*u.*(1-u);  %更新权值和阈值
    r=r+k*eb*s.*u.*(1-u) ;  
    s=s+k*b'*eu;
    d=d+k*eu;
    w=w+(k*g'*u)';  
    h=h+k*g;  
    N=N-1;
 end
 end
M=M-1;
end
for t=1:3  %依次输入三组数据,检测输出
    Y3=[Y(t) Y1(t) Y2(t)];
    a=[x(t) C(t)];
    A=a*v;               
    b=fc_sigmod(A+r);     
    F=b*s;                  
    u=fc_sigmod(F+d);     
    B=u*w;             
    y_hat=fc_sigmod(B+h); 
    E=0.5*sum((y_hat-Y3).^2);
y_hat
E
end
end

如果训练成功,则在输入第一组数据时,输出应该为 y_hat=[1 0 0],但是实际输出的却是 y_hat=[0.33 0.33 0.33],而且三组数据的输出都是如此。好像是三组数据被求了均值一样。

过程公式都是自己写的,对照网上公式推导,觉得自己应该没有推错。
也不知道是自己对bp算法的理解不对还是什么?
不知道是哪里不对,bp算法到底是怎么训练的?

  • 写回答

2条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2022-09-01 16:24
    关注
    评论

报告相同问题?

问题事件

  • 系统已结题 9月9日
  • 修改了问题 9月2日
  • 赞助了问题酬金20元 9月1日
  • 赞助了问题酬金10元 9月1日
  • 展开全部

悬赏问题

  • ¥50 rk3588板端推理
  • ¥50 opencv怎么去掉 数字0中间的斜杠。
  • ¥15 这种情况的伯德图和奈奎斯特曲线怎么分析?
  • ¥50 paddleocr带斜线的0很容易识别成9
  • ¥15 电子档案元素采集(tiff及PDF扫描图片)
  • ¥15 flink-sql-connector-rabbitmq使用
  • ¥15 zynq7015,PCIE读写延时偏大
  • ¥15 使用spss做psm(倾向性评分匹配)遇到问题
  • ¥20 vue+UEditor附件上传问题
  • ¥15 想做个WPS的自动化代码,不知道能做的起不。