《機(jī)器學(xué)習(xí)(周志華)》學(xué)習(xí)筆記(五)

Q:什么是人工神經(jīng)網(wǎng)絡(luò)?

人工神經(jīng)網(wǎng)絡(luò)是科學(xué)家模擬人類大腦的神經(jīng)網(wǎng)絡(luò)建立的數(shù)學(xué)模型。人工神經(jīng)網(wǎng)絡(luò)由一個(gè)個(gè)“人工神經(jīng)元”組合而成。“人工神經(jīng)元”也是一個(gè)數(shù)學(xué)模型,其本質(zhì)是一個(gè)函數(shù)。所以人工神經(jīng)網(wǎng)絡(luò)的本質(zhì)也是一個(gè)函數(shù),而且是一個(gè)復(fù)雜的,包含很多變量和參數(shù)的函數(shù)。

前饋神經(jīng)網(wǎng)絡(luò):最簡(jiǎn)單的神經(jīng)網(wǎng)絡(luò)

Q:什么是人工神經(jīng)元?

人工神經(jīng)元是人工神經(jīng)網(wǎng)絡(luò)的基本單元,其本質(zhì)也是一個(gè)函數(shù)。類似人類大腦的神經(jīng)元,人工神經(jīng)元模型也有樹突、軸突、神經(jīng)元中心等結(jié)構(gòu)。最經(jīng)典的神經(jīng)元模型是“M-P神經(jīng)元模型”。

簡(jiǎn)單神經(jīng)元

一個(gè)神經(jīng)元接收來自其他神經(jīng)元傳來的信號(hào)(變量),通過樹突傳輸(參數(shù))到神經(jīng)元中心(參數(shù)),經(jīng)過轉(zhuǎn)換后(映射f),通過突觸傳遞出去(函數(shù)值)。上圖中紅色的函數(shù)表達(dá)式就是一個(gè)人工神經(jīng)元的數(shù)學(xué)表達(dá)。如果把上圖的激活函數(shù)f設(shè)置成sigmoid函數(shù),那么一個(gè)神經(jīng)元本質(zhì)上就是一個(gè)logistic 回歸模型。

由上述神經(jīng)元工作過程可知,一個(gè)神經(jīng)元可以接受多個(gè)變量,輸出一個(gè)結(jié)果。一個(gè)神經(jīng)元的輸出也可能是另一個(gè)神經(jīng)元的輸入。所以一個(gè)由多個(gè)神經(jīng)元組成的神經(jīng)網(wǎng)絡(luò),本質(zhì)上就是一個(gè)復(fù)雜的、多層嵌套的復(fù)合函數(shù)。

Q:為什么神經(jīng)網(wǎng)絡(luò)要加入激活函數(shù)?

或問:神經(jīng)網(wǎng)絡(luò)引入非線性函數(shù)的用意是什么?

引入激活函數(shù)的根本目的是提高學(xué)習(xí)模型的學(xué)習(xí)(擬合數(shù)據(jù))能力,其最初的動(dòng)機(jī)是彌補(bǔ)線性模型學(xué)習(xí)能力不足的問題。

我們學(xué)習(xí)機(jī)器學(xué)習(xí),都是從最簡(jiǎn)單的線性模型開始的(也有人從K臨近算法開始)。我們知道線性模型雖然簡(jiǎn)單,但是功能卻不差,起碼預(yù)測(cè)一下波士頓的房?jī)r(jià)或者判斷一下是否糖尿病是沒問題的。但是線性模型說到底也只是一條直線或者一個(gè)直的平面,但是現(xiàn)實(shí)中的數(shù)據(jù)卻不都是能用直線擬合或者能用平面分隔開的。比如依據(jù)培養(yǎng)時(shí)間預(yù)測(cè)細(xì)胞數(shù)目(函數(shù)圖像為S型曲線,類似tanh)就不能用線性模型了,或者說線性模型的效果就很差了。

一句話,線性組合能力有限,不能表示復(fù)雜的規(guī)律;線性模型先天不足,不能學(xué)習(xí)復(fù)雜的情況。就像我們不能指望一個(gè)普通的6個(gè)月嬰兒能掌握勾股定理,也不能指望一個(gè)普通的兩歲小孩能理解量子力學(xué)。

所以我們?cè)诰€性模型外面包上一層非線性函數(shù),其實(shí)就是使其結(jié)構(gòu)更加復(fù)雜,使得改造后的(廣義)線性模型有能力表示復(fù)雜的映射,有能力學(xué)習(xí)到更復(fù)雜的情況,有能力擬合呈線性關(guān)系數(shù)據(jù),也能擬合不呈線性關(guān)系的數(shù)據(jù)。

Q:神經(jīng)網(wǎng)絡(luò)有哪些分類?

按照神經(jīng)元的層數(shù)來分,可以分為只有輸入、輸出層的單層網(wǎng)絡(luò)(不計(jì)算輸入層),代表是感知機(jī);以及包含隱含層的多層網(wǎng)絡(luò)。

按照網(wǎng)絡(luò)結(jié)構(gòu)來分,可以分為徑向基函數(shù)網(wǎng)絡(luò)(RBF)、競(jìng)爭(zhēng)學(xué)習(xí)網(wǎng)絡(luò)(ART)、自組織映射網(wǎng)絡(luò)(SOM)、級(jí)聯(lián)相關(guān)網(wǎng)絡(luò)、遞歸神經(jīng)網(wǎng)絡(luò)(RNN)、Boltzman機(jī)等各種各樣紛繁復(fù)雜的種類。

Q:感知機(jī)有什么作用?怎么訓(xùn)練一個(gè)感知機(jī)?

感知機(jī)是最簡(jiǎn)單的神經(jīng)網(wǎng)絡(luò),只有輸入層和輸出層。從數(shù)學(xué)形式上看,感知機(jī)就是只有一個(gè)神經(jīng)元的神經(jīng)網(wǎng)絡(luò)。一般來說,感知機(jī)用來進(jìn)行二分類任務(wù),或者實(shí)現(xiàn)邏輯“與”、“或”、“非”的操作。

Paste_Image.png

感知機(jī)模型 f(x)=sign(\vec{w}?\vec{x}+b) 的輸出一般是二值的,即1或-1。

感知機(jī)的學(xué)習(xí)的學(xué)習(xí)規(guī)則很簡(jiǎn)單,也是類似于線性回歸一樣,使用梯度下降的思想,每讀取一個(gè)樣本,計(jì)算一次預(yù)測(cè)值,就調(diào)整一次參數(shù)(權(quán)值)。

感知機(jī)的訓(xùn)練規(guī)則

x_i表示第i個(gè)輸入,w_i表示第i個(gè)輸入對(duì)應(yīng)的參數(shù)(權(quán)值)。

Q:神經(jīng)元如何組成神經(jīng)網(wǎng)絡(luò)?

通常來說,神經(jīng)元會(huì)按層次結(jié)構(gòu)組成一個(gè)網(wǎng)絡(luò),也就是一個(gè)多部圖結(jié)構(gòu):每一層有任意數(shù)量個(gè)節(jié)點(diǎn),但是同一層節(jié)點(diǎn)之間沒有直接相連,只會(huì)和相鄰層的結(jié)點(diǎn)直接相連,這也是經(jīng)典的前饋神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)。

多層前饋神經(jīng)網(wǎng)絡(luò)

如此一來,本層的節(jié)點(diǎn)接收前一層節(jié)點(diǎn)的輸出作為輸入,經(jīng)過計(jì)算后輸出給后一層節(jié)點(diǎn),每一層節(jié)點(diǎn)的輸出結(jié)構(gòu)都會(huì)是后一層節(jié)點(diǎn)的輸入。

前饋神經(jīng)網(wǎng)絡(luò)只是最基本的網(wǎng)絡(luò)架構(gòu),在此基礎(chǔ)上有多種不同的變體:

競(jìng)爭(zhēng)神經(jīng)網(wǎng)絡(luò)

競(jìng)爭(zhēng)型網(wǎng)絡(luò)的輸出層之間會(huì)有直接聯(lián)系,每個(gè)神經(jīng)元都會(huì)和其他神經(jīng)元競(jìng)爭(zhēng),勝利者才能順利輸出,落敗者沒有輸出。典型的模型有自組織映射網(wǎng)絡(luò)(SOM)。

SOM網(wǎng)絡(luò)

級(jí)聯(lián)相關(guān)網(wǎng)絡(luò)

前饋網(wǎng)絡(luò)的網(wǎng)絡(luò)結(jié)構(gòu)一般在訓(xùn)練開始前就設(shè)置好,訓(xùn)練過程中不會(huì)改變。級(jí)聯(lián)相關(guān)網(wǎng)絡(luò)則是可以在訓(xùn)練過程中動(dòng)態(tài)改變網(wǎng)絡(luò)結(jié)構(gòu):新增隱藏層和隱藏節(jié)點(diǎn)。

級(jí)聯(lián)相關(guān)網(wǎng)絡(luò)

遞歸神經(jīng)網(wǎng)絡(luò)

前饋網(wǎng)絡(luò)每一層的輸入都是來自前一層的輸出,而遞歸神經(jīng)網(wǎng)絡(luò)每一層的輸入除了前一層的輸出,還有本層在上一輪訓(xùn)練的輸出,因此特別適合對(duì)序列數(shù)據(jù)(如文本數(shù)據(jù))建模。Elman網(wǎng)絡(luò)是常用的遞歸神經(jīng)網(wǎng)絡(luò)模型。

Elman網(wǎng)絡(luò)

波茲曼機(jī)

波茲曼機(jī)只有兩層,可見層和隱含層。標(biāo)準(zhǔn)的波茲曼機(jī)是一個(gè)全連接網(wǎng)絡(luò),每個(gè)神經(jīng)元都和其他所有神經(jīng)元相連,顯然這種網(wǎng)絡(luò)的復(fù)雜度就很高,難以訓(xùn)練。而受限波茲曼機(jī)則是同一層之間的神經(jīng)元沒有連接,類似一個(gè)二層前饋神經(jīng)網(wǎng)絡(luò)(不包含輸入層)。

波茲曼機(jī)

Q:神經(jīng)網(wǎng)絡(luò)訓(xùn)練過程是怎樣的?

多層神經(jīng)網(wǎng)絡(luò)由于神經(jīng)元層數(shù)比單層多,所以參數(shù)更多,也意味著學(xué)習(xí)能力更強(qiáng),所以能夠勝任圖像處理、語音識(shí)別等任務(wù)。

最經(jīng)典的多層網(wǎng)絡(luò)訓(xùn)練算法是“誤差逆?zhèn)鞑ニ惴ǎ˙P)”。其基本思想也是通過構(gòu)建關(guān)于網(wǎng)絡(luò)權(quán)重參數(shù)的損失函數(shù)來衡量神經(jīng)網(wǎng)絡(luò)的誤差,然后通過梯度下降令損失函數(shù)取最小值,求得網(wǎng)絡(luò)權(quán)重參數(shù)的最優(yōu)值。

多層神經(jīng)網(wǎng)絡(luò)的參數(shù)也是按層劃分的,所以參數(shù)的求解也要一層一層地進(jìn)行。首先求出輸出層的各個(gè)參數(shù),求出倒數(shù)第二層的參數(shù),再求解出倒數(shù)第三層的參數(shù),以此類推,求解出所有層的參數(shù)。

由于參數(shù)是從輸出層往后求解的,并且是通過損失函數(shù)計(jì)算出來的,因此成為誤差反向傳播算法。

多層網(wǎng)絡(luò)的結(jié)構(gòu)

下面是誤差反向傳播算法的數(shù)學(xué)推導(dǎo)

由于反向傳播算法應(yīng)用于復(fù)雜網(wǎng)絡(luò)時(shí)會(huì)產(chǎn)生巨量的計(jì)算,為闡釋清楚算法過程,這里把西瓜書上給出的示例網(wǎng)絡(luò)進(jìn)一步簡(jiǎn)化:整個(gè)網(wǎng)絡(luò)只有輸入層、一個(gè)隱含層,和輸出層,每層只有一個(gè)神經(jīng)元。訓(xùn)練樣本也只有一個(gè):(x, y),其中x是一個(gè)實(shí)數(shù)(實(shí)際上應(yīng)該是一維向量)。

最簡(jiǎn)單的三層感知機(jī)

在開始理解數(shù)學(xué)推導(dǎo)前,我們要先明確作者使用的數(shù)學(xué)符號(hào)所代表的含義:

  • x 訓(xùn)練集的樣本數(shù)據(jù)。在這里只是一個(gè)實(shí)數(shù)。
  • y 訓(xùn)練集的標(biāo)記數(shù)據(jù),也就是實(shí)際結(jié)果。在這里只是一個(gè)實(shí)數(shù)(二分類任務(wù)的話就只有0或1)。
  • v 輸入層和隱含層之間的連接權(quán)重(weights)
  • \gamma 輸入層和隱含層之間的連接偏置/閾值(bias)
  • \alpha = vx - \gamma 隱含層的線性組合計(jì)算值
  • \sigma Sigmoid函數(shù):\sigma(z) = \frac{1}{1 + e^{-z}}
  • b 隱含層的輸出結(jié)果,也是輸出層的輸入值
  • w 隱含層和輸出層之間的連接權(quán)重(weights)
  • \theta 隱含層和輸出層之間的連接偏置/閾值(bias)
  • \beta 輸出層的線性組合計(jì)算值
  • \hat{y} 輸出層的輸出結(jié)果,也是神經(jīng)網(wǎng)絡(luò)的輸出值,也就是預(yù)測(cè)結(jié)果 。
首先我們要拿到誤差,然后才能反向傳播

把訓(xùn)練樣本x輸入神經(jīng)網(wǎng)絡(luò)后,我們得到網(wǎng)絡(luò)的預(yù)測(cè)值\hat{y},然后我們可以用均方誤差公式來計(jì)算本輪訓(xùn)練的誤差:

E = \frac{1}{2} (y - \hat{y})^2

然后我們可以利用這個(gè)誤差值來著手更新隱含層到輸出層的連接權(quán)重。

更新隱含層到輸出層的參數(shù)w和\theta

按照梯度下降算法,w\theta的更新公式如下。其中\eta是學(xué)習(xí)率,一個(gè)我們自己定義的超參數(shù)。整個(gè)更新公式的含義就是讓參數(shù)朝著學(xué)習(xí)誤差E最小的方向(正是梯度的幾何意義)移動(dòng)一點(diǎn),至于移動(dòng)的步子多大,由學(xué)習(xí)率\eta決定。

w \leftarrow w + \eta\nabla w = w + \eta \frac{\partial E}{\partial w}

\theta \leftarrow \theta + \eta\nabla \theta = \theta + \eta \frac{\partial E}{\partial \theta}

\frac{\partial E}{\partial w}\frac{\partial E}{\partial \theta}這個(gè)又該怎么算?由于

E = \frac{1}{2} (y - \hat{y})^2 \\ \hat{y} = \sigma(\beta) \\ \beta = wb - \theta

通過導(dǎo)數(shù)的鏈?zhǔn)椒▌t,有

\nabla w = \frac{\partial E}{\partial w} = \frac{\partial E}{\partial \hat{y}} \frac{\partial \hat{y}}{\partial \beta} \frac{\partial \beta}{\partial w}

\nabla \theta = \frac{\partial E}{\partial \theta} = \frac{\partial E}{\partial \hat{y}} \frac{\partial \hat{y}}{\partial \beta} \frac{\partial \beta}{\partial \theta}

其中

\frac{\partial E}{\partial \hat{y}} = \frac{\partial (\frac{1}{2} (y - \hat{y})^2 )}{\partial \hat{y}} = y-\hat{y} \\ \frac{\partial \hat{y}}{\partial \beta} = \frac{\partial (\frac{1}{1 + e^{-\beta}})}{\partial \beta} = \frac{1}{1 + e^{-\beta}}(1-\frac{1}{1 + e^{-\beta}}) = \hat{y}(1-\hat{y})\\ \frac{\partial \beta}{\partial w} = \frac{\partial ( bw - \theta)}{\partial w} =b

因此

\nabla w = \frac{\partial E}{\partial w} = \frac{\partial E}{\partial \hat{y}} \frac{\partial \hat{y}}{\partial \beta} \frac{\partial \beta}{\partial w} = (y-\hat{y}) · \hat{y}(1-\hat{y}) · b

\nabla \theta = \frac{\partial E}{\partial \theta} = \frac{\partial E}{\partial \hat{y}} \frac{\partial \hat{y}}{\partial \beta} \frac{\partial \beta}{\partial \theta} = (y-\hat{y}) · \hat{y}(1-\hat{y}) · 1

完成這一層后,我們接著更新后一層的參數(shù),亦即更新輸入層和隱含層之間的權(quán)重參數(shù)。

更新隱含層到輸出層的參數(shù)v和\gamma

按照梯度下降算法,v\gamma的更新公式如下。

v \leftarrow v + \eta\nabla v = v + \eta \frac{\partial E}{\partial v}

\gamma \leftarrow \gamma + \eta\nabla \gamma = \gamma + \eta \frac{\partial E}{\partial \gamma}

\frac{\partial E}{\partial v}\frac{\partial E}{\partial \gamma}又該怎么算?按照類似的流程,由于

E = (y - \hat{y})^2 \\ \hat{y} = \sigma(\beta) \\ \beta = wb - \theta \\ b = \sigma(\alpha) \\ \alpha = wx - \gamma

通過導(dǎo)數(shù)的鏈?zhǔn)椒▌t,有

\nabla v = \frac{\partial E}{\partial v} = \frac{\partial E}{\partial \hat{y}} \frac{\partial \hat{y}}{\partial \beta} \frac{\partial \beta}{\partial b} \frac{\partial b}{\partial \alpha} \frac{\partial \alpha}{\partial v} = (y-\hat{y}) · \hat{y}(1-\hat{y}) · w · b(1-b) · x

\nabla \gamma = \frac{\partial E}{\partial \gamma} = \frac{\partial E}{\partial \hat{y}} \frac{\partial \hat{y}}{\partial \beta} \frac{\partial \beta}{\partial b} \frac{\partial b}{\partial \alpha} \frac{\partial \alpha}{\partial \gamma} = (y-\hat{y}) · \hat{y}(1-\hat{y}) · w · b(1-b) · 1

總結(jié)BP算法流程

對(duì)于上面我們給出的簡(jiǎn)化3層感知機(jī),以及只有一個(gè)訓(xùn)練樣本的情況,我們要循環(huán)往復(fù)地進(jìn)行如下計(jì)算

\alpha = wx - \gamma \\ b = \sigma(\alpha) \\ \beta = wb - \theta \\ \hat{y} = \sigma(\beta) \\ w \leftarrow w + \eta(y-\hat{y})\hat{y}(1-\hat{y})b \\ \theta \leftarrow \theta + \eta(y-\hat{y})\hat{y}(1-\hat{y}) \\ v \leftarrow v + \eta(y-\hat{y})\hat{y}(1-\hat{y})wb(1-b)x \\ \gamma \leftarrow \gamma + \eta(y-\hat{y})\hat{y}(1-\hat{y})wb(1-b)

一直計(jì)算到給定的循環(huán)次數(shù),或者這一輪的誤差與前一輪地誤差相差小于一個(gè)閾值為止E_t - E_{t-1} < \epsilon。

以上便是誤差反向傳播算法在3層感知機(jī),且每層只有一個(gè)神經(jīng)元的情況下的數(shù)學(xué)推導(dǎo)。對(duì)于多層網(wǎng)絡(luò),每層多個(gè)神經(jīng)元的情況,數(shù)學(xué)原理相同,具體可以參考吳恩達(dá)的機(jī)器學(xué)習(xí)課程深度學(xué)習(xí)課程。


Talk is cheap, show me the code!

下面代碼是按照西瓜書里的案例,實(shí)現(xiàn)的一個(gè)極其簡(jiǎn)陋的3層感知機(jī)分類器。這個(gè)模型沒有momentum,沒有penalty,沒有adaptive,其他優(yōu)化手段一切都沒有,就只是一個(gè)簡(jiǎn)陋的網(wǎng)絡(luò)結(jié)構(gòu)。本來西瓜書里兩層的激活函數(shù)都是sigmoid,后來測(cè)試的時(shí)候怎么測(cè)準(zhǔn)確率都在0.56左右浮動(dòng),實(shí)在忍不了,把第一層的激活函數(shù)換了ReLU,這才好看一點(diǎn),但仍然被其他模型吊打??赡苁沁@份代碼里面的bug詞太多了吧?

"""
Naive 3 layer perceptron, uneffective, full of flaws!

:file: supervised.py
:author: Richy Zhu
:email: rickyzhu@foxmail.com
"""
import numpy as np

def binarize(y, threashold=0.5):
    '''
    Transform numeric data into binarize 0 and 1

    >>> y = np.array([0.27, 0.07, 0.56, 0.35, 0.32, 0.65])
    >>> binarize(y)
    array([0, 0, 1, 0, 0, 1])
    '''
    return np.where(np.array(y) < threashold, 0, 1)

def sigmoid(x): 
    '''
    Batch version Sigmoid function

    >>> x = np.array([-0.27, 0.07, 0.56, -0.35, 0.32, -0.65])
    >>> sigmoid(x)
    array([0.4329071 , 0.51749286, 0.63645254, 0.41338242, 0.57932425,
       0.34298954])
    '''
    return 1 / (1 + np.exp(-x))

def relu(x):
    '''
    Batch version ReLU function

    >>> x = np.array([-0.27, 0.07, 0.56, -0.35, 0.32, -0.65])
    >>> relu(x)
    array([0.  , 0.07, 0.56, 0.  , 0.32, 0.  ])
    '''
    return np.where(x<0, 0, x)


class My3LPClassifier:
    '''An naive 3 layer perceptron classifier'''
    
    def __init__(self, layer_dims):

        assert len(layer_dims)==3, 'layer_dims should be 3 elements'
        self.input_size = layer_dims[0]
        self.hidden_size = layer_dims[1]
        self.output_size = layer_dims[-1]
        
        self.V = np.random.randn(self.input_size, self.hidden_size)
        self.gamma = np.zeros([1, self.hidden_size])
        self.W = np.random.randn(self.hidden_size, self.output_size)
        self.theta = np.zeros([1, self.output_size])
        
    def _forward(self, x):
        '''forward computing'''
        x = x.reshape([1,-1])
        alpha = np.dot(x, self.V) - self.gamma
        b =     relu(alpha)
        # b =     sigmoid(alpha)
        beta =  np.dot(b, self.W)
        y_hat = sigmoid(beta) - self.theta
        return alpha, b, beta, y_hat
    
    def _loss(self, y, y_hat):
        '''mean square error'''
        return np.sum(np.square(y-y_hat)) / len(y)

    def _back(self, x, y, alpha, b, beta, y_hat, eta):
        '''back propagation'''
        g = y_hat * (1-y_hat) * (y - y_hat)
        self.W = self.W + eta * (g * b.reshape([-1,1]))
        self.theta = self.theta - eta * g
        e = np.where(alpha<0, 0, alpha) * np.sum(self.W * g, axis=1)
        # e = b * (1-b) * np.sum(self.W * g, axis=1)
        self.V = self.V + eta * (e * x.reshape([-1,1]))
        self.gamma = self.gamma - eta * e

    def fit(self, X, y, eta=1e-5, eps=1e-6, max_iter=10000):
        '''
        Build an random forest classifier

        Parameters
        ----------
        X: ndarray of shape (m, n)
            sample data where row represent sample and column represent feature
        y: ndarray of shape (m, k)
            labels of sample data

        Returns
        -------
        self
            trained model
        '''
        self.X = X
        self.y = y
        
        i = 0
        prev_loss = np.inf
        while i < max_iter:
            predicted = []
            for x, y in zip(self.X, self.y):
                alpha, b, beta, y_hat = self._forward(x)
                self._back(x, y, alpha, b, beta, y_hat, eta)
                predicted.append(y_hat)
            this_loss = self._loss(self.y, np.array(predicted))
            if prev_loss - this_loss < eps:
                break
            prev_loss = this_loss
            i += 1
        return self
    
    def predict(self, X):
        '''
        Make prediction by the trained model.

        Parameters
        ----------
        X: ndarray of shape (m, n)
            data to be predicted, the same shape as trainning data

        Returns
        -------
        C: ndarray of shape (m, k)
            Predicted class label(s) per sample.
        '''
        y = []
        for x in X:
            y.append(self._forward(x)[-1])
        return binarize(np.array(y))
    

測(cè)試一下

import numpy as np
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import  accuracy_score

print('\nMultilayer Perceptron')
print('---------------------------------------------------------------------')
X, y = make_classification(n_samples=1000, n_features=4,
                           n_informative=2, n_redundant=0,
                           random_state=0, shuffle=False)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
mymlp = My3LPClassifier(layer_dims=[X_train.shape[1], 3, 1])
mymlp.fit(X_train, y_train)
print('My 3LP:',  accuracy_score(mymlp.predict(X_test).flatten(), y_test))

from sklearn.neural_network import MLPClassifier
skmlp = MLPClassifier()
skmlp.fit(X_train, y_train)
print('Sk 3LP:',  accuracy_score(skmlp.predict(X_test), y_test))

測(cè)試結(jié)果如下,可謂慘不忍睹,scikit-learn里面任何一個(gè)分類器拿出來都能吊打,側(cè)面反映出網(wǎng)絡(luò)的優(yōu)化是多么重要。

Multilayer Perceptron
---------------------------------------------------------------------
My 3LP: 0.76
Sk 3LP: 0.96

更多代碼請(qǐng)參考https://github.com/qige96/programming-practice/tree/master/machine-learning


本作品首發(fā)于簡(jiǎn)書博客園平臺(tái),采用知識(shí)共享署名 4.0 國(guó)際許可協(xié)議進(jìn)行許可。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容