用BP神经网络解决简单的分类问题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/john_bian/article/details/79501975

有关于BP神经网络原理前人之述备矣,这里就暂且略过。从一年前第一次接触机器学习到现在,已经学习很多类似的智能学习算法,无论是遗传算法、群算法、模拟退火算法还是神经网络算法,在有监督的学习算法中,无非就是设计一个标准和进化方式,让结果与标准之间的误差越来越少,直到误差缩小到允许的范围内并收敛,我们谓之学习成功了。BP神经网络也是这样的,在BP神经网络学习的目标就是输出层输出的结果与真实值的差距尽可能的少。而在更新参数时实际上用的是梯度下降的方法,所以需要计算一些偏导数。而在解决分类问题中,每一层的神经元数目的设定,可以根据数据选择,我目前的建议是输入数据是多少维,输入层就设置多少个神经元,每一个输入层神经元对应一个维度上的分量。数据总共要分成多少类,输出层就设置多少个神经元,比如假设要分为四类,可以设置输入这四类数据时期望的输出分别为[0 0 0 1],[0 0 1 0],[0 1 0 0 ]和[1 0 0 0]。至于隐含层的数目,我目前也不确切的知道应该设置多少个神经元,需要进一步的学习。这两点只是我今天想到的,是一种有点朴素的想法而已。

下面是一个用BP神经网络解决分类问题的MATLAB实现。

clc,clear

load('Data-Ass2.mat');
traindata = data(:,1:2000);
testdata = data(:,2001:3000);

insize = 2;%输入层神经元数目
hidesize = 10;%隐含层神经元数目
outsize = 2;%输出层神经元数目

yita1 = 0.001;%输入层到隐含层之间的学习率
yita2 = 0.001;%隐含层到输出层之间的学习率

W1 = rand(hidesize,insize);%输入层到隐含层之间的权重
W2 = rand(outsize,hidesize);%隐含层到输出层之间的权重
B1 = rand(hidesize,1);%隐含层神经元的阈值
B2 = rand(outsize,1);%输出层神经元的阈值

Y = zeros(2,2000);%期望输出
for i = 1:2000
    y = zeros(2,1);
    if traindata(3,i)==1
        y = [1;0];
    else
        y = [0;1];
    end
    Y(:,i) = y;
end

loop = 1000;
E = zeros(1,loop);
for loopi = 1:loop
    
    for i = 1:2000
        x = traindata(1:2,i);
        
        hidein = W1*x+B1;%隐含层输入值
        hideout = zeros(hidesize,1);%计算隐含层输出值
        for j = 1:hidesize
            hideout(j) = sigmod(hidein(j));
        end
        
        yin = W2*hideout+B2;%输入层输入值
        yout = zeros(outsize,1);%输出层输出值
        for j = 1:outsize
            yout(j) = sigmod(yin(j));
        end
        
        e = yout-Y(:,i);%输出层计算结果误差
        E(loopi) = e(1)+e(2);
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        %后向反馈
        dB2 = zeros(outsize,1);%误差对输出层阈值求偏导,计算阈值变化量
        for j = 1:outsize
            dB2 = sigmod(yin(j))*(1-sigmod(yin(j)))*e(j)*yita2;
        end
        
        %隐含层与输出层之间的权重的变化量
        dW2 = zeros(outsize,hidesize);
        for j = 1:outsize
            for k = 1:hidesize
                dW2(j,k) = sigmod(yin(j))*(1-sigmod(yin(j)))*hideout(k)*e(j)*yita2;
            end
        end
        
        %隐含层阈值变化量
        dB1 = zeros(hidesize,1);
        for j = 1:hidesize
            tempsum = 0;
            for k = 1:outsize
                tempsum = tempsum + sigmod(yin(k))*(1-sigmod(yin(k)))*W2(k,j)*sigmod(hidein(j))*(1-sigmod(hidein(j)))*e(k)*yita1;
            end
            dB1(j) = tempsum;
        end
        
        %输入层到隐含层的权重变化量
        dW1 = zeros(hidesize,insize);
        for j = 1:hidesize
            for k = 1:insize
               tempsum = 0;
               for m = 1:outsize
                   tempsum = tempsum + sigmod(yin(m))*(1-sigmod(yin(m)))*W2(m,j)*sigmod(hidein(j))*(1-sigmod(hidein(j)))*x(k)*e(m)*yita1;
               end
               
               dW1(j,k) = tempsum;
                
            end
            
        end
        
        W1 = W1-dW1;
        W2 = W2-dW2;
        B1 = B1-dB1;
        B2 = B2-dB2;
        
    end
    
    if mod(loopi,100)==0
        loopi
    end
    
end

plot(E);

% %查看训练效果
% tempyout = zeros(2,1000);
% for i = 1:1000
%     x = testdata(1:2,i);
%     
%     hidein = W1*x+B1;%隐含层输入值
%     hideout = zeros(hidesize,1);%隐含层输出值
%     for j = 1:hidesize
%         hideout(j) = sigmod(hidein(j));
%     end
%     
%     yin = W2*hideout+B2;%输出层输入值
%     yout = zeros(outsize,1);
%     for j = 1:outsize
%         yout(j) = sigmod(yin(j));
%     end
%     
%     tempyout(:,i) = yout;
%     
%     if yout(1)>yout(2)
%         scatter(x(1),x(2),'r')
%         hold on;
%     else
%         scatter(x(1),x(2),'g')
%         hold on;
%     end
%       
%     
% end

当迭代1000次时的训练效果和分类效果分别如下

训练效果:

测试效果:

我们可以看到当迭代次数为1000次时,分类的正确率已经比较高了,只有少量点分错。

而当迭代次数达到10000次时的训练效果如下图所示

测试效果:

而当迭代次数达到10000次时,对于图中的数据正确率已经到达了100%。当然在实际情况中,这种结果并不一定好,有可能会出现过拟合的情况。

本实例中所用到的数据可以从链接:https://pan.baidu.com/s/1Uxt9RurmBraFR-SjGquoww 密码:beb1下载。

----------------------------------------补充--------------------------------------------------

有好多同志私信或留言说MATLAB提示缺少sigmod函数,本以为大家都知道的,看来在这里还是需要补充一下。这是属于BP神经网络的基本原理部分,我开头的一句“前人之述备矣”好像是有点不负责任的嫌疑。这个函数就是那个常用的激活函数:

写这么一个函数就可以了

function [ y ] = sigmod( x )
% 激活函数Sigmod,用于神经网络
%   鸿武六年三月七日
y = 1/(1+exp(-x));

end

测试数据的话上面的那个百度云链接好像还没有失效。

如有不当之处,欢迎通过QQ进行深入交流,同时也欢迎通过微信打赏的方式对博主进行支持。

猜你喜欢

转载自blog.csdn.net/john_bian/article/details/79501975