數據挖掘入門系列教程(八)之使用神經網絡(基於pybrain)識別數字手寫集MNIST

在本章節中,並不會對神經網絡進行介紹,所以若是不瞭解神經網絡的話,強烈推薦先去看《西瓜書》,或者看一下個人上一篇博客:數據挖掘入門系列教程(七點五)之神經網絡介紹html

原本是打算按照《Python數據挖掘入門與實踐》裏面的步驟使用神經網絡來識別驗證碼,可是呢,驗證碼要本身生成,而後我又想了一下,不是有大名鼎鼎的MNIST數據集嗎,爲何不使用它呢,他不香嗎?python

MNIST(Mixed National Institute of Standards and Technology database)相信你們基本上都瞭解過他,大部分的機器學習入門項目就是它。它是一個很是龐大的手寫數字數據集(官網)。裏面包含了0~9的手寫的數字。部分數據以下:git

數據集分爲兩個部分,訓練集和測試集。而後在不一樣的集合中分爲兩個文件,數據Images文件和Labels文件。在數據集中一個有60,000個訓練數據和10,000個測試數據。圖片的大小是28*28。github

下載數據集

萬物始於數據集,儘管官網提供了數據集供咱們下載,可是在sklearn中提供了更方便方法讓咱們下載數據集。代碼以下:算法

import numpy as np
from sklearn.datasets import fetch_openml
# X爲image數據,y爲標籤
X, y = fetch_openml('mnist_784', version=1, return_X_y=True)

其中X,y中間既包含了訓練集又包含了測試集。也就是說X或者y中有70,000條數據。 那麼數據是什麼呢?api

在X中,每一條數據是一個長爲\(28 \times 28=784\)的數組,數組的數據是圖片的像素值。每一條y數據就是一個標籤,表明這張圖片表示哪個數字(從0到9)。數組

而後咱們將數據進行二值化,像素值大於0的置爲1,並將數據保存到文件夾中:網絡

X[X > 0 ] = 1
np.save("./Data/dataset",X)
np.save("./Data/class",y)

而後在Data文件夾中就出現瞭如下兩個文件:框架

咱們取出dataset中間的一條數據,而後轉成28*28的格式,以下所示:dom

數據集既可使用上面的方法獲得,也能夠從個人Github上面進行下載(其中dataset數據集由於GitHub文件大小的限制因此進行了壓縮,須要解壓纔可以使用)。

加載數據集

前面的步驟咱們下載好了數據集,如今咱們就能夠來加載數據了。

import numpy as np
X = np.load("./Data/dataset.npy")
y = np.load("./Data/class.npy")

取出X中的一條數據以下所示:

取出y中的一條數據,以下所示:

一切都很完美,可是這裏有一個問題,在神經網絡中,輸出層其實是這樣的:

它並非直接輸出某一個結果,而是輸出\(y_1,…,y_j,…,y_l\)結果(在MNIST中\(l=10\),由於只有10種數字)。以上面的5爲例子,輸出層並非單純的輸出只輸出一個數字,而是要輸出10個值。那麼如何將輸出5變成輸出10個數字呢?這裏咱們使用」one hot Encoding「。

One-Hot編碼,又稱爲一位有效編碼,主要是採用\(N\)位狀態寄存器來對\(N\)個狀態進行編碼,每一個狀態都由他獨立的寄存器位,而且在任意時候只有一位有效。

如下面的數據爲例,每一行表明一條數據,每一列表明一個屬性。其中第2個屬性只須要3個狀態碼,由於他只有0,1,2三種屬性。這樣咱們就可使用100表明0,010表明1,001表明2。

那麼這個數據編碼後的數據長什麼樣呢?以下圖:

如今咱們就能夠將前面加載的數據集標籤\(y\)進行「one hot Encoding」。

代碼以下:

from sklearn.preprocessing import OneHotEncoder
# False表明不生成稀疏矩陣
onehot = OneHotEncoder(sparse = False)
# 首先將y轉成行長爲7000,列長爲1的矩陣,而後再進行轉化。
y = onehot.fit_transform(y.reshape(y.shape[0],1))

接着就是切割數據集了。將數據集切割成訓練集和測試集。

from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test = train_test_split(X,y,random_state=14)

在神經網絡中,咱們使用pybrain框架去構建一個神經網絡。可是呢,對於pybrain庫,他很不同凡響,他要使用本身的數據集格式,所以,咱們須要將數據轉成它規定的格式。

from pybrain.datasets import SupervisedDataSet

train_data = SupervisedDataSet(x_train.shape[1],y.shape[1])
test_data = SupervisedDataSet(x_test.shape[1],y.shape[1])

for i in range(x_train.shape[0]):
    train_data.addSample(x_train[i],y_train[i])
for i in range(x_test.shape[0]):
    test_data.addSample(x_test[i],y_test[i])

終於,數據集的加載就到這裏結束了。接下來咱們就能夠開始構建一個神經網絡了。

構建神經網絡

首先咱們來建立一個神經網絡,網絡中只含有輸入層,輸出層和一層隱層。

from pybrain.tools.shortcuts import buildNetwork
# X.shape[1]表明屬性的個數,100表明隱層中神經元的個數,y.shape[1]表明輸出
net = buildNetwork(X.shape[1],100, y.shape[1], bias=True)

這裏說有如下「bias」的做用。bias表明的是偏置神經元,bias = True表明偏置神經元激活,也就是在每一層都使用這個這個神經元。偏置神經元以下圖,實際上也就是閾值,只不過換一種說法而已。

如今咱們已經構建好了一個比較簡單的神經網絡,接下來咱們就是使用BP算法去獲得合適的權重值了。

反向傳播(BP)算法

具體的算法步驟在上一篇博客已經介紹過了,很幸運的是在pybrain中間提供了BP算法的庫供咱們使用。這裏就直接上代碼吧。關於BackpropTrainer更加細節的使用能夠看官網

from pybrain.supervised.trainers import BackpropTrainer
trainer = BackpropTrainer(net, train_data, learningrate=0.01,weightdecay=0.01)

這裏面有幾個參數稍微的說明下:

  • net:神經網絡

  • train_data:訓練的數據集

  • learningrate:學習率,也就是下面的\(\eta\),一樣它可使用lrdecay這個參數去控制衰減率,具體的就去看官網文檔吧。

    \[\begin{equation}\begin{array}{l} \Delta w_{h j}=\eta g_{j} b_{h} \\ \Delta \theta_{j}=-\eta g_{j} \\ \Delta v_{i h}=\eta e_{h} x_{i} \\ \Delta \gamma_{h}=-\eta e_{h} \\ \end{array}\end{equation} \]

  • weightdecay:權重衰減,權重衰減也就是下面的\(\lambda\)

    \[\begin{equation} E=\lambda \frac{1}{m} \sum_{k=1}^{m} E_{k}+(1-\lambda) \sum_{i} w_{i}^{2} \\ \lambda \in(0,1) \end{equation} \]

而後咱們就能夠開始訓練了。

trainer.trainEpochs(epochs=100)

epochs也就是訓練集被訓練遍歷的次數。

接下載即是等待的時間了。等待訓練集訓練成完成。訓練的時間跟訓練集的大小,隱層神經元的個數,電腦的性能,步數等等有關。

切記切記,這一次的程序就不要在阿里雲的學生機上面跑了,仍是用本身的機器跑吧。儘管聯想小新pro13 i5版本性能還能夠,可是仍是跑了一個世紀這麼久,哎(耽誤了我打遊戲的時間)。

進行預測

經過前面的步驟以及等待一段時間後,咱們就完成了模型的訓練。而後咱們就可使用測試集進行預測。

predictions = trainer.testOnClassData(dataset=test_data)

predictions的部分數據,表明着測試集預測的結果:

而後咱們就能夠開始驗證準確度了,這裏繼續使用F1評估。這個已經在前面介紹過了,就再也不介紹了。

F1驗證

這裏有個地方須要注意,由於以前的y_test數據咱們使用one-hot encoding進行了編碼,所以咱們須要先將one-hot編碼轉成正常的形式。

# 取每一行最大值的索引。
y_test_arry = y_test.argmax(axis =1)

具體效果以下:

而後使用F1值進行驗證。

from sklearn.metrics import f1_score
print("F-score: {0:.2f}".format(f1_score(predictions,y_test_arry,average='micro')))

而後結果以下:

結果只能說還行吧,不是特別的差,可是也不是特別的好。

總結

項目地址:Github。儘管上面的準確度不咋地,只有\(86\%\),可是也還行吧,畢竟也是使用了一層隱層,而後隱層也只有100個神經元。

若是電腦的性能不夠的話,但是適當的減小步數和訓練集的大小,以及隱層神經元的個數。

參考

相關文章
相關標籤/搜索