“sample”“batch”“epoch”
Sample:樣本,比如:一張圖像是一個樣本,一段音頻也是一個樣本。
Batch:批,含有N個樣本的集合。每一個batch的樣本都是獨立的並行處理。在訓練是,一個batch的結果只會用來更新一次模型。
Epoch:輪次,通常通常定義為 [在整個數據集上的一輪迭代],用於訓練的不同的階段,這有利於記錄和定期
保存/加載Keras模型(結構+權重+優化器狀態)
model.save(filepath)將Keras模型保存到單個HDF5文件中,該文件將包含:
- 模型的結構,允許重新創建模型
- 模型的權重
- 訓練配置項(損失函數、優化器)
- 優化器狀態,允許准確地從你上次結束的地方繼續訓練
keras.models.load_model(filepath)重新實例化模型,load_model還將負責使用保存的訓練配置項來編譯模型(除非模型從未編譯過)
from keras.models import load_model model.save('my_model.h5') # 創建 HDF5 文件 'my_model.h5' del model # 刪除現有模型 # 返回一個編譯好的模型 # 與之前那個相同 model = load_model('my_model.h5')
只保存/加載模型的結構
如果我們只需要保存模型的結構,而非其權重或訓練配置項,則:
model.save_weights('my_model_weights.h5')
假如我們有用於實例化模型的代碼,則可以將保存的權重加載到具有相同結構的模型中:
model.load_weights('my_model_weights.h5')
如果你需要將權重加載到不同的結構(有一些共同層)的模型中,例如微調或遷移學習,則可以按層的名字來加載權重:
model.load_weights('my_model_weights.h5', by_name=True)
例如:

""" 假設原始模型如下所示: model = Sequential() model.add(Dense(2, input_dim=3, name='dense_1')) model.add(Dense(3, name='dense_2')) ... model.save_weights(fname) """ # 新模型 model = Sequential() model.add(Dense(2, input_dim=3, name='dense_1')) # 將被加載 model.add(Dense(10, name='new_dense')) # 將不被加載 # 從第一個模型加載權重;只會影響第一層,dense_1 model.load_weights(fname, by_name=True)
獲取中間層的輸出
創建一個新的Model來輸出:
from keras.models import Model model = ... # 創建原始模型 layer_name = 'my_layer' intermediate_layer_model = Model(inputs=model.input, outputs=model.get_layer(layer_name).output) intermediate_output = intermediate_layer_model.predict(data)
或者構建一個Keras函數,該函數將在給定輸入的情況下返回某一層的輸出,例如:
from keras import backend as K # 以 Sequential 模型為例 get_3rd_layer_output = K.function([model.layers[0].input], [model.layers[3].output]) # 測試模式的輸出 layer_output = get_3rd_layer_output([x])[0]
使用Keras處理超過內存的數據集
使用 model.train_on_batch(x,y)
和 model.test_on_batch(x,y)
進行批量訓練與測試。請參閱 模型文檔。
或者,你可以編寫一個生成批處理訓練數據的生成器,然后使用 model.fit_generator(data_generator,steps_per_epoch,epochs)
方法。可以在 CIFAR10 example 中找到實踐代碼。
在驗證集的誤差不再下降時,中斷訓練
使用 EarlyStopping
回調:
from keras.callbacks import EarlyStopping early_stopping = EarlyStopping(monitor='val_loss', patience=2) model.fit(x, y, validation_split=0.2, callbacks=[early_stopping])
Keras 驗證集的划分
如果您將 model.fit
中的 validation_split
參數設置為 0.1,那么使用的驗證數據將是最后 10% 的數據。如果設置為 0.25,就是最后 25% 的數據。注意,在提取分割驗證集之前,數據不會被混洗,因此驗證集僅僅是傳遞的輸入中最后一個 x% 的樣本。
所有 epoch 都使用相同的驗證集(在同一個 fit
中調用)。
在訓練過程中數據是否會混洗?
是的,如果 model.fit
中的 shuffle
參數設置為 True(默認值),則訓練數據將在每個 epoch 混洗。
驗證集永遠不會混洗。
如何在每個 epoch 后記錄訓練集和驗證集的誤差和准確率?
model.fit
方法返回一個 History
回調,它具有包含連續誤差的列表和其他度量的 history
屬性。
hist = model.fit(x, y, validation_split=0.2) print(hist.history)
如何「凍結」網絡層?
「凍結」一個層意味着將其排除在訓練之外,即其權重將永遠不會更新。
可以將 trainable
參數(布爾值)傳遞給一個層的構造器,以將該層設置為不可訓練的:
frozen_layer = Dense(32, trainable=False)
另外,可以在實例化之后將網絡層的 trainable
屬性設置為 True 或 False。為了使之生效,在修改 trainable
屬性之后,需要在模型上調用 compile()
。這是一個例子:
x = Input(shape=(32,)) layer = Dense(32) layer.trainable = False y = layer(x) frozen_model = Model(x, y) # 在下面的模型中,訓練期間不會更新層的權重 frozen_model.compile(optimizer='rmsprop', loss='mse') layer.trainable = True trainable_model = Model(x, y) # 使用這個模型,訓練期間 `layer` 的權重將被更新 # (這也會影響上面的模型,因為它使用了同一個網絡層實例) trainable_model.compile(optimizer='rmsprop', loss='mse') frozen_model.fit(data, labels) # 這不會更新 `layer` 的權重 trainable_model.fit(data, labels) # 這會更新 `layer` 的權重
如何從 Sequential 模型中移除一個層?
你可以通過調用 .pop()
來刪除 Sequential
模型中最后添加的層:
model = Sequential() model.add(Dense(32, activation='relu', input_dim=784)) model.add(Dense(32, activation='relu')) print(len(model.layers)) # "2" model.pop() print(len(model.layers)) # "1"
全連接網絡
keras.layers.Dense(units, activation=None, use_bias=True,
kernel_initializer='glorot_uniform', bias_initializer='zeros',
kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None,
kernel_constraint=None, bias_constraint=None)
參數
- units: 正整數,輸出空間維度。
- activation: 激活函數 (activations)。 若不指定,則不使用激活函數 (即,「線性」激活:
a(x) = x
)。 - use_bias: 布爾值,該層是否使用偏置向量。
- kernel_initializer:
kernel
權值矩陣的初始化器 (initializers)。 - bias_initializer: 偏置向量的初始化器 (initializers).
- kernel_regularizer: 運用到
kernel
權值矩陣的正則化函數 (regularizer)。 - bias_regularizer: 運用到偏置向的的正則化函數 (regularizer)。
- activity_regularizer: 運用到層的輸出的正則化函數 (它的 "activation")。 (regularizer)。
- kernel_constraint: 運用到
kernel
權值矩陣的約束函數 (constraints)。 - bias_constraint: 運用到偏置向量的約束函數 (constraints)。
輸入尺寸
n維張量,size:(batch_size, ..., input_dim),最常見的情況是一個尺寸為(batch, input_dim)的二維輸入。
輸出尺寸
n維張量,size:(batch_size, ..., units),例如對於尺寸為 (batch, input_dim)的二維輸入,輸出尺寸為(datch_size, units)
Activation
keras.layers.Activation(activation)
參數
- activation: 要使用的激活函數的名稱 (詳見: activations), 或者選擇一個 Theano 或 TensorFlow 操作。
輸入尺寸和輸出尺寸
任意尺寸。 當使用此層作為模型中的第一層時, 使用參數 input_shape
(整數元組,不包括樣本數的軸)。
循環網絡:簡單RNN、LSTM和GRU
在代碼倉庫的 examples 目錄中,你會找到更多高級模型:基於記憶網絡的問答系統、基於棧式 LSTM 的文本生成等等。
卷積層和池化層
正則化
批歸一化
預定義激活函數概述
Keras實現手寫數字識別
MNIST是一個由美國由美國郵政系統開發的手寫數字識別數據集。手寫內容是0~9,一共有60000個圖片樣本,我們可以到MNIST官網免費下載,總共4個文件,該文件是二進制內容。
train-images-idx3-ubyte.gz: training set images (9912422 bytes) 圖片樣本,用來訓練模型
train-labels-idx1-ubyte.gz: training set labels (28881 bytes) 圖片樣本對應的數字標簽
t10k-images-idx3-ubyte.gz: test set images (1648877 bytes) 測試樣本
t10k-labels-idx1-ubyte.gz: test set labels (4542 bytes) 測試樣本對應的數字標簽
我們下載下來的文件是.gz
后綴的,表明是一個壓縮文件,我們設計代碼的時候,需要考慮對文件進行解壓。
訓練數據集包含 60,000 個樣本, 測試數據集包含 10,000 樣本。在 MNIST 數據集中的每張圖片由 28 x 28 個像素點構成, 每個像素點用一個灰度值表示。
Keras目標函數常見的一些選項
MSE:預測值和真實值指之間的均方誤差
Binary cross-entropy:二分對數損失,該目標函數適合二元標簽預測
$$-tlog(p)-(1-t)log(1-p)$$
Categorical cross-entropy:多元對數損失,該目標函數適合多分類預測,他也是與激活函數softmax相關聯的默認選擇
$$L_i=-\sum _jt_{t,j}log(p_{i,j})$$
Keras常見的性能估計指標
- Accuracy:准確率,針對預測目標的預測正確的比例
- Precision:查准率,衡量多分類問題中多少選擇項是關聯正確的
- Recall:查全率,衡量多分類問題中多少關聯正確的數據被選出來
先用model.compile(lose, optimizer, metrics)編譯模型
model.compile(loss='categorical_crossentropy', optimizer=SGD(), metrics=['accuracy'])
然后用model.fit()訓練模型
model.fit(X_train, Y_train, batch_size, epochs, verbpose, validation_split)
改進神經網絡的方法
增加隱層
dropout
DropOut是深度學習中常用的方法,主要是為了克服過擬合的現象。全連接網絡極高的VC維,使得它的記憶能力非常強,甚至把一下無關緊要的細枝末節都記住,一來使得網絡的參數過多過大,二來這樣訓練出來的模型容易過擬合。
DropOut:是指在在一輪訓練階段臨時關閉一部分網絡節點。讓這些關閉的節點相當去去掉。如下圖所示去掉虛線圓和虛線,原則上是去掉的神經元是隨機的。
keras.layers.Dropout(rate, noise_shape=None, seed=None)
將 Dropout 應用於輸入。
參數
- rate: 在 0 和 1 之間浮動。需要丟棄的輸入比例。
- noise_shape: 1D 整數張量, 表示將與輸入相乘的二進制 dropout 掩層的形狀。 例如,如果你的輸入尺寸為
(batch_size, timesteps, features)
,然后 你希望 dropout 掩層在所有時間步都是一樣的, 你可以使用noise_shape=(batch_size, 1, features)
。 - seed: 一個作為隨機種子的 Python 整數。
選擇更好的優化器
SGD、RMSprop、Adam
增加訓練輪次
優化器的學習率
增加內部隱藏神經元的數量
增加批處理的大小
采用正則化方法避免過擬合
機器學習中有3種不同類型的正則化方法
- L1正則化(也稱為 lasso):模型復雜度表示為權重的絕對值
- L2正則化(也稱為 ridge):模型復雜度表示為權重的平方和
- 彈性網絡正則化:模型復雜度通過聯合前述兩種技術捕捉
L1正則化懲罰項: $Lose = {Lose}_0 + \frac{\lambda }{n}\sum_{w}|w|$
L2正則化懲罰項: $Lose = {Lose}_0 + \frac{\lambda }{2n}\sum_{w}|w^2|$
我們對損失方式添加了正則化懲罰項來進行改造。加上正則化懲罰項能在一定程度上避免過擬合。
前一部分的損失函數叫做“經驗風險”,經驗風險就是由於擬合結果和樣本標簽之間的殘差總和所產生的這種經驗差距所帶來的風險。
后一部分的損失函數叫做“結構風險”,結構風險是因為我們希望這種描述能夠簡潔來保證其泛化性的良好。
注意λλ不是指學習率,而是一個權重,也可以稱為正則化系數,表示對后面這部分的“重視程度”。
舉個例子,比如我們兩個模型的輸入權重系數為下所示,我們使用L2正則化懲罰系數,為了方便我們只計算“結構風險”
$$W_1=\begin{pmatrix}1\\ 0\\ 0\\ 0\end{pmatrix}
W_2=\begin{pmatrix}\frac{1}{4}\\ \frac{1}{4}\\ \frac{1}{4}\\ \frac{1}{4}\end{pmatrix}$$
$$\sum W_1^2=[1,0,0,0]^2=1^2+0^2+0^2+0^2=1$$
$$\sum W_2^2=[\frac{1}{4},\frac{1}{4},\frac{1}{4},\frac{1}{4}]^2={\frac{1}{4}}^2+{\frac{1}{4}}^2+{\frac{1}{4}}^2+{\frac{1}{4}}^2={\frac{1}{4}}$$
由上可見,模型2的結構風險比模型1的小,所以模型2的損失函數小,模型2的泛化能力更強。這就是正則化的好處。
相同的正則化方案可以獨立地應用於權重、模型和激活函數
model.add(Dense(64, input_dim=64, kernel_regularizer= regularizers.l2(0.01)))
超參數
超參數是指那些在機器學習算法中訓練前設定的一些初始化參數,這些參數沒法通過算法本身來學習。比如:$W_0$,$b_0$,還有學習率$\eta $
在搭建神經網絡的時候,我們有件事情不得不做,那就是參數w、b等的初始化,業界來說,把整個網路中所有的w初始化成以0為均值、以一個很小的$\mu $為標准差的正態分布的方式會比較好。
最常見的是以0為均值、1為方差的正態分布來隨機初始化。
還有一種常見的初始化方法是以0為均值、1為方差的正態分布生成后除以當前層的神經元個數的算術平方來獲得初始化。
如果你非要問為什么,思路大致是這樣的:對於一個模型中輸入權重的設置相當於一種重視程度,而一個模型中需要我們非常重視或者不怎么重視的輸入一定是少數,而其他大部分輸入的信息可能就比較中庸,對判斷結果影響比較小的因素的信息比較多。
說來也有意思,自然界中大部分數據的統計分布都服從高斯分布的特點。
輸出預測
當模型訓練好之后,就可以用於測試了。
predictions = model.predict(X)
對於給定的輸入,我們可以計算幾種類型的輸出:
model.evaluate() :用於計算損失值
model.predict_classes() :用於計算輸出類別
model.predict_proba() :用於計算類別概率