利用keras進行分類
Classifier
做classifier的時候,本來是按照莫煩的教程一步一步做的,但是總是在mnist.load_data這部分出錯,說是無法連結到https://s3.amazonaws.com/img-datasets/mnist.npz,我上網也找了一些解決方案都不行。然後我看到程式上有說明:
果然,這個方法是可行的。但是,執行莫煩教程上給出的程式時,準確率只有0.4,這實在不科學。然後我就想找出問題。悲劇發生了……我不知道動了哪裡,就一直numpy這個包import不了,,,好氣哦。沒辦法,只好解除安裝重灌,好在只是keras有問題。
pip uninstall keras
pip install keras
終於可以運行了,結果可以達到98.38%
附上程式碼
#!/usr/bin/python
# -*- coding:utf8 -*-
'''
Trains a simple deep NN on the MNIST dataset.
Gets to 98.40% test accuracy after 20 epochs
(there is *a lot* of margin for parameter tuning).
2 seconds per epoch on a K520 GPU.
'''
from __future__ import print_function #使python2.7可以使用print函式形式
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import RMSprop
batch_size = 128
num_classes = 10
epochs = 20
# the data, shuffled and split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(60000 , 784)
x_test = x_test.reshape(10000, 784)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255 #輸入的 x 變成 60,000*784 的資料,然後除以 255 進行標準化,因為每個畫素都是在 0 到 255 之間的,標準化之後就變成了 0 到 1 之間
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')
# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes) #把 y 變成了 one-hot 的形式,即之前 y 是一個數值, 在 0-9 之間,現在是一個大小為 10 的向量,它屬於哪個數字,就在哪個位置為 1,其他位置都是 0
y_test = keras.utils.to_categorical(y_test, num_classes)
# build the neural net
model = Sequential() #序貫式模型
model.add(Dense(512, activation='relu', input_shape=(784,)))
model.add(Dropout(0.2)) #防止過擬合,每次更新引數時隨機斷開一定百分比(rate)的輸入神經元
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(10, activation='softmax'))
model.summary() #打印出模型概況
# compile the model
model.compile(loss='categorical_crossentropy', # 對數損失
optimizer=RMSprop(),
metrics=['accuracy'])
# train the model
history = model.fit(x_train, y_train,
batch_size=batch_size,
epochs=epochs,
verbose=1, #日誌顯示
validation_data=(x_test, y_test)) #fit將模型訓練epochs輪
# test the model
score = model.evaluate(x_test, y_test, verbose=0) #evaluate函式按batch計算在某些輸入資料上模型的誤差
print('Test loss:', score[0])
print('Test accuracy:', score[1])
轉載一些基礎知識
符號計算
Keras的底層庫使用Theano或TensorFlow,這兩個庫也稱為Keras的後端,無論事Theano還是TensorFlow,都是一個符號主義的庫。
關於符號主義,可以一般概括為這種說法:符號主義的計算首先定義各種變數,然後建立一個“計算圖”,計算圖規定了各個變數之間的計算關係。建立好的計算圖需要編譯已確定其內部細節,然而,此時的計算圖還是一個“空殼子”,裡面沒有任何實際的資料,只有當你把需要運算的輸入放進去後,才能在整個模型中形成資料流,從而形成輸出值。
Keras的模型搭建形式就是這種方法,在你搭建Keras模型完畢後,你的模型就是一個空殼子,只有實際生成可呼叫的函式後(K.function),輸入資料,才會形成真正的資料流。
使用計算圖的語言,如Theano,以難以除錯而聞名,當Keras的Debug進入Theano這個層次時,往往也令人頭痛。沒有經驗的開發者很難直觀的感受到計算圖到底在幹些什麼。儘管很讓人頭痛,但大多數的深度學習框架使用的都是符號計算這一套方法,因為符號計算能夠提供關鍵的計算優化、自動求導等功能。
張量
前面的概念中提到並解釋了這個詞,該詞本身還是兼具多個學科的,而這裡的用到的相對來說較簡單一些。
張量,或tensor,是本文件會經常出現的一個詞彙,在此稍作解釋。
使用這個詞彙的目的是為了表述統一,張量可以看作是向量、矩陣的自然推廣,我們用張量來表示廣泛的資料型別。
規模最小的張量是0階張量,即標量,也就是一個數。
當我們把一些數有序的排列起來,就形成了1階張量,也就是一個向量
如果我們繼續把一組向量有序的排列起來,就形成了2階張量,也就是一個矩陣
把矩陣摞起來,就是3階張量,我們可以稱為一個立方體,具有3個顏色通道的彩色圖片就是一個這樣的立方體
把矩陣摞起來,好吧這次我們真的沒有給它起別名了,就叫4階張量了,不要去試圖想像4階張量是什麼樣子,它就是個數學上的概念。
‘th’與’tf’
‘th’模式,也即Theano模式會把100張RGB三通道的16×32(高為16寬為32)彩色圖表示為下面這種形式(100,3,16,32),Caffe採取的也是這種方式。第0個維度是樣本維,代表樣本的數目,第1個維度是通道維,代表顏色通道數。後面兩個就是高和寬了。
而TensorFlow,即‘tf’模式的表達形式是(100,16,32,3),即把通道維放在了最後。這兩個表達方法本質上沒有什麼區別。
泛型模型
在原本的Keras版本中,模型其實有兩種,一種叫Sequential,稱為序貫模型,也就是單輸入單輸出,一條路通到底,層與層之間只有相鄰關係,跨層連線統統沒有。這種模型編譯速度快,操作上也比較簡單。第二種模型稱為Graph,即圖模型,這個模型支援多輸入多輸出,層與層之間想怎麼連怎麼連,但是編譯速度慢。可以看到,Sequential其實是Graph的一個特殊情況。
在現在這版Keras中,圖模型被移除,而增加了了“functional model API”,這個東西,更加強調了Sequential是特殊情況這一點。一般的模型就稱為Model,然後如果你要用簡單的Sequential,OK,那還有一個快捷方式Sequential。
由於functional model API表達的是“一般的模型”這個概念,我們將其譯為泛型模型,即只要這個東西接收一個或一些張量作為輸入,然後輸出的也是一個或一些張,不管它是什麼鬼。統統都稱作“模型”。
Batch
其實我之前看到這個引數設定的時候,一直沒搞懂,今天來整理一下吧。
這詞設計到訓練過程中如何優化,嘿嘿,那就提到了深度學習的優化演算法,說白了就是梯度下降。每次的引數更新有兩種方式。
第一種,遍歷全部資料集算一次損失函式,然後算函式對各個引數的梯度,更新梯度。這種方法每更新一次引數都要把資料集裡的所有樣本都看一遍,計算量開銷大,計算速度慢,不支援線上學習,這稱為Batch gradient descent,批梯度下降。
另一種,每看一個數據就算一下損失函式,然後求梯度更新引數,這個稱為隨機梯度下降,stochastic gradient descent。這個方法速度比較快,但是收斂效能不太好,可能在最優點附近晃來晃去,hit不到最優點。兩次引數的更新也有可能互相抵消掉,造成目標函式震盪的比較劇烈。
為了克服兩種方法的缺點,現在一般採用的是一種折中手段,mini-batch gradient decent,小批的梯度下降,這種方法把資料分為若干個批,按批來更新引數,這樣,一個批中的一組資料共同決定了本次梯度的方向,下降起來就不容易跑偏,減少了隨機性。另一方面因為批的樣本數與整個資料集相比小了很多,計算量也不是很大。
基本上現在的梯度下降都是基於mini-batch的,所以Keras的模組中經常會出現batch_size,就是指這個。
順便說一句,Keras中用的優化器SGD是stochastic gradient descent的縮寫,但不代表是一個樣本就更新一回,還是基於mini-batch的。