【Keras】学习笔记(一)
傳送門:Keras 中文文檔
文章目錄
- 一、準備工作
- 1、概述
- 2、安裝
- 3、GPU設置
- (1)單GPU運行
- (2)多GPU運行
- 二、順序模型 簡單示例
- 1、整體流程
- (1)順序模型的構建——Sequential()
- (2)模型編譯——compile
- (3)模型訓練——fit
- (4)模型保存
- a、保存/加載整個模型(結構 + 權重 + 優化器狀態)
- b、只保存/加載模型的結構*:無其權重或訓練配置項
- c、只保存/加載模型的權重:保存成 HDF5 格式
- d、處理已保存模型中的自定義層(或其他自定義對象)
- (5)獲取中間層的輸出
- 2、示例
- (1)樣例1:基于多層感知器 (MLP) 的 softmax 多分類
- (2)示例2:類似 VGG 的卷積神經網絡
- (3)示例3:基于 LSTM 的序列分類
- (4)示例4:用于序列分類的棧式LSTM
- (5)示例5:"stateful" 渲染的的棧式 LSTM 模型
- 三、Keras 函數式 API
- 1、示例
- 2、多輸入多輸出模型
- 3、共享網絡層
- (1)共享網絡層
- (2)讀取共享層的輸出或輸出尺寸
- 4、其他示例
- (1)Inception
- (2)Conv上的殘差連接
- (3)共享視覺模型
- (4)視覺問答模型
- (5)視頻問答模型
一、準備工作
1、概述
Keras 是一個用 Python 編寫的高級神經網絡 API,它能夠以 TensorFlow, CNTK, 或者 Theano 作為后端運行。Keras 的開發重點是支持快速的實驗。能夠以最小的時延把你的想法轉換為實驗結果,是做好研究的關鍵。
Keras 支持多個后端引擎,即可以基于不同的深度學習后端開發。重要的是,任何僅利用內置層構建的 Keras 模型,都可以在所有這些后端中移植:你可以用一種后端訓練模型,再將它載入另一種后端中(例如為了發布的需要)。支持的后端有:
- 谷歌的 TensorFlow 后端
- 微軟的 CNTK 后端
- Theano 后端
- 亞馬遜也正在為 Keras 開發 MXNet 后端。
2、安裝
pip install keras3、GPU設置
(1)單GPU運行
根據后端的不同:
- TensorFlow 或 CNTK 后端:只要檢測到任何可用的 GPU,那么代碼將自動在 GPU 上運行。
- Theano 后端:
- 方法1:使用 Theano flags。gpu 可能需要根據你的設備標識符(例如gpu0,gpu1等)進行更改。THEANO_FLAGS=device=gpu,floatX=float32 python test.py
- 方法 2:創建 .theanorc,詳見 Theano Configuration
- 方法 3:在代碼的開頭手動設置 theano.config.device, theano.config.floatX:import theano theano.config.device = 'gpu' theano.config.floatX = 'float32'
(2)多GPU運行
建議使用 Tensorflow 后端實現,方法:數據并行 和 設備并行。
- 數據并行(大多數情況):在每個設備上復制一次目標模型,并使用每個模型副本處理不同部分的輸入數據。
- 使用內置函數 keras.utils.multi_gpu_model:可以生成任何模型的數據并行版本,在多達 8 個 GPU 上實現準線性加速。
- 文檔:multi_gpu_model
- 示例:from keras.utils import multi_gpu_model# 將 `model` 復制到 8 個 GPU 上。假定機器有 8 個可用的 GPU。 parallel_model = multi_gpu_model(model, gpus=8) parallel_model.compile(loss='categorical_crossentropy',optimizer='rmsprop')# 這個 `fit` 調用將分布在 8 個 GPU 上。 # 由于 batch size 為 256,每個 GPU 將處理 32 個樣本。 parallel_model.fit(x, y, epochs=20, batch_size=256)
- 設備并行:在不同設備上運行同一模型的不同部分。
- 適用于具有并行體系結構的模型,eg:兩個分支的模型;
- 使用 TensorFlow 的 device_scopes 來實現;
- 示例:
二、順序模型 簡單示例
1、整體流程
(1)順序模型的構建——Sequential()
方法:
- 通過網絡層的列表構建
- 使用 .add() 方法將各層添加到模型中
指定輸入數據的尺寸:順序模型中的第一層(且只有第一層,因為下面的層可以自動地推斷尺寸)需要接收關于其輸入尺寸的信息。
- input_shape 參數:一個表示尺寸的元組 (一個由整數或 None 組成的元組,其中 None 表示可能為任何正整數)。在 input_shape 中不包含數據的 batch 大小。
- 具體的層可能會支持特定的參數:Dense 層通過參數 input_dim 指定輸入尺寸、某些 3D 時序層支持 input_dim 和 input_length 參數。
- batch_size 參數:設置 batch 的大小,eg:同時傳遞 batch_size=32 和 input_shape=(6, 8),則每一批輸入的尺寸就為 (32,6,8)
- 示例,兩者等價:model = Sequential() model.add(Dense(32, input_shape=(784, )))model = Sequential() model.add(Dense(32, input_dim=784)))
(2)模型編譯——compile
配置模型學習的過程,通過 compile 方法實現,其參數如下:
- optimizer 參數:優化器 ??梢允?strong>現有優化器的字符串標識符,如 rmsprop 或 adagrad,也可以是 Optimizer 類的實例。
- loss 參數:損失函數,模型試圖最小化的目標函數。可以是現有損失函數的字符串標識符,如 categorical_crossentropy 或 mse,也可以是一個 目標函數 。
- metrics 參數:評估標準。分類問題,至少設置 metrics = ['accuracy']。評估標準可以是現有的標準的字符串標識符,也可以是自定義的評估標準函數。
(3)模型訓練——fit
訓練數據均為Numpy矩陣。
示例1:
## 數據生成 import numpy as npdata = np.random.random((1000, 100)) labels = np.random.randint(2, size=(1000, 1))## 模型構建:二分類模型 model = Sequential() model.add(Dense(32, activation='relu', input_dim = 100)) model.add(Dense(1, activation='sigmoid')) model.compile(optimizer='rmsprop',loss='binary_crossentropy',metrics=['accuracy'])## 模型訓練 model.fit(data, labels, epochs=10, batch_size=32)示例2:
## 數據生成 import numpy as npdata = np.random.random((1000, 100)) labels = np.random.randint(10, size=(1000, 1))## 模型構建:多分類模型 model = Sequential() model.add(Dense(32, activation='relu', input_dim = 100)) model.add(Dense(10, activation='softmax')) model.compile(optimizer='rmsprop',loss='categorical_crossentropy',metrics=['accuracy'])## 將標簽轉換為分類的 one-hot 編碼 import keras one_hot_labels = keras.utils.to_categorical(labels, num_classes=10)## 訓練模型 model.fit(data, one_hot_labels, epochs=10, batch_size=32)(4)模型保存
a、保存/加載整個模型(結構 + 權重 + 優化器狀態)
- 使用 model.save(filepath) 將 Keras 模型保存到單個 HDF5 文件中,該文件包括:
- 模型的結構,允許重新創建模型;
- 模型的權重;
- 訓練配置項(損失函數,優化器);
- 優化器狀態,允許準確地從你上次結束的地方繼續訓練。
- 使用 keras.models.load_model(filepath) 重新實例化模型。此外,還負責使用保存的訓練配置項來編譯模型(除非模型從未編譯過)。
- 注意:不建議使用 pickle 或 cPickle 來保存 Keras 模型。
- 示例:
b、只保存/加載模型的結構*:無其權重或訓練配置項
- 生成 JSON/YAML 文件,可讀、可手動編輯;
- 示例:
c、只保存/加載模型的權重:保存成 HDF5 格式
- 保存參數、加載參數(同結構、有共同層)
- 示例:
d、處理已保存模型中的自定義層(或其他自定義對象)
若要加載的模型包含自定義層或其他自定義類或函數,則可以通過 custom_objects 參數將它們傳遞給加載機制。
from keras.models import load_model# 假設模型包含一個 AttentionLayer 類的實例 model = load_model('my_model.h5', custom_objects={'AttentionLayer': AttentionLayer})或 使用 自定義對象作用域
from keras.utils import CustomObjectScopewith CustomObjectScope({'AttentionLayer': AttentionLayer}):model = load_model('my_model.h5')自定義對象的處理與 load_model, model_from_json, model_from_yaml 的工作方式相同
from keras.models import model_from_jsonmodel = model_from_json(json_string, custom_objects={'AttentionLayer': AttentionLayer})(5)獲取中間層的輸出
方法一:創建一個新的 Model 來輸出你所感興趣的層
from keras.models import Modelmodel = ... # 創建原始模型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 函數,也可構建 Theano 或 TensorFlow 函數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]
- 注意:若模型在訓練和測試階段有不同的行為(例如,使用 Dropout, BatchNormalization 等),則需要將學習階段標志傳遞給你的函數:get_3rd_layer_output = K.function([model.layers[0].input, K.learning_phase()],[model.layers[3].output])# 測試模式 = 0 時的輸出 layer_output = get_3rd_layer_output([x, 0])[0]# 測試模式 = 1 時的輸出 layer_output = get_3rd_layer_output([x, 1])[0]
2、示例
(1)樣例1:基于多層感知器 (MLP) 的 softmax 多分類
import keras from keras.models import Sequential from keras.layers import Dense, Dropout, Activation from keras.optimizers import SGD## 數據生成 import numpy as npx_train = np.random.random((1000, 20)) y_train = keras.utils.to_categorical(np.random.randint(10, size=(1000, 1)), num_classes=10) x_test = np.random.random((100, 20)) y_test = keras.utils.to_categorical(np.random.randint(10, size=(100, 1)), num_classes=10)## 模型構建 model = Sequential() model.add(Dense(64, activation='relu', input_dim=20)) model.add(Dropout(0.5)) model.add(Dense(64, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(10, activation='softmax'))sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True) model.compile(loss='categorical_crossentropy',optimizer=sgd,metrics=['accuracy']) model.fit(x_train, y_train,epochs=20,batch_size=128) score = model.evaluate(x_test, y_test, batch_size=128)(2)示例2:類似 VGG 的卷積神經網絡
import numpy as np import keras from keras.models import Sequential from keras.layers import Dense, Dropout, Flatten from keras.layers import Conv2D, MaxPooling2D from keras.optimizers import SGD# 生成虛擬數據 x_train = np.random.random((100, 100, 100, 3)) y_train = keras.utils.to_categorical(np.random.randint(10, size=(100, 1)), num_classes=10) x_test = np.random.random((20, 100, 100, 3)) y_test = keras.utils.to_categorical(np.random.randint(10, size=(20, 1)), num_classes=10)## 模型構建 model = Sequential() # 輸入: 3 通道 100x100 像素圖像 -> (100, 100, 3) 張量。 # 使用 32 個大小為 3x3 的卷積濾波器。 model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(100, 100, 3))) model.add(Conv2D(32, (3, 3), activation='relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25))model.add(Conv2D(64, (3, 3), activation='relu')) model.add(Conv2D(64, (3, 3), activation='relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25))model.add(Flatten()) model.add(Dense(256, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(10, activation='softmax'))sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True) model.compile(optimizer=sgd,loss='categorical_crossentropy')model.fit(x_train, y_train, batch_size=32, epochs=10) score = model.evaluate(x_test, y_test, batch_size=32)(3)示例3:基于 LSTM 的序列分類
from keras.models import Sequential from keras.layers import Dense, Dropout from keras.layers import Embedding from keras.layers import LSTMtimesteps = 7 #句子長度 num_classes = 9 #類別數 max_features = 8 #詞匯量 batch = 5# 創建虛假的訓練數據 x_train = np.random.randint(max_features,size=(batch, timesteps)) #存的是各個字在embedding中的index y_train = np.random.randint(num_classes, size=(batch, 1))model = Sequential() model.add(Embedding(max_features, output_dim=20, input_length=timesteps)) model.add(LSTM(20)) model.add(Dropout(0.5)) model.add(Dense(1, activation='sigmoid'))model.compile(loss='binary_crossentropy',optimizer='rmsprop',metrics=['accuracy'])model.fit(x_train, y_train, batch_size=16, epochs=10)(4)示例4:用于序列分類的棧式LSTM
結構:三個LSTM堆疊。 開始的兩層LSTM返回其全部輸出序列,而第三層LSTM只返回其輸出序列的最后一步結果,從而其時域維度降低(即將輸入序列轉換為單個向量)
(5)示例5:“stateful” 渲染的的棧式 LSTM 模型
有狀態 (stateful) 的循環神經網絡模型中:在一個 batch 的樣本處理完成后,其內部狀態(記憶)會被記錄并作為下一個 batch 的樣本的初始狀態。這允許處理更長的序列,同時保持計算復雜度的可控性。
from keras.models import Sequential from keras.layers import LSTM, Dense import numpy as npdata_dim = 16 timesteps = 8 num_classes = 10 batch_size = 32# 生成虛擬訓練數據 x_train = np.random.random((batch_size * 10, timesteps, data_dim)) y_train = np.random.random((batch_size * 10, num_classes)) # 生成虛擬驗證數據 x_val = np.random.random((batch_size * 3, timesteps, data_dim)) y_val = np.random.random((batch_size * 3, num_classes))# 期望輸入數據尺寸: (batch_size, timesteps, data_dim) # 請注意,我們必須提供完整的 batch_input_shape,因為網絡是有狀態的。 # 第 k 批數據的第 i 個樣本是第 k-1 批數據的第 i 個樣本的后續。 model = Sequential() model.add(LSTM(32, return_sequences=True, stateful=True,batch_input_shape=(batch_size, timesteps, data_dim))) model.add(LSTM(32, return_sequences=True, stateful=True)) model.add(LSTM(32, stateful=True)) model.add(Dense(10, activation='softmax'))model.compile(loss='categorical_crossentropy',optimizer='rmsprop',metrics=['accuracy']) model.fit(x_train, y_train,batch_size=batch_size, epochs=5, shuffle=False,validation_data=(x_val, y_val))三、Keras 函數式 API
Keras 函數式 API :定義復雜模型(如多輸出模型、有向無環圖,或具有共享層的模型)的方法。
1、示例
- 網絡層的實例是可調用的,它以張量為參數,并且返回一個張量;
- 輸入和輸出均為張量,它們都可以用來定義一個模型(Model);
- 這樣的模型同 Keras 的 Sequential 模型一樣,都可以被訓練;
所有的模型都可調用,就像網絡層一樣
- 便于重用訓練好的模型:可以將任何模型看作是一個層,然后通過傳遞一個張量來調用它。
- 注意:在調用模型時,您不僅重用模型的結構,還重用了它的權重。
- 示例:圖像分類 =》視頻分類
2、多輸入多輸出模型
函數式 API 使 處理大量交織的數據流 變得容易。
示例:預測 Twitter 上的一條新聞標題有多少轉發和點贊數。
- 模型的主要輸入:新聞標題本身,即一系列詞語,其他的輔助輸入:例如新聞標題的發布的時間等。
- 該模型也將通過兩個損失函數進行監督學習。較早地在模型中使用主損失函數,是深度學習模型的一個良好正則方法。
模型結構如下:
實現
- 主要輸入:新聞標題,即一個整數序列(每個整數編碼一個詞)。 這些整數在 1 到 10,000 之間(10,000 個詞的詞匯表),且序列長度為 100 個詞。
3、共享網絡層
(1)共享網絡層
目標:建立一個模型來分辨兩條推文是否來自同一個人(例如,通過推文的相似性來對用戶進行比較)。
方法:建立一個模型,將兩條推文編碼成兩個向量,連接向量,然后添加邏輯回歸層;這將輸出兩條推文來自同一作者的概率。模型將接收一對對正負表示的推特數據。
分析:該問題是對稱的,編碼第一條推文的機制應該被完全重用來編碼第二條推文(權重及其他全部)。這里我們使用一個共享的 LSTM 層來編碼推文。
數據預處理:首先 將一條推特轉換為一個尺寸為 (280, 256) 的矩陣,即每條推特 280 字符,每個字符為 256 維的 one-hot 編碼向量 (取 256 個常用字符)。
import keras from keras.layers import Input, LSTM, Dense from keras.models import Model##### 模型構建 tweet_a = Input(shape=(280, 256)) tweet_b = Input(shape=(280, 256)) ## 共享網絡層:該層只實例化一次,然后傳入想要的輸入即可 # 這一層可以輸入一個矩陣,并返回一個 64 維的向量 shared_lstm = LSTM(64) # 當我們重用相同的圖層實例多次,圖層的權重也會被重用 (它其實就是同一層) encoded_a = shared_lstm(tweet_a) encoded_b = shared_lstm(tweet_b) # 連接兩個向量 merged_vector = keras.layers.concatenate([encoded_a, encoded_b], axis=-1) pred = Dense(1, activation='sigmoid')(merged_vector) # 定義一個連接推特輸入和預測的可訓練的模型 model = Model(inputs=[tweet_a, tweet_b], outputs=pred)##### 編譯與訓練 model.compile(optimizer='rmsprop',loss='binary_crossentropy',metrics=['accuracy']) model.fit([data_a, data_b], labels, epochs=10)(2)讀取共享層的輸出或輸出尺寸
每當在某個輸入上調用一個層時,都將創建一個新的張量(層的輸出),并且為該層添加一個「節點」,將輸入張量連接到輸出張量。當多次調用同一個圖層時,該圖層將擁有多個節點索引 (0, 1, 2…)。
- layer.output:獲得層實例的輸出張量;
- layer.output_shape:獲取其輸出形狀;
- layer.input_shape:獲取其輸入形狀;
注意1:如果該層有多個輸入,則不能用 layer.output 獲取輸出的張量
a = Input(shape=(280, 256)) b = Input(shape=(280, 256))lstm = LSTM(32) encoded_a = lstm(a) # 輸入1 encoded_b = lstm(b) # 輸入2assert lstm.get_output_at(0) == encoded_a assert lstm.get_output_at(1) == encoded_b注意2:同上示例
a = Input(shape=(32, 32, 3)) b = Input(shape=(64, 64, 3))conv = Conv2D(16, (3, 3), padding='same') conved_a = conv(a)# 到目前為止只有一個輸入,以下可行: assert conv.input_shape == (None, 32, 32, 3)conved_b = conv(b) # 現在 `.input_shape` 屬性不可行,但是這樣可以: assert conv.get_input_shape_at(0) == (None, 32, 32, 3) assert conv.get_input_shape_at(1) == (None, 64, 64, 3)4、其他示例
(1)Inception
##### Inception from keras.layers import Conv2D, MaxPooling2D, Inputinput_img = Input(shape=(256, 256, 3))tower_1 = Conv2D(64, (1, 1), padding='same', activation='relu')(input_img) tower_1 = Conv2D(64, (3, 3), padding='same', activation='relu')(tower_1)tower_2 = Conv2D(64, (1, 1), padding='same', activation='relu')(input_img) tower_2 = Conv2D(64, (5, 5), padding='same', activation='relu')(tower_2)tower_3 = MaxPooling2D((3, 3), strides=(1, 1), padding='same')(input_img) tower_3 = Conv2D(64, (3, 3), padding='same', activation='relu')(tower_3)output = keras.layers.concatenate([tower_1, tower_2, tower_3])(2)Conv上的殘差連接
##### Conv上的殘差連接 from keras.layers import Conv2D, Inputx = Input(shape=(256, 256, 3)) y = Conv2D(3, (3, 3), padding='same')(x)z = keras.layers.add([x, y])(3)共享視覺模型
共享視覺模型:在兩個輸入上重復使用同一個圖像處理模塊,以判斷兩個 MNIST 數字是否為相同的數字。
from keras.layers import Conv2D, MaxPooling2D, Input, Dense, Flatten from keras.models import Model# 首先,定義視覺模型 digit_input = Input(shape=(27, 27, 1)) x = Conv2D(64, (3, 3))(digit_input) x = Conv2D(64, (3, 3))(x) x = MaxPooling2D((2, 2))(x) output = Flatten(x) vision_model = Model(digit_input, output)# 然后,定義區分數字的模型 digit_a = Input(shape=(27, 27, 1)) digit_b = Input(shape=(27, 27, 1))# 視覺模型將被共享,包括權重和其他所有,并構建新網絡 out_a = vision_model(digit_a) out_b = vision_model(digit_b) concatenated = keras.layers.concatenate([out_a, out_b]) output = Dense(1, activation='sigmoid')(concatenated)classification_model = Model([digit_a, digit_b], output)(4)視覺問答模型
目標:當問關于圖片的自然語言問題時,選擇正確的單詞作答。
方法:它通過將問題和圖像編碼成向量,然后連接兩者,在上面訓練一個邏輯回歸,來從詞匯表中挑選一個可能的單詞作答。
from keras.layers import Conv2D, MaxPooling2D, Flatten from keras.layers import Input, LSTM, Embedding, Dense from keras.models import Model, Sequential## 定義視覺模型,該模型將圖像編碼為向量 vision_model = Sequential() vision_model.add(Conv2D(64, (3, 3), activation='relu', padding='same', input_shape=(224, 224, 3))) vision_model.add(Conv2D(64, (3, 3), activation='relu')) vision_model.add(MaxPooling2D((2, 2))) vision_model.add(Conv2D(128, (3, 3), activation='relu', padding='same')) vision_model.add(Conv2D(128, (3, 3), activation='relu')) vision_model.add(MaxPooling2D((2, 2))) vision_model.add(Conv2D(256, (3, 3), activation='relu', padding='same')) vision_model.add(Conv2D(256, (3, 3), activation='relu')) vision_model.add(Conv2D(256, (3, 3), activation='relu')) vision_model.add(MaxPooling2D((2, 2))) vision_model.add(Flatten()) ## 用視覺模型來得到一個輸出張量: image_input = Input(shape=(224, 224, 3)) encoded_image = vision_model(image_input)## 定義語言模型,將問題編碼成一個向量。每個問題最長 100 個詞,詞的索引從 1 到 9999. question_input = Input(shape=(100, ), dtype='int32') embedded_question = Embedding(input_dim=10000, output_dim=256, input_length=100)(question_input) encoded_question = LSTM(256)(embedded_question)# 連接問題向量和圖像向量 merged = keras.layers.concatenate([encoded_question, encoded_image])# 然后在上面訓練一個 1000 詞的邏輯回歸模型 output = Dense(1000, activation='softmax')(merged)# 最終模型 vqa_model = Model(inputs=[image_input, question_input], outputs=output)(5)視頻問答模型
目標:圖像問答模型 ==》 視頻問答模型。在適當的訓練下,你可以給它展示一小段視頻(例如 100 幀的人體動作),然后問它一個關于這段視頻的問題(例如,「這個人在做什么運動?」 -> 「足球」)。
from keras.layers import TimeDistributedvideo_input = Input(shape=(100, 224, 224, 3)) ### 基于之前定義的視覺模型(權重被重用)構建的視頻編碼 # 輸出為向量的序列 encoded_frame_sequence = TimeDistributed(vision_model)(video_input) # 輸出為一個向量 encoded_video = LSTM(256)(encoded_frame_sequence)# 這是問題編碼器的模型級表示,重復使用與之前相同的權重: question_encoder = Model(inputs=question_input, outputs=encoded_question)#用它來編碼這個問題: video_question_input = Input(shape=(100, ), dtype='int32') encoded_video_question = question_encoder(video_question_input)#視頻問答模式: merged = keras.layers.concatenate([encoded_video, encoded_video_question]) out = Dense(1000, activation='softmax')(merged) video_qa_model = Model(inputs=[video_input, video_question_input], outputs=output)總結
以上是生活随笔為你收集整理的【Keras】学习笔记(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【知识图谱实战】 Neo4j入门与示例
- 下一篇: 【Keras】学习笔记(二)