1. 程式人生 > >Keras基於TensorFlow實現的簡單分類問題

Keras基於TensorFlow實現的簡單分類問題

神經網路是可以用來模擬分類問題。
首先先說一下什麼是分類問題,分類問題是用於將事物打上一個標籤,通常結果為離散值。例如判斷一個學生是好學生還是壞學生,其結果是離散的,即好學生、壞學生。而回歸問題是給出一個值去逼近正確值。但是分類通常是建立在迴歸之上,例如上面的學生判斷問題,我們可以規定由迴歸模型得到的值,然後設立一個臨界值,大於這個就是好學生,小於就是壞學生,類似這樣。分類的最後一層通常要使用softmax函式進行判斷其所屬類別。分類並沒有逼近的概念,其最終得到的只有一個結果,即好學生或者壞學生,即錯誤的就是錯誤的,不會有相近的概念。最常見的分類方法是邏輯迴歸,或者叫邏輯分類。

神經網路用於 分類 和 迴歸的本質

:
用於迴歸:最後一層有m個神經元,每個神經元輸出一個標量,m個神經元的輸出可以看做向量 v,現全部連到一個神經元上,則這個神經元輸出wv+b,是一個連續值,可以處理迴歸問題,跟上面 Linear Regression 思想一樣。
用於N分類:現在這m個神經元最後連線到 N 個神經元,就有 N 組w值不同的 wv+b,同理可以歸一化(比如用 softmax )變成
N個類上的概率。
這個模型是根據莫煩老師的網上教學視訊寫的,感謝。

一、根據程式碼對其進行詳細解讀
1.匯入的模組
匯入本例子的模組有numpy、keras.datasets、keras.utils、keras.model、keras.layers、keras.optimizers,
首先看一下模組datasets,其實一個數據庫,這裡我們匯入的是mnist資料庫,本資料庫有60,000個用於訓練的28*28的灰度手寫數字圖片,10,000個測試圖片。


使用方法:

from keras.datasets import mnist
(X_train, y_train), (X_test, y_test) = mnist.load_data()

返回值:
兩個Tuple, (X_train, y_train), (X_test, y_test) ,其中
X_train和X_test:是形如(nb_samples, 28, 28)的灰度圖片資料,資料型別是無符號8位整形
(uint8)
y_train和y_test:是形如(nb_samples,)標籤資料,標籤的範圍是0~9
np.utils的作用是將y_train和y_test這樣的數變成一個大小為10的向量,其屬於那個位置就將那個位置為1,其他位置都是0。

啟用函式 Activations
啟用函式可以通過設定單獨的啟用層實現,也可以在構造層物件時通過傳遞 activation 引數實現.

優化器 optimizers
優化器是編譯Keras模型必要的兩個引數之一,RMSprop通過引入一個衰減係數,讓r每回合都衰減一定的比例,類似於Momentum中的做法。
具體實現:
需要:全域性學習速率 ϵ, 初始引數 θ, 數值穩定量δ,衰減速率ρ
中間變數:梯度累積量r(初始化為0)
每步迭代過程:
1. 從訓練集中的隨機抽取一批容量為m的樣本{x1,…,xm},以及相關的輸出yi
2. 計算梯度和誤差,更新r,再根據r和梯度計算引數更新量
優點:
相比於AdaGrad,這種方法很好的解決了深度學習中過早結束的問題 。
適合處理非平穩目標,對於RNN效果很好。
缺點:
又引入了新的超參,衰減係數ρ 。
依然依賴於全域性學習速率。

2.資料生成
這裡是呼叫mnist資料庫,該資料庫有60,000個用於訓練的28*28的灰度手寫數字圖片,10,000個測試圖片。

3.建立模型
這裡我們用到了四層模型即Dense、Activation、Dense、Activation這四個模型。
Dense層全連線層在迴歸的時候已經介紹了,下面介紹一下Activation啟用函式,
啟用函式通常有如下一些性質:

非線性: 當啟用函式是線性的時候,一個兩層的神經網路就可以逼近基本上所有的函數了。但是,如果啟用函式是恆等啟用函式的時候(即f(x)=x),就不滿足這個性質了,而且如果MLP使用的是恆等啟用函式,那麼其實整個網路跟單層神經網路是等價的。
可微性: 當優化方法是基於梯度的時候,這個性質是必須的。
單調性: 當啟用函式是單調的時候,單層網路能夠保證是凸函式。
f(x)≈x: 當啟用函式滿足這個性質的時候,如果引數的初始化是random的很小的值,那麼神經網路的訓練將會很高效;如果不滿足這個性質,那麼就需要很用心的去設定初始值。
輸出值的範圍: 當啟用函式輸出值是 有限 的時候,基於梯度的優化方法會更加 穩定,因為特徵的表示受有限權值的影響更顯著;當啟用函式的輸出是 無限 的時候,模型的訓練會更加高效,不過在這種情況小,一般需要更小的learning rate。
這裡我們使用了‘relu’、‘softmax’這兩種類別的函式。程式碼首先利用全連線層將其轉化為32種,然後利用啟用函式‘relu’,再使用全連線層將其變為10中,然後利用softmax啟用函式來將其分類。關於啟用函式詳細的可以參考:
http://blog.csdn.net/cyh_24/article/details/50593400

4.編譯模型
利用model.compile()去編譯,這個函式前面一章已經介紹了 這裡就不詳細介紹了。主要就是這裡的優化器利用了RMSprop。

5.訓練模型
這裡我們運用的是model.fit()函式去訓練模型,而不是像昨天那樣利用train_on_batch()來一組一組的訓練模型。fit函式可以指定訓練次數以及每次訓練的個數。

fit(self, x, y, batch_size=32, nb_epoch=10, verbose=1, callbacks=[], validation_split=0.0, validation_data=None,
shuffle=True, class_weight=None, sample_weight=None)

本函式將模型訓練 nb_epoch 輪,其引數有:
x:輸入資料。如果模型只有一個輸入,那麼x的型別是numpy array,如果模型有多個輸入,那
麼x的型別應當為list,list的元素是對應於各個輸入的numpy array
y:標籤,numpy array
batch_size:整數,指定進行梯度下降時每個batch包含的樣本數。訓練時一個batch的樣本會被計
算一次梯度下降,使目標函式優化一步。
nb_epoch:整數,訓練的輪數,訓練資料將會被遍歷nb_epoch次。Keras中nb開頭的變數均
為”number of”的意思
verbose:日誌顯示,0為不在標準輸出流輸出日誌資訊,1為輸出進度條記錄,2為每個epoch輸出
一行記錄
callbacks:list,其中的元素是 keras.callbacks.Callback 的物件。這個list中的回撥函式將會在訓練過
程中的適當時機被呼叫,參考回撥函式
validation_split:0~1之間的浮點數,用來指定訓練集的一定比例資料作為驗證集。驗證集將不參與
訓練,並在每個epoch結束後測試的模型的指標,如損失函式、精確度等。
validation_data:形式為(X,y)的tuple,是指定的驗證集。此引數將覆蓋validation_spilt。
shuffle:布林值或字串,一般為布林值,表示是否在訓練過程中隨機打亂輸入樣本的順序。若為
字串“batch”,則是用來處理HDF5資料的特殊情況,它將在batch內部將資料打亂。
class_weight:字典,將不同的類別對映為不同的權值,該引數用來在訓練過程中調整損失函式
(只能用於訓練)
sample_weight:權值的numpy array,用於在訓練時調整損失函式(僅用於訓練)。可以傳遞一
個1D的與樣本等長的向量用於對樣本進行1對1的加權,或者在面對時序資料時,傳遞一個的形式為
(samples,sequence_length)的矩陣來為每個時間步上的樣本賦不同的權。這種情況下請確定在
編譯模型時添加了 sample_weight_mode=’temporal’ 。
fit 函式返回一個 History 的物件,其 History.history 屬性記錄了損失函式和其他指標的數值
隨epoch變化的情況,如果有驗證集的話,也包含了驗證集的這些指標變化情況。

6.驗證模型
用到的函式是 model.evaluate,輸入測試集的x和y,輸出 cost,weights 和 biases。其中 weights 和 biases 是取在模型的第一層 model.layers[0] 學習到的引數。

evaluate(self, x, y, batch_size=32, verbose=1, sample_weight=None)

本函式按batch計算在某些輸入資料上模型的誤差,其引數有:
x:輸入資料,與 fit 一樣,是numpy array或numpy array的list
y:標籤,numpy array
batch_size:整數,含義同 fit 的同名引數
verbose:含義同 fit 的同名引數,但只能取0或1
sample_weight:numpy array,含義同 fit 的同名引數
本函式返回一個測試誤差的標量值(如果模型沒有其他評價指標),或一個標量的list(如果模型還有
其他的評價指標)。

7.模型結果
這裡寫圖片描述

二、具體程式碼實現

#Classifier example

import numpy as np 
np.random.seed(1337)
from keras.datasets import mnist
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers import Dense,Activation
from keras.optimizers import RMSprop

#獲取資料
#X_shape(60000,28*28),y_shape(10000)
(X_train,y_train),(X_test,y_test)=mnist.load_data()

#資料處理
X_train=X_train.reshape(X_train.shape[0],-1)/255 #將其範圍變成0-1
X_test=X_test.reshape(X_test.shape[0],-1)/255
y_train=np_utils.to_categorical(y_train,10) #
y_test=np_utils.to_categorical(y_test,10)

#簡歷模型
model=Sequential([
    Dense(input_dim=784,units=32),
    Activation('relu'),
    Dense(10),
    Activation('softmax')
])

rmsprop=RMSprop(lr=0.001,rho=0.9,epsilon=1e-08,decay=0.0)

#編譯模型
model.compile(
    optimizer=rmsprop,
    loss='categorical_crossentropy',
    metrics=['accuracy',]
)

#訓練模型
print('Training-------------------')
model.fit(X_train,y_train,nb_epoch=12,batch_size=32)

#測試誤差
loss,accuracy=model.evaluate(X_test,y_test)
print('test loss', loss)
print('test accuracy',accuracy)