用BP神經網絡解決簡單的分類問題


有關於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
測試數據的話上面的那個百度雲鏈接好像還沒有失效。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章