Keras的概述
而我之前的筆記主要的針對點就是序貫模型和卷積神經網絡這塊,那今天我們不學習這些東西。從架構上整體的瞭解一下Keras。
Keras是Python中一個以CNTK、TensorFlow或者Theano為計算後臺的深度學習建模環境。相對於常見的幾種深度學習計算軟件,比如TensorFlow、Theano、Caffe、CNTK、Torch等,Keras在實際應用中有如下幾個顯著的優點。Keras在設計時以人為本,強調快速建模,用戶能快速地將所需模型的結構映射到Keras代碼中,儘可能減少編寫代碼的工作量,特別是對於成熟的模型類型,從而加快開發速度。支持現有的常見結構,比如卷積神經網絡、時間遞歸神經網絡等,足以應對大量的常見應用場景。高度模塊化,用戶幾乎能夠任意組合各個模塊來構造所需的模型。
在Keras中,任何神經網絡模型都可以被描述為一個圖模型或者序列模型,其中的部件被劃分為以下模塊:神經網絡層、損失函數、激活函數、初始化方法、正則化方法、優化引擎。這些模塊可以以任意合理地方式放入圖模型或者序列模型中來構造所需的模型,用戶並不需要知道每個模塊後面的細節。這種方式相比其他軟件需要用戶編寫大量代碼或者用特定語言來描述神經網絡結構的方法效率高很多,也不容易出錯。基於Python,用戶也可以使用Python代碼來描述模型,因此易用性、可擴展性都非常高。用戶可以非常容易地編寫自己的定製模塊,或者對已有模塊進行修改或者擴展,因此可以非常方便地開發和應用新的模型與方法,加快迭代速度。能在CPU和GPU之間無縫切換,適用於不同的應用環境。當然,我們強烈推薦GPU環境。
首先這個思維導圖是對Keras中文文檔的整體概述,也可以叫做目錄:
上面從上面導圖我們可以直觀的看到Keras官網文檔主要分為五個方面寫:模型,後端,網絡層,網絡配置,數據預處理。模型分為序貫模型和函數式模型,我們之前學習過就不贅述了;下面利用三個思維導圖展示一下網絡配置,網絡層,數據預處理。(原圖地址:https://blog.csdn.net/sinat_26917383/article/details/72857454?locationNum=1&fps=1)
注意:回調函數 callbacks應該是Keras的精髓。。
3,一個簡單的Keras訓練模型過程
使用Keras訓練模型的步驟圖示如下:
Keras的核心數據結構是model,一種組織網絡層的方式,最簡單的模型是Sequential順序模型,它由多個網絡層線性堆疊。對於更復雜的結構,你應該使用Keras函數式API,它允許構建任意的神經網絡圖。
3.1,選擇模型
Sequential順序模型如下所示:
from keras.models import Sequential
model = Sequential()
3.2,構建網絡層
可以簡單地使用.add()來堆疊模型:
from keras.layers import Dense
model.add(Dense(units=64, activation='relu', input_dim=100))
model.add(Dense(units=10, activation='softmax'))
3.3,編譯
在完成了模型的構建後,可以使用.compile()來配置學習過程。編譯模型時必須指明損失函數和優化器,如果有需要的話也可以自己定製損失函數。
model.compile(loss='categorical_crossentropy',
optimizer='sgd',
metrics=['accuracy'])
如果需要,我們還可以進一步的配置我們的優化器,Keras的核心原則是使事情變得相當簡單,同時又允許用戶在需要的時候能夠進行完全的控制(終控的控制是源代碼的易擴展性)。
model.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.SGD(lr=0.01, momentum=0.9, nesterov=True))
3.4 訓練
現在我們可以批量的在訓練數據上進行迭代了:
# x_train 和 y_train 是 Numpy 數組 -- 就像在 Scikit-Learn API 中一樣。
model.fit(x_train, y_train, epochs=5, batch_size=32)
或者,你可以手動地將批次的數據提供給模型:
model.train_on_batch(x_batch, y_batch)
只需一行代碼就能評估模型性能:
loss_and_metrics = model.evaluate(x_test, y_test, batch_size=128)
3.5 預測
或者對新的數據生成預測:
classes = model.predict(x_test, batch_size=128)
構建一個問答系統,一個圖形分類模型,一個神經圖靈機,或者其他的任何模型,就是這麼的快。我們利用一個小的代碼展示了一個Keras完整的訓練過程,後面就不再贅述了。
4,一些Keras中常見的問題
4.1 為什麼訓練誤差比測試誤差高很多?
一個Keras的模型有兩個模式:訓練模式和測試模式。一些正則機制,如Dropout,L1/L2正則項在測試模式下將不被啟用。
另外,訓練誤差是訓練數據每個batch的誤差的平均。在訓練過程中,每個 epoch 起始時的batch的誤差要大一些,而後面的batch的誤差要小一些。另一方面,每個 epoch 結束時計算的測試誤差是由模型在 epoch結束時的狀態決定的,這時候的網絡將產生較小的誤差。
Tips:可以通過定義回調函數將每個 epoch的訓練誤差和測試誤差並作圖,如果訓練誤差曲線和測試誤差曲線之間有很大的空隙,說明你的模型可能有過擬合的問題。當然,這個問題與Keras無關。
4.2 在Theano和TensorFlow中如何表示一組彩色圖片的尺寸?
Keras提供了兩套後端,Theano和TensorFlow,這是一件幸福的事,就像手裡拿著麵包,想蘸紅糖蘸紅糖,想蘸白糖蘸白糖。如果你從無到有搭建自己的一套網絡,則大可放心。但是如果你想使用一個已有的網絡,或把一個用 th/tf 訓練的網絡以另一種後端應用,在載入的時候你就應該特別小心了。
Theano和TensorFlow在表示一組彩色圖片的問題上有分歧,“th”模式,也就是Theano模式會把100張 RGB 三通道的16*32(高為16 寬為32)彩色圖表示為下面這張形式(100, 3, 16, 32),Caffe採取的也是這種形式。第0個維度為樣本維,代表樣本的樹木,第一個維度是通道維,代表顏色通道數。後面兩個就是高和寬了。這張Theano 風格的數據組織方式,稱為“channels_first”, 即通道維靠前。
而TensorFlow 的表達形式(100, 16, 32,3),即把通道維放在了最後,這張數據組織形式稱為“channels_last”。
注意:卷積核與所使用的後端不匹配,不會報任何錯誤,因為他們的shape是完全一致的,沒有辦法能夠檢測出這種錯誤。所以在使用預訓練模型的時候,一個建議是首先找一些測試樣本,看看模型的表現是否與預計的一致,如需對卷積核進行轉換,可以使用 utils.convert_call_kernels_in_model 對模型的所有卷積核進行轉換。
4.3,模型的節點信息提取
# 節點信息提取
config = model.get_config()
# 把model中的信息,solver.prototxt和train.prototxt信息提取出來
model = Model.from_config(config)
# 還回去
# or, for Sequential:
model = Sequential.from_config(config)
# 重構一個新的Model模型,用去其他訓練,fine-tuning比較好用
4.4 模型概況查詢(包括權重查詢)
# 1、模型概括打印
model.summary()
# 2、返回代表模型的JSON字符串,僅包含網絡結構,不包含權值。可以從JSON字符串中重構原模型:
from models import model_from_json
json_string = model.to_json()
model = model_from_json(json_string)
# 3、model.to_yaml:與model.to_json類似,同樣可以從產生的YAML字符串中重構模型
from models import model_from_yaml
yaml_string = model.to_yaml()
model = model_from_yaml(yaml_string)
# 4、權重獲取
model.get_layer() #依據層名或下標獲得層對象
model.get_weights() #返回模型權重張量的列表,類型為numpy array
model.set_weights() #從numpy array裡將權重載入給模型,要求數組具有與model.get_weights()相同的形狀。
# 查看model中Layer的信息
model.layers 查看layer信息
4.5 當驗證集的 loss 不再下降時,如何中斷訓練?
可以定義 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])
可以參考 官網:回調函數
4.6 如何在每個 epoch後記錄訓練/測試的loss和正確率?
model.fit 在運行結束後返回一個 History 對象,其中含有的 history 屬性包含了訓練過程中損失函數的值以及其他度量指標。
hist = model.fit(X, y, validation_split=0.2)
print(hist.history)
4.7 如何在keras中設定GPU使用的大小
如果採用TensorFlow作為後端,當機器上有可用的GPU時,代碼會自動調用GPU進行並行計算,但是在使用keras時候會出現總是佔滿GPU顯存的情況,可以通過重設backend的GPU佔用情況來進行調節。
import tensorflow as tf
from keras.backend.tensorflow_backend import set_session
config = tf.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = 0.3
set_session(tf.Session(config=config))
需要注意的是,雖然代碼或配置層面設置了對顯存佔用百分比閾值,但在實際運行中如果達到了這個閾值,程序有需要的話還是會突破這個閾值。換而言之如果跑在一個大數據集上還是會用到更多的顯存。以上的顯存限制僅僅為了在跑小數據集時避免對顯存的浪費而已。
4.8 如何更科學的模型訓練與模型保存
filepath = 'model-ep{epoch:03d}-loss{loss:.3f}-val_loss{val_loss:.3f}.h5'
checkpoint = ModelCheckpoint(filepath, monitor='val_loss', verbose=1, save_best_only=True, mode='min')
# fit model
model.fit(x, y, epochs=20, verbose=2, callbacks=[checkpoint], validation_data=(x, y))
save_best_only打開之後,會如下:
ETA: 3s - loss: 0.5820Epoch 00017: val_loss did not improve
如果val_loss 提高了就會保存,沒有提高就不會保存。
4.9,如何在keras中使用tensorboard
RUN = RUN + 1 if 'RUN' in locals() else 1 # locals() 函數會以字典類型返回當前位置的全部局部變量。
LOG_DIR = model_save_path + '/training_logs/run{}'.format(RUN)
LOG_FILE_PATH = LOG_DIR + '/checkpoint-{epoch:02d}-{val_loss:.4f}.hdf5' # 模型Log文件以及.h5模型文件存放地址
tensorboard = TensorBoard(log_dir=LOG_DIR, write_images=True)
checkpoint = ModelCheckpoint(filepath=LOG_FILE_PATH, monitor='val_loss', verbose=1, save_best_only=True)
early_stopping = EarlyStopping(monitor='val_loss', patience=5, verbose=1)
history = model.fit_generator(generator=gen.generate(True), steps_per_epoch=int(gen.train_batches / 4),
validation_data=gen.generate(False), validation_steps=int(gen.val_batches / 4),
epochs=EPOCHS, verbose=1, callbacks=[tensorboard, checkpoint, early_stopping])
都是在回調函數中起作用:
- EarlyStopping patience:當early (1)stop被激活(如發現loss相比上一個epoch訓練沒有下降),則經過patience個epoch後停止訓練。 (2)mode:‘auto’,‘min’,‘max’之一,在min模式下,如果檢測值停止下降則中止訓練。在max模式下,當檢測值不再上升則停止訓練。
- 模型檢查點ModelCheckpoint (1)save_best_only:當設置為True時,將只保存在驗證集上性能最好的模型 (2) mode:‘auto’,‘min’,‘max’之一,在save_best_only=True時決定性能最佳模型的評判準則,例如,當監測值為val_acc時,模式應為max,當檢測值為val_loss時,模式應為min。在auto模式下,評價準則由被監測值的名字自動推斷。 (3)save_weights_only:若設置為True,則只保存模型權重,否則將保存整個模型(包括模型結構,配置信息等) (4)period:CheckPoint之間的間隔的epoch數
- 可視化tensorboard write_images: 是否將模型權重以圖片的形式可視化
4.10 模型概況查詢(包括權重查詢)
# 1、模型概括打印
model.summary()
# 2、返回代表模型的JSON字符串,僅包含網絡結構,不包含權值。可以從JSON字符串中重構原模型:
from models import model_from_json
json_string = model.to_json()
model = model_from_json(json_string)
# 3、model.to_yaml:與model.to_json類似,同樣可以從產生的YAML字符串中重構模型
from models import model_from_yaml
yaml_string = model.to_yaml()
model = model_from_yaml(yaml_string)
# 4、權重獲取
model.get_layer() #依據層名或下標獲得層對象
model.get_weights() #返回模型權重張量的列表,類型為numpy array
model.set_weights() #從numpy array裡將權重載入給模型,要求數組具有與model.get_weights()相同的形狀。
# 查看model中Layer的信息
model.layers
4.11 二分類和多分類編譯模型的參數設置
二分類編譯模型的參數與多分類設置還是有區別的,具體如下:
# 二分類
#model.compile(loss='binary_crossentropy',
# optimizer='rmsprop',
# metrics=['accuracy'])
# 多分類
model.compile(loss='categorical_crossentropy', # matt,多分類,不是binary_crossentropy
optimizer='rmsprop',
metrics=['accuracy'])
# 優化器rmsprop:除學習率可調整外,建議保持優化器的其他默認參數不變
5,Keras中常用數據庫Datasets
5.1 CIFAR10 小圖片分類數據集
該數據庫具有 50000個32*32 的彩色圖片作為訓練集,10000個圖片作為測試集,圖片一共有10個類別。
使用方法:
from keras.datasets import cifar10
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
返回值是兩個Tuple。
X_train和X_test 是形如 (nb_samples, 3, 32, 32)的RGB三通道圖像數據,數據類型是無符號8位整形(uint8)
Y_train和Y_test 是形如(nb_samples, )標籤數據,標籤的範圍是0-9
5.2 CIFAR100 小圖片分類數據集
該數據庫具有 50000個32*32 的彩色圖片作為訓練集,10000個圖片作為測試集,圖片一共有100個類別,每個類別有600張圖片。這100個類別又分為20個大類。
使用方法:
from keras.datasets import cifar100
(X_train, y_train), (X_test, y_test) = cifar100.load_data(lebel_mode='fine')
參數 label_model:為 fine 或 coarse,控制標籤的精細度,‘fine’ 獲得的標籤是100個小類的標籤;coarse獲得的標籤是大類的標籤。
返回值是兩個Tuple。
X_train和X_test 是形如 (nb_samples, 3, 32, 32)的RGB三通道圖像數據,數據類型是無符號8位整形(uint8)
Y_train和Y_test 是形如(nb_samples, )標籤數據,標籤的範圍是0-9
5.3 MNIST 手寫數字識別
該數據庫具有 60000個28*28 的灰度手寫數字圖片作為訓練集,10000個圖片作為測試集
使用方法:
from keras.datasets import mnist
(X_train, y_train), (X_test, y_test) = mnist.load_data()
參數 path:如果你本機上已經有此數據集(位於'~/.keras/datasets/'+path),則載入,否則數據將下載到該目錄下。
返回值是兩個Tuple。
X_train和X_test 是形如 (nb_samples, 28, 28)的RGB三通道圖像數據,數據類型是無符號8位整形(uint8)
Y_train和Y_test 是形如(nb_samples, )標籤數據,標籤的範圍是0-9
數據庫會被下載到 ~/.keras/datasets/'+path
5.4 Boston 房屋價格迴歸數據庫
該數據庫由StatLib庫取得,由CMU維護,每個樣本都是 1970s晚期波士頓郊區的不同位置,每條數據含有13個屬性,目標值是該位置房子的房價中位數(千 dollar)。
使用方法:
from keras.datasets import boston_housing
(X_train, y_train), (X_test, y_test) = boston_housing.load_data()
參數 path:如果你本機上已經有此數據集(位於'~/.keras/datasets/'+path),則載入,否則數據將下載到該目錄下。
參數 seed:隨機數種子
參數 test_split:分割測試集的比例
返回值是兩個Tuple。
X_train和X_test Y_train和Y_test
數據庫會被下載到 ~/.keras/datasets/'+path
5.5 IMDB 影評傾向分類
本數據庫含有來自 IMDB 的 25000 條影評,被標記為正面/負面兩種評價。影評已被預處理為詞下標構成的序列。方便起見,單詞的下標基於它在數據集中出現的頻率標定,例如整數3所編碼的詞為數據中第三常出現的詞。這樣的組織方式使得用戶可以快速完成諸如“只考慮最常出現的10000個詞,但不考慮最常出現的20個詞”這樣的操作。
按照慣例,0不代表任何特定的詞,而用來編碼任何未知單詞。
使用方法
from keras.datasets import imdb
(X_train, y_train), (X_test, y_test) = imdb.load_data(
path='imdb.npz', num_words=None, skip_top=0,
maxlen=None, seed=113,
start_char=1, oov_char=2, index_from=3, )
參數path:如果你本機上已經有此數據集(位於'~/.keras/datasets/'+path),則載入,否則數據將下載到該目錄下。
參數 nb_words:整數或None,要考慮的最常見的單詞數,序列中任何出現頻率更低的單詞將會被編碼為 oov_char 的值。
參數skip_top:整數,忽略最常出現的若干單詞,這些單詞將會被編碼為 oov_char的值。
參數maxlen:整數,最大序列長度,任何長度大於此值的序列將會被截斷。
參數 seed:整數,用於數據重排的隨機數種子
參數start_char:字符,序列的起始將以該字符標記,默認為1 因為0通常用作padding
參數oov_char:整數,因 nb_words或 skip_top 限制而 cut 掉的單詞將被該字符代替
參數index_form:整數,真實的單詞(而不是類似於 start_char的特殊佔位符)將從這個下標開始
返回值是兩個Tuple。
X_train和X_test 序列的列表,每個序列都是詞下標的列表,如果指定了 nb_words,則序列中可能的最大下標為 nb_word-1.如果指定了 maxlen,則序列的最大可能長度為 maxlen
y_train和y_test 序列的標籤,是一個二值 list
5.6 路透社新聞主題分類
該數據庫包含來自路透社的11228條新聞,分為了46個主題,與IMDB庫一樣,每條新聞被編碼為一個詞下標的序列。
使用方法:
from keras.datasets import reuters
(X_train, y_train), (X_test, y_test) = reuters.load_data(
path='reuters.npz', num_words=None, skip_top=0,
maxlen=None, test_split=0.2, seed=113,
start_char=1, oov_char=2, index_from=3,
)
參數的含義與 IMDB同名參數相同,唯一多的參數是:test_split,用於指定從原數據中分割出作為測試集的比例。該數據庫支持獲取用於編碼序列的詞的下標:
1
word_index = reuters.get_word_index(path='reuters_word_index.json')
上面的代碼的返回值是一個以單詞為關鍵字,以其下標為值的字典,例如 word_index['giraffe'] 的值可能是1234.
參數path:如果你在本機上有此數據集(位於 ~/.keras/datasets/'+path),則載入。否則數據將下載到該目錄下
5.7 多分類標籤指定Keras格式
數據集的載入上面都說了,而下面要強調的是Keras對多分類的標籤需要一種固定格式,所以需要按照以下的方式進行轉換,num_classes 為分類數量,假設此時有五類:
y_train = keras.utils.to_categorical(y_train, num_classes)
最終輸出的格式應該是(100, 5)
to_categorical 函數如下:
to_categorical(y, num_classes = None)
將類別向量(從0到 nb_classes的整數向量)映射為二值類別矩陣,用於應用到以 categorical_crossentropy 為目標函數的模型中。 其中y表示類別向量,num_classes表示總共類別數。
6,延伸
6.1 fine-tuning 時如何加載 No_top 的權重
如果你需要加載權重到不同的網絡結構(有些層一樣)中,例如 fine-tune或transfer-learning,你可以通過層名字來加載模型:
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)
新模型如下:
# new model
model = Sequential()
model.add(Dense(2, input_dim=3, name="dense_1")) # will be loaded
model.add(Dense(10, name="new_dense")) # will not be loaded
# load weights from first model; will only affect the first layer, dense_1.
model.load_weights(fname, by_name=True)
6.2 應對不均衡樣本的情況
使用 class_weight, sample_weight
兩者的區別為
- class_weight 主要針對的時數據不均衡問題,比如:異常檢測的二項分類問題,異常數據僅佔 1%,正常數據佔 99 %;此時就要設置不同類對 loss 的影響。
- sample_weight 主要解決的時樣本質量不同的問題,比如前 1000 個樣本的可信度,那麼他的權重就要高,後 1000個樣本可能有錯,不可信,那麼權重就要調低。
class-weight 的使用:
cw = {0: 1, 1: 50}
model.fit(x_train, y_train,batch_size=batch_size,epochs=epochs,verbose=1,callbacks=cbks,
validation_data=(x_test, y_test), shuffle=True,class_weight=cw)
sample_weight 的使用:
from sklearn.utils import class_weight
list_classes = ["toxic", "severe_toxic", "obscene", "threat", "insult", "identity_hate"]
y = train[list_classes].values
sample_weights = class_weight.compute_sample_weight('balanced', y)
model.fit(X_t, y, batch_size=batch_size, epochs=epochs,validation_split=0.1,sample_weight=sample_weights, callbacks=callbacks_list)
閱讀更多 風信子編程 的文章