Python機器學習筆記:深入理解Keras中序貫模型和函式模型
先從sklearn說起吧,如果學習了sklearn的話,那麼學習Keras相對來說比較容易。為什麼這樣說呢?
我們首先比較一下sklearn的機器學習大致使用流程和Keras的大致使用流程:
sklearn的機器學習使用流程:
1 2 3 4 5 6 7 8 9 10 |
|
Keras的機器學習使用流程:
1 2 3 4 5 6 7 8 |
|
兩者的區別
由上面虛擬碼可知Keras和sklearn最大不同在於需要進行模型搭建,可是既然有了這麼多模型為什麼還要模型搭建?
如果你瞭解過神經網路感知機就會比較理解這個過程,一個感知器相當於一個神經元,可根據輸入資訊反饋出需要的電訊號,根據我們的世界觀,一個細胞可以單獨執行很多功能但是大量單純的任務會讓細胞只針對一個方向發展。用生物學的說話就是分化能力逐漸減弱,機器學習說法就是過擬合。因此,只有大量細胞通過不同的組合才能完成紛繁複雜的預測任務,因而有證明說神經網路理論上可擬合出任何曲線。
那麼話說回來,Keras需要自行搭建模型,搭建方法有兩種:序貫模型和函式式模型。而我本次的筆記就是學習序貫模型和函式式模型。
序貫模型
序貫模型是多個網路蹭的線性堆疊,是函式式模型的簡略版,為最簡單的線性,從頭到尾的結構順序,不發生分叉。是多個網路層的線性堆疊。
Keras實現了很多層,包括core核心層,Convolution卷積層,Pooling池化層等非常豐富有趣的網路結構。
應用序貫模型的基本步驟
- 1,model.add() 新增層
- 2,model.compile() 模型訓練的BP模式設定
- 3,model.fit() 模型訓練引數設定+訓練
- 4,model.evaluate() 模型評估
- 5,model.predict() 模型預測
序貫模型的建立
1,可以通過向Sequential模型傳遞一個layer的list來構造Sequential模型:
1 2 3 4 5 6 7 8 9 10 11 |
|
2,也可以通過.add()方法一個個的將layer加入模型中:
1 2 3 4 5 6 7 8 9 10 |
|
結果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
3,指定輸入資料的shape
模型需要知道輸入資料的shape,因此,Sequential的第一層需要接受一個關於輸入資料shape的引數,後面的各個層則可以自動的推匯出中間資料的shape,因此不需要為每一層都指定這個引數。有幾種方法來為第一層指定輸入資料的shape
1,傳遞一個input_shape的關鍵字引數給第一層,input_shape是一個tupel型別的資料(一個整數或者None的元祖,其中None表示可能為任何正整數)在input_shape中不包含資料的batch大小。
1 2 |
|
2,有些2D層,如Dense,支援通過指定其輸入維度input_dim來隱含的指定輸入資料shape,是一個Int型別的資料。一些3D的時域層支援通過引數input_dim和input_length來指定輸入shape。
1 2 |
|
3,如果你需要為你的輸入指定一個固定的batch大小(這對於statsful RNNs很有用),你可以傳遞一個batch_size引數給一個層。如果你同時將batch_size=32和input_shape = (6,8)傳遞給一個層,那麼每一批輸入的尺寸就是(32,6,8)。
因此下面的程式碼是等價的:
1 2 3 4 5 |
|
下面三種方法也是嚴格等價的
1 2 3 4 5 6 7 8 9 10 |
|
4,編譯
在訓練模型之前,我們需要通過compile來對學習過程進行配置,compile接收三個引數:優化器optimizer,損失函式loss,指標列表metrics。
1 |
|
其中:
optimizer:字串(預定義優化器名)或者優化器物件,,如 rmsprop
或 adagrad
,也可以是 Optimizer 類的例項。詳見:optimizers。
loss:字串(預定義損失函式名)或目標函式,模型試圖最小化的目標函式,它可以是現有損失函式的字串識別符號,如categorical_crossentropy
或 mse
,也可以是一個目標函式。詳見:losses。
metrics:列表,包含評估模型在訓練和測試時的網路效能的指標,典型用法是metrics=[‘accuracy’]。評估標準可以是現有的標準的字串識別符號,也可以是自定義的評估標準函式。
注意:
模型在使用前必須編譯,否則在呼叫fit或者evaluate時會丟擲異常。
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
5,訓練
Keras 模型在輸入資料和標籤的 Numpy 矩陣上進行訓練。為了訓練一個模型,你通常會使用 fit
函式。文件詳見此處。
1 2 3 |
|
本函式將模型訓練nb_epoch輪,其引數有:
x:輸入資料,如果模型只有一個輸入,那麼x的型別是numpy array,如果模型有多個輸入,那麼x的型別應當是list,list的元素是對應於各個輸入的numpy array
y:標籤 ,numpy array
batch_size:整數,指定進行梯度下降時每個batch包含的樣本數,訓練時一個batch的樣本會被計算一次梯度下降,使目標函式優化一步。
epochs:整數,訓練的輪數,每個epoch會把訓練集輪一遍。
verbose:日誌顯示,0為不在標準輸出流輸出日誌資訊,1為輸出進度條記錄,2為每個epoch輸出一行記錄
callbacks:list,,其中的元素是keras.callbacks.Callback的物件。這個list中的回撥函式將會在訓練過程中的適當時機被呼叫,參考回撥函式。
validation_split:0~1之間的浮點數,用來指定訓練集的一定比例資料作為驗證集。驗證集將不參與訓練,並在每個epoch結束後測試的模型的指標,如損失函式,精確度等。注意,validation_split的劃分在shuffle之前,因此如果你的資料本身是有序的,需要先手工打亂再指定validation_split,否則可能會出現驗證集樣本不均勻。
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’。
initial_epoch:從該引數指定的epoch開始訓練,在繼續之前的訓練時候有用。
fit函式返回一個History的物件,其History.history屬性記錄了損失函式和其他指標的數值隨著epoch變化的情況,如果有驗證集的話,也包含了驗證集的這些指標變化情況。
示例一:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
示例二:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
6,評估
根據驗證集評估模型的好壞
1 |
|
本函式按batch計算在某些輸入資料上模型的誤差,其引數有:
x:輸入資料,與fit一樣,是numpy array 或者numpy array的list
y:標籤,numpy array
batch_size:整數,含義同fit的同名引數
verbose:含義同fit的同名引數,但是隻能取0或1
sample_weight:numpy array ,含義同fit的同名引數
本函式返回一個測試誤差的標量值(如果模型沒有其他評價指標),或一個標量的list(如果模型還有其他的評價指標)。model.metrics_names將給出list中各個值的含義。
如果沒有特殊說明,以下函式的引數均保持與fit的同名引數相同的含義
如果沒有特殊說明,以下函式的verbose引數(如果有)均只能取0或者1
1 2 3 |
|
7,預測
對已經訓練完成的模型,輸入特徵值x會預測得到標籤y。
1 2 3 |
|
本函式按batch獲得輸入資料對應的輸出,其引數有:
函式的返回值是預測值的numpy array
predict_classes:本函式按batch產生輸入資料的類別預測結果
predict_proba:本函式按batch產生輸入資料屬於各個類別的概率
1 2 3 |
|
8,on_batch,batch的結果,檢查
1 2 3 |
|
train_on_batch:本函式在batch的資料上進行一次引數更新,函式返回訓練誤差的標量值或者標量值的list,與evaluate的情形相同。
test_on_batch:本函式在一個batch的樣本上對模型進行評估,函式的返回與evaluate的情形相同。
predict_on_batch:本函式在一個batch的樣本上對模型進行測試,函式返回模型在一個batch上的預測結果。
9,完整程式碼及其一次結果
程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
結果:
函式式模型
比序貫模型要複雜,但是效果很好,可以同時/分階段輸入變數,分階段輸出想要的模型。
所以說,只要你的模型不是類似VGG一樣
1,應用函式式模型的基本步驟
1,model.layers() 新增層
2,model.compile() 模型訓練的BP模式設定
3,model.fit() 模型訓練引數設定+訓練
4,evaluate() 模型評估
5,predict() 模型預測
2,常用Model屬性
1 2 3 |
|
1 |
|
3,指定輸入資料的shape
1 |
|
4,編譯,訓練,評估,預測等步驟與序貫式模型相同(這裡不再贅述)
1 |
|
本函式按batch計算在某些輸入資料上模型的誤差,其引數有:
x:輸入資料,與fit一樣,是numpy array或者numpy array的list
y:標籤,numpy array
batch_size:整數,含義同fit的同名函式
verbose:含義與fit的同名函式,但是隻能取0或者1
sample_weight:numpy array,含義同fit的同名函式
本函式編譯模型以供訓練,引數有:
1 |
|
5,示例一(基於上面序貫模型進行改造)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
序貫模型和函式模型共同的API
model.summary():打印出模型的概況,它實際呼叫的是keras.utils.print_summary
model.get_config():返回包含模型配置資訊的Python字典,模型也可以從config中重構回去。
1 2 3 |
|
上面是分別對序貫模型和函式式模型載入config
model.get_layer():依據層名或下標獲得層物件
model.get_weights():返回模型權重張量的列表,型別為numpy.array
model.set_weights():從numpy array裡載入給模型,要求陣列與model.get_weights()一樣
model.to_json():返回代表模型的JSON字串,僅僅包含網路結構,不包含權重,可以從JSON字串中重構模型
Keras模型儲存
首先不推薦使用pickle或者cPickle來儲存Keras模型
1,儲存結構
可以使用model.save(filepath)將Keras模型和權重儲存在一個HDF5檔案中,該檔案將包含:
- 模型的結構,以便重構該模型
- 模型的權重
- 訓練配置(損失函式,優化器等)
- 優化器的狀態,以便從上次訓練中斷的地方開始
使用Keras.models.load_model(filepath)來重新例項化你的模型,如果檔案中儲存了訓練配置的話,該函式還會同時完成模型的編譯。例如:
1 2 3 4 5 6 7 8 9 10 11 |
|
2,儲存結構
如果你只是希望儲存模型的結構,而不包括其權重或者配置資訊,可以使用:
1 2 3 4 5 |
|
這項操作可以將模型序列化為json或者yaml檔案,如果需要的話你甚至可以手動開啟這些檔案進行編輯。
當然你也可以從儲存好的json檔案或者yaml檔案中載入模型:
1 2 3 4 5 6 |
|
3,儲存模型的權重
如果需要儲存模型,可通過下面的程式碼利用HDF5進行儲存。注意,在使用前需要確保你已經安裝了HDF5 和Python的庫h5py。
1 |
|
如果你需要在程式碼中初始化一個完全相同的模型,請使用:
1 |
|
4,載入權重到不同的網路結構
如果你需要載入權重到不同的網路結構(有些層一樣)中,例如fine-tune或transfer-learning,你可以通過層名字來載入模型。
1 |
|
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
載入權重到不同的網路結構上多數用於遷移學習。