1. 程式人生 > >大白話5分鐘帶你走進人工智慧-第35節神經網路之sklearn中的MLP實戰(3)

大白話5分鐘帶你走進人工智慧-第35節神經網路之sklearn中的MLP實戰(3)

本節的話我們開始講解sklearn裡面的實戰:

先看下程式碼:

 

from sklearn.neural_network import MLPClassifier

X = [[0, 0],
     [1, 1]]
y = [0, 1]

clf = MLPClassifier(solver='sgd', alpha=1e-5, activation='logistic',
                    hidden_layer_sizes=(5, 2), max_iter=2000, tol=1e-4)
clf.fit(X, y)

predicted_value = clf.predict([[2, 2],
                               [-1, -2]])
print(predicted_value)
predicted_proba = clf.predict_proba([[2., 2.],
                                     [-1., -2.]])
print(predicted_proba)

print([coef.shape for coef in clf.coefs_])
print([coef for coef in clf.coefs_])

 

 

 

我們依次解釋下:

在sklearn裡面,我們需要

from sklearn.neural_network import MLPClassifier

這樣來匯入神經網路這個模組,如果做分類,就是MLPClassifier,它和神經網路什麼關係?它叫做多層感知機。這裡是用它做分類的一個演算法。

接下來



X = [[0, 0],
     [1, 1]]
y = [0, 1]

 

人為地構建了一個數據集, X矩陣裡面有兩行兩列, Y是構建了兩行一列,分別是分類號,負例和正例。

如何使用多層感知機呢?

先建立一個物件MLPClassifier:



clf = MLPClassifier(solver='sgd', alpha=1e-5, activation='logistic',
                    hidden_layer_sizes=(5, 2), max_iter=2000, tol=1e-4)

 

解釋下這些引數:solver就是選擇最優解的演算法,隨機梯度下降SGD;alpha是L2正則前面的超引數;activation=logistic意味著每一個神經元最後的function是Sigmoid函式;max_iter是最大迭代次數,如果迭代次數達到2000次,我們就把2000的結果作為最優解;tol是收斂的閾值,如果在2000次內達到了閾值,就停了。

我們再來看下MLP的原始碼引數:

學習率是learning_rate,如果是constant就是一直保持學習率的值,如果是invscaling就是根據公式來每次迭代算學習率。

activation如果是logistic,就是sigmod函式;如果是tanh,就是-1到+1;如果是relu,就是max(0,z),平時用的時候就是這些個。

最關鍵的是hidden_layer_sizes隱藏層的節點數:



hidden_layer_sizes=(5, 2)
 

(5,2)意思是有兩個隱藏層,第一個隱藏層有五個神經元,第二個隱藏層有兩個神經元。為什麼要寫成(5,2)?因為如果第一個隱層H1有五個神經元,第二層有兩個神經元,這兩個隱藏層之間要算多少個連線的w呢?就是五行兩列,十個連線上的w。可以直接計算出來。

MLP多層感知機,它其實就只是全連線,如果你不是全連線它就不能叫多層感知機了,而sklearn裡面只有多層感知機。

它是層與層之間的網路拓撲,x資料裡面有兩個x,相當於第一個輸入層有兩個神經元x1,x2。我們把隱藏層設五個隱藏節點,所以隱藏裡分類點就有5個。所以輸入層到第一個隱藏層的w矩陣,它的形狀是兩行五列。

第二個隱藏層設定是兩個神經元,第二個w矩陣就是五行兩列,因為這裡是做一個二分類, Y的標籤裡面就兩個類別號,所以它是做二分類,二分類需要一個輸出節點就夠了。所以最後一個矩陣它是兩行一列。以下是這個網路拓撲結構圖:



clf.fit(X, y)
 

fit後就可以來計算出來最終的w引數、模型。

有了分類器這個模型,我們就可以通過predict進行預測:



predicted_value = clf.predict([[2, 2],
                               [-1, -2]])
 

意思是未來給它一個x,它可以給你y。預測結果如下:

predicted_value是兩行一列的,如果用的是predicted_proba,有什麼區別呢?



predicted_proba = clf.predict_proba([[2., 2.],
                                     [-1., -2.]])
 

在sklearn裡面,用predicted_proba,它給出的是概率值,列印結果如下:



print([coef.shape for coef in clf.coefs_])
 

Clf.coefs_,就是把這些w全部拿出來,然後for迴圈這些w,它是分層的。然後看shape,就可以清晰地知道,從輸入層到第一個隱藏層,中間網路拓撲是什麼樣子的,然後第一個隱藏層到第二個隱藏層,以此類推。如果我們直接把coef的列印輸出的話,我們就可以直接拿到層與層之間的w矩陣具體值是什麼樣子的。結果如下:

我們從線性代數矩陣相乘的概念去解釋最後的輸出:

x資料集是一個兩行兩列的資料:

輸入層和第一個隱藏層之間w矩陣是兩行五列的

 

它們點積兩行兩列*兩行五列=兩行五列的資料。判斷是兩行五列之後,還要再跟第一個隱藏層和第二個隱藏層之間五行兩列的w矩陣相乘,

得到的就是兩行五列*五行兩列=兩行兩列的結果,最後和兩行一列的相乘:

得到的是兩行兩列*兩行一列=兩行一列的ŷ,因為x是兩行,所以最後得到的是兩個ŷ。

完美~~~解釋!!哈哈。

真正去做predict時候,就是把某一條資料帶起來,分別做一個正向傳播,如果用predict,結果和0.5比較進行判別,給出分類號;如果是predict_proba它不用根據0.5進行判別,直接輸出概率。

不管資料量有多少,只要寫的是SGD,就會在每次迭代的時候選x資料集裡面的一部分資料來進行訓練,因為總共2000次迭代,迭代次數越多,相當於所有的資料都會被隨機到。

總結下神經網路需要考慮三件事情:第一個是設定啟用函式,第二個是設定網路拓撲,就是構建一個神經網路時,它有多少層,然後每一層有神經元的個數。這裡是做分類的,輸入和輸出層不用設定,輸入層、輸出層有多少神經元,根據它有多少個x,和y多少個分類,它就會自動設定神經元。把網路拓撲定下來,第三就是需要去設定有多少個隱藏層,每層有多少個神經元,那麼一個元組來表達(5,2),告訴這裡有兩個隱藏層,數值是每個隱藏有多少個神經元。一百層就是元組裡有一百個數。比如三個隱藏層(10,8,15),意思是第一個隱藏層10個神經元,第二個隱藏層8個神經元,第三個隱藏層15個神經元。裡面的值是隨便定的。怎麼設定是沒有方法設定,這個是調的,咱們的工作。後期深度學習裡面咱們說案例,都會去判別它的準確率,然後根據準確率判別有沒有過擬合,在深度學習裡面都會奔著過擬合的方向去調,如果過擬合再往回調。比如設定100個隱藏層,我發現50個隱藏層的效果跟100個一樣,那麼就設定50個,訓練得更快,使用的時候正向傳播也更快,這個值是調的。不同的應用方向,比如卷積神經網路或者迴圈神經網路,引數設定是有一些規律的,它但是沒有一個死的數,還是根據規律來調的。

啟用函式是統一設定的,在神經網路拓撲裡面,每一個神經元的啟用函式都是一樣的,都是統一的,在神經網路裡面是這樣,在深度學習裡面也是這樣。假如設定了ReLU,隱藏層,輸出層,啟用函式都是ReLU,如果是Sigmoid,它都是Sigmoid。對於sklearn來說,就必須得是統一的。

對於tensorflow來說,它給了更多的自由度,可以讓每一層都是一樣的,但是層與層之間可以設定不一樣的。

下面進入Q&A環節:

w矩陣的順序是什麼樣的,也就是每一層和每一層之間的w的形狀是什麼樣的?

比如有兩個隱藏層,第一個隱藏層H1有五個神經元,第二個隱藏層H2有兩個神經元,連線一定是5*2有10個連線,w矩陣就是五行兩列的。

每個神經元的位置誰放上,誰放下無所謂。因為中間的隱藏節點,它具體代表什麼含義是我們不管的,因為我們沒法知道它具體代表什麼含