1. 程式人生 > >機器學習之實戰matlab神經網路工具箱

機器學習之實戰matlab神經網路工具箱

上節在

中,我們已經從原理上介紹了神經網路演算法的來源與構造,並程式設計實戰了簡單神經網路對於線性與非線性資料的分類測試實驗。看過上節的可能會發現,上節實現的演算法對於非線性資料的分類效果並不是非常完美,有許多值得優化的地方。而matlab作為一個科學計算軟體,本身集成了非常多的優化演算法,其中的神經網路工具箱就是其中一個優秀的工具箱,本節將以工具箱中的函式重新實驗上節中的分類實驗。

首先來了解這個工具箱。我們說,一個簡單的神經網路就如下圖所示:
這裡寫圖片描述
這是我們上節用過的網路,含有兩層,每層3個節點的網路。然而已經證明,其實只含有一個隱含層的網路是可以擬合出任意有限的輸入輸出對映問題的。基於此,在matlab整合的工具箱中我們只能看到只含有一個隱含層的網路,而網路的節點個數卻是我們可以需要改變與設計的。簡單來工具箱的一個簡單神經網路可以表示如下:
這裡寫圖片描述


通過輸入然後對映到輸出,輸出在對映到最終輸出。整個網路包含權值w、v和常數b。網路需要設計的就是確定隱含層的節點個數(matlab預設10),同時對映函式需要注意,上節我們預設的都是採用sigmod函式,然而matlab預設的是隱含層輸出採用sigmod,而輸出後的對映採用的是線性對映,像上圖中的在輸出部分的紅色所示。其實除了這兩種對映函式外,還有正切等等函式,可以作為對映函式的共同點就是他們都是可導的(這是原理推導上所必須的)。那麼matlab預設輸出對映為什麼是線性的而不是sigmod的呢?我們知道sigmod函式會把資料對映到0-1之間,然而我們實際應用中獲得的資料的目標值(分類標籤)並不一定都在0-1之間,那麼如果用sigmod函式,那麼我們需要把原始資料的目標輸出轉化到0-1之間,而線性對映就沒有這個問題(因為它對映後的資料沒有上下限)。

好了下面說說關於幾個重要的函式:

  1. 網路建立函式:feedforwardnet(hiddenSizes,trainFcn) ,(matlab2012後較新的版本),在老版本的matlab,這個函式是newff。這個函式就是建立一個上述的(前饋)網路,包括兩個引數,第一個hiddenSizes隱藏層的大小(實際就是節點數的多少,預設10),trainFcn是網路訓練所採取的方法,這個方法包括:梯度下降演算法、動量梯度下降演算法、變學習率梯度下降演算法等等數10種方法,各種方法各有優缺點,而有代表性的方法是有代表性的五種演算法為:’traingdx’,’trainrp’,’trainscg’,’trainoss’,’trainlm’,預設的是’trainlm’。其實不需要了解的太詳細,一般的資料預設的方法就非常的好了,所以這個引數可以不用管。給一個詳細介紹這個函式的連結:

  2. 好了網路建立完以後,下面就是訓練網路的引數了,這裡的引數就是權值矩陣w,v,以及常數矩陣b。函式是train,關於這個函式其實可以有很多引數,也可以只有幾個引數,因為好多引數都是有預設,而採用預設值就可以得到很好的效果,比如迭代次數,訓練最小的允許誤差等等。這裡只說幾個重要的引數,
    1.第一個引數,上述建立的網路net,
    2.第二個,訓練資料,
    3.第三個,與訓練資料對應的資料目標值(分類標籤或者輸出值等),這個輸出值不光可以是一維的,還可以是多維的。

而train函數出來的就是訓練好的網路net,matlab出來的net是一個結構體資料,裡面包括了網路的所有資訊(訓練方法,誤差,包括我們熟悉的權值矩陣w,b等等),那麼我們是否需要把w與b在提取出來呢?並不需要,在實際應用中,我們可以直接把需要測試的資料輸入到net中就可以了。比如說現在網路訓練好了就是net,那麼來了一個測試樣本sample,那麼它的輸出值就是net(sample),這樣就可以達到預測的目的了。

好了,瞭解這些就可以實驗了,還有許多詳細的細節部分也可以改變,用不到的說多了可能也沒有用就不說了。

下面同樣實驗上一節的兩組人造樣本集,線性集與非線性集,畫出來如下:
這裡寫圖片描述
這裡寫圖片描述
程式碼如下:

%%  
% * matlab自帶神經網路工具箱的分類設計
% * 線性與非線性分類
% 
%% 
clc
clear
close all
%% Load data
% * 資料預處理--分兩類情況
data = load('data_test1.mat');
data = data.data';
% 將標籤設定為0,1
data(:,3) = data(:,3) - 1;
%選擇訓練樣本個數
num_train = 80;
%構造隨機選擇序列
choose = randperm(length(data));
train_data = data(choose(1:num_train),:);
gscatter(train_data(:,1),train_data(:,2),train_data(:,3));
label_train = train_data(:,end);
test_data = data(choose(num_train+1:end),:);
label_test = test_data(:,end);
%% 神經網路的構建與訓練
% 構造神經網路(包含10個隱藏層的節點)
net = feedforwardnet(10);
% net.layers{2}.transferFcn = 'tansig';% 輸出的對映方法,預設purelin--線性對映
% 訓練網路
net = train(net,train_data(:,1:end-1)',label_train');
% 顯示構造的網路
view(net);
% 用這個網路來預測測試集的分類
y_test = net(test_data(:,1:end-1)');
%輸出的值四捨五入,認為大於0.5的屬於類‘1’,其他的屬於類‘0’
predict = round(abs(y_test));

%% 顯示結果--測試訓
figure;
index1 = find(predict==0);
data1 = (test_data(index1,:))';
plot(data1(1,:),data1(2,:),'or');
hold on
index2 = find(predict==1);
data2 = (test_data(index2,:))';
plot(data2(1,:),data2(2,:),'*');
hold on
indexw = find(predict'~=(label_test));
dataw = (test_data(indexw,:))';
plot(dataw(1,:),dataw(2,:),'+g','LineWidth',3);
accuracy = length(find(predict'==label_test))/length(test_data);
title(['predict the training data and the accuracy is :',num2str(accuracy)]);

首先載入線性資料集:
這裡寫圖片描述
這裡寫圖片描述

綠色為錯分的點,程式中我們採用的是10個隱含層節點,同時輸出採用的預設的對映—線性對映。程式中也有sigmod對映(對應的註釋掉的地方)。

下面進行非線性資料的測試:
這裡寫圖片描述
同樣,綠色為錯分的點。可以看到,準確率終於上升到80%以上(與上節對比,基本上不可能)。這裡我們再把輸出對映也改為sigmod對映,因為我們的輸出標籤已經改到了0、1標籤,輸入就在0-1之間,所以可以直接用。將上述對應的註釋去掉,改完後的結果如下:
這裡寫圖片描述
可以看到輸出採用sigmod函式效果似乎更好些。同時再來看看畫出來的網路結構:
這裡寫圖片描述
看這個結果和上面那個結構,你發現了什麼?是不是輸出層的對映關係變化了。

這就是matlab下基本神經網路的訓練與預測實驗,其神經網路工具箱功能遠遠不止這。同時我這是採用函式命令實現的,matlab對於神經網路集成了GUI功能,可以直接在圖形介面操作。在命令視窗輸入:nnstart就會出現下面GUI介面:
這裡寫圖片描述
可以看到matlab下神經網路主要有四個方向用途:擬合數據,模式識別與分類資料,聚類資料,時間序列模型的資料處理,可以看到,我們這篇的這個問題其實是輸入模式分類資料這部分的,考慮篇幅有限,感興趣自己可以去詳細研究其他用途,異常的強大。

總結一下該部分,matlab自帶神經網路工具箱相比上節自己編的,對於線性資料準確率大概差不多,但是對於非線性資料的劃分,工具箱的函式效果優化的非常好,同時用法也簡單,運算速度快,可以說是一個非常好的一個分類方法。