在本章節中,並不會對神經網絡進行介紹,所以若是不瞭解神經網絡的話,強烈推薦先去看《西瓜書》,或者看一下個人上一篇博客:數據挖掘入門系列教程(七點五)之神經網絡介紹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算法去獲得合適的權重值了。
具體的算法步驟在上一篇博客已經介紹過了,很幸運的是在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這個參數去控制衰減率,具體的就去看官網文檔吧。
weightdecay:權重衰減,權重衰減也就是下面的\(\lambda\)
而後咱們就能夠開始訓練了。
trainer.trainEpochs(epochs=100)
epochs
也就是訓練集被訓練遍歷的次數。
接下載即是等待的時間了。等待訓練集訓練成完成。訓練的時間跟訓練集的大小,隱層神經元的個數,電腦的性能,步數等等有關。
切記切記,這一次的程序就不要在阿里雲的學生機上面跑了,仍是用本身的機器跑吧。儘管聯想小新pro13 i5版本性能還能夠,可是仍是跑了一個世紀這麼久,哎(耽誤了我打遊戲的時間)。
經過前面的步驟以及等待一段時間後,咱們就完成了模型的訓練。而後咱們就可使用測試集進行預測。
predictions = trainer.testOnClassData(dataset=test_data)
predictions
的部分數據,表明着測試集預測的結果:
而後咱們就能夠開始驗證準確度了,這裏繼續使用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個神經元。
若是電腦的性能不夠的話,但是適當的減小步數和訓練集的大小,以及隱層神經元的個數。