【Keras】學習筆記(一)

傳送門:Keras 中文文檔

一、準備工作

1、概述

Keras 是一個用 Python 編寫的高級神經網絡 API,它能夠以 TensorFlow, CNTK, 或者 Theano 作爲後端運行。Keras 的開發重點是支持快速的實驗。能夠以最小的時延把你的想法轉換爲實驗結果,是做好研究的關鍵。

Keras 支持多個後端引擎,即可以基於不同的深度學習後端開發。重要的是,任何僅利用內置層構建的 Keras 模型,都可以在所有這些後端中移植:你可以用一種後端訓練模型,再將它載入另一種後端中(例如爲了發佈的需要)。支持的後端有:

  • 谷歌的 TensorFlow 後端
  • 微軟的 CNTK 後端
  • Theano 後端
  • 亞馬遜也正在爲 Keras 開發 MXNet 後端。

2、安裝

pip install keras

3、GPU設置

(1)單GPU運行

根據後端的不同:

  • TensorFlow 或 CNTK 後端:只要檢測到任何可用的 GPU,那麼代碼將自動在 GPU 上運行。
  • Theano 後端
    • 方法1:使用 Theano flags。gpu 可能需要根據你的設備標識符(例如gpu0gpu1等)進行更改。
      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 來實現;
    • 示例
# 模型中共享的 LSTM 用於並行編碼兩個不同的序列
input_a = keras.Input(shape=(140, 256))
input_b = keras.Input(shape=(140, 256))

shared_lstm = keras.layers.LSTM(64)

# 在一個 GPU 上處理第一個序列
with tf.device_scope('/gpu:0'):
    encoded_a = shared_lstm(tweet_a)
# 在另一個 GPU上 處理下一個序列
with tf.device_scope('/gpu:1'):
    encoded_b = shared_lstm(tweet_b)

# 在 CPU 上連接結果
with tf.device_scope('/cpu:0'):
    merged_vector = keras.layers.concatenate([encoded_a, encoded_b],
                                             axis=-1)

二、順序模型 簡單示例

1、整體流程

(1)順序模型的構建——Sequential()

方法:

  • 通過網絡層的列表構建
  • 使用 .add() 方法將各層添加到模型中
## 順序模型構建
#  1. 通過網絡層的列表構建
model = Sequential([
        Dense(32, input_shape=(784,)),
        Activation('relu'),
        Dense(10),
        Activation('softmax'),
        ])
        
#  2.使用 .add() 方法將各層添加到模型中
model = Sequential()
model.add(Dense(units=32, activation='relu', input_dim=784))
model.add(Dense(units=10, activation='softmax'))

指定輸入數據的尺寸:順序模型中的第一層(且只有第一層,因爲下面的層可以自動地推斷尺寸)需要接收關於其輸入尺寸的信息。

  • input_shape 參數:一個表示尺寸的元組 (一個由整數或 None 組成的元組,其中 None 表示可能爲任何正整數)。在 input_shape 中不包含數據的 batch 大小。
    • 具體的層可能會支持特定的參數:Dense 層通過參數 input_dim 指定輸入尺寸、某些 3D 時序層支持 input_diminput_length 參數。
  • batch_size 參數:設置 batch 的大小,eg:同時傳遞 batch_size=32input_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 參數:優化器 。可以是現有優化器的字符串標識符,如 rmspropadagrad,也可以是 Optimizer 類的實例
  • loss 參數:損失函數,模型試圖最小化的目標函數。可以是現有損失函數的字符串標識符,如 categorical_crossentropymse,也可以是一個 目標函數
  • metrics 參數:評估標準。分類問題,至少設置 metrics = ['accuracy']。評估標準可以是現有的標準的字符串標識符,也可以是自定義的評估標準函數。
## 多分類器問題
model.compile(optimizer='rmsprop',
              loss='categorical_crossentropy',
              metrics=['accuracy'])

## 二分類問題
model.compile(optimizer='rmsprop',
              loss='binary_crossentropy',
              metrics=['accuracy'])

## 均方誤差迴歸問題
model.compile(optimizer='rmsprop',
              loss='mse')

## 自定義評估標準函數
import keras.backend as K

def maen_pred(y_true, y_pred):
    return K.mean(y_pred)

model.compile(optimizer='rmsprop',
              loss='binary_crossentropy',
              metrics=['accuracy', mean_pred])

(3)模型訓練——fit

訓練數據均爲Numpy矩陣。

示例1

## 數據生成
import numpy as np

data = 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 np

data = 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 模型。
  • 示例:
from keras.models import load_model

model.save('my_model.h5')  # 創建 HDF5 文件 'my_model.h5'
del model  # 刪除現有模型

# 返回一個編譯好的模型
# 與之前那個相同
model = load_model('my_model.h5')

b、只保存/加載模型的結構*:無其權重或訓練配置項

  • 生成 JSON/YAML 文件,可讀、可手動編輯;
  • 示例:
#####   保存模型
# 保存爲 JSON
json_string = model.to_json()
# 保存爲 YAML
yaml_string = model.to_yaml()

#####   重建模型
# 從 JSON 重建模型:
from keras.models import model_from_json
model = model_from_json(json_string)
# 從 YAML 重建模型:
from keras.models import model_from_yaml
model = model_from_yaml(yaml_string)

c、只保存/加載模型的權重:保存成 HDF5 格式

  • 保存參數、加載參數(同結構、有共同層)
## 保存參數
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)

d、處理已保存模型中的自定義層(或其他自定義對象)

若要加載的模型包含自定義層或其他自定義類或函數,則可以通過 custom_objects 參數將它們傳遞給加載機制。

from keras.models import load_model

# 假設模型包含一個 AttentionLayer 類的實例
model = load_model('my_model.h5', custom_objects={'AttentionLayer': AttentionLayer})

或 使用 自定義對象作用域

from keras.utils import CustomObjectScope

with CustomObjectScope({'AttentionLayer': AttentionLayer}):
    model = load_model('my_model.h5')

自定義對象的處理與 load_model, model_from_json, model_from_yaml 的工作方式相同

from keras.models import model_from_json

model = model_from_json(json_string, custom_objects={'AttentionLayer': AttentionLayer})

(5)獲取中間層的輸出

方法一:創建一個新的 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 函數,也可構建 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 np

x_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 LSTM

timesteps = 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只返回其輸出序列的最後一步結果,從而其時域維度降低(即將輸入序列轉換爲單個向量)
在這裏插入圖片描述

from keras.models import Sequential
from keras.layers import LSTM, Dense
import numpy as np

data_dim = 16
timesteps = 8
num_classes = 10

# 生成虛擬訓練數據
x_train = np.random.random((1000, timesteps, data_dim))
y_train = np.random.random((1000, num_classes))
# 生成虛擬驗證數據
x_val = np.random.random((100, timesteps, data_dim))
y_val = np.random.random((100, num_classes))


#########  模型構建
## input data shape: (batch_size, timesteps, data_dim)
model = Sequential()
# 返回維度爲 32 的向量序列
model.add(LSTM(32, return_sequences=True,
               input_shape=(timesteps, data_dim)))
model.add(LSTM(32, return_sequences=True))
model.add(LSTM(32))
model.add(Dense(10, activation='softmax'))

model.compile(loss='categorical_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])

model.fit(x_train, y_train, batch_size=64, epochs=5, validation_data=(x_val, y_val))

(5)示例5:“stateful” 渲染的的棧式 LSTM 模型

有狀態 (stateful) 的循環神經網絡模型中:在一個 batch 的樣本處理完成後,其內部狀態(記憶)會被記錄並作爲下一個 batch 的樣本的初始狀態。這允許處理更長的序列,同時保持計算複雜度的可控性。

from keras.models import Sequential
from keras.layers import LSTM, Dense
import numpy as np

data_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 模型一樣,都可以被訓練;
from keras.layers import Input, Dense
from keras.models import Model

## 數據生成
import numpy as np

data = np.random.random((1000, 784))
labels = np.random.randint(10, size=(1000, 10))


## 這部分返回一個張量
inputs = Input(shape=(784, ))

## 層的實例是可調用的,它以張量爲參數,並且返回一個張量
x = Dense(64, activation='relu')(inputs)
x = Dense(64, activation='relu')(x)
pred = Dense(10, activation='softmax')(x)

# 這部分創建了一個包含輸入層和三個全連接層的模型
model = Model(inputs=inputs, outputs=pred)
model.compile(optimizer='rmsprop',
              loss='categorical_crossentropy',
              metrics=['accuracy'])
model.fit(data, labels, epochs=10)

所有的模型都可調用,就像網絡層一樣

  • 便於重用訓練好的模型:可以將任何模型看作是一個層,然後通過傳遞一個張量來調用它。
  • 注意:在調用模型時,您不僅重用模型的結構,還重用了它的權重。
  • 示例:圖像分類 =》視頻分類
from keras.layers import TimeDistributed

## 模型定義
x = Input(shape=(784,))
# 這是可行的,並且返回上面定義的 10-way softmax。
y = model(x)

# 輸入數據定義:輸入張量是 20 個時間步的序列,每一個時間爲一個 784 維的向量
input_sequences = Input(shape=(20, 784))

# 這部分將我們之前定義的模型應用於輸入序列中的每個時間步。
# 之前定義的模型的輸出是一個 10-way softmax,
# 因而下面的層的輸出將是維度爲 10 的 20 個向量的序列。
processed_sequeneces = TimeDistributed(model)(input_sequences)

2、多輸入多輸出模型

函數式 API 使 處理大量交織的數據流 變得容易。

示例預測 Twitter 上的一條新聞標題有多少轉發和點贊數

  • 模型的主要輸入:新聞標題本身,即一系列詞語,其他的輔助輸入:例如新聞標題的發佈的時間等。
  • 該模型也將通過兩個損失函數進行監督學習。較早地在模型中使用主損失函數,是深度學習模型的一個良好正則方法。

模型結構如下:
在這裏插入圖片描述
實現

  • 主要輸入:新聞標題,即一個整數序列(每個整數編碼一個詞)。 這些整數在 1 到 10,000 之間(10,000 個詞的詞彙表),且序列長度爲 100 個詞。
from keras.layers import Input, Embedding, LSTM, Dense
from keras.models import Model


######  模型構建
# 標題輸入:接收一個含有 100 個整數的序列,每個整數在 1 到 10000 之間。
# 注意我們可以通過傳遞一個 "name" 參數來命名任何層。
main_input = Input(shape=(100,), dtype='int32', name='main_input')

# Embedding 層將輸入序列編碼爲一個稠密向量的序列,每個向量維度爲 512。
x = Embedding(output_dim=512, input_dim=10000, input_length=100)(main_input)

# LSTM 層把向量序列轉換成單個向量,
# 它包含整個序列的上下文信息
lstm_out = LSTM(32)(x)

# 輔助損失: 使得即使在模型主損失很高的情況下,LSTM 層和 Embedding 層都能被平穩地訓練。
auxiliary_output = Dense(1, activation='sigmoid', name='aux_output')(lstm_out)

# 將輔助輸入數據與 LSTM 層的輸出連接起來,輸入到模型中 
auxiliary_input = Input(shape=(5,), name='aux_input')
x = keras.layers.concatenate([lstm_out, auxiliary_input])

# 堆疊多個全連接網絡層
x = Dense(64, activation='relu')(x)
x = Dense(64, activation='relu')(x)
x = Dense(64, activation='relu')(x)

# 最後添加主要的邏輯迴歸層
main_output = Dense(1, activation='sigmoid', name='main_output')(x)

# 然後定義一個具有兩個輸入和兩個輸出的模型
model = Model(inputs=[main_input, auxiliary_input], outputs=[main_output, auxiliary_output])



#####  編譯與訓練
# 方式1:編譯模型,並給輔助損失分配一個 0.2 的權重。
# 如果要爲不同的輸出指定不同的 loss_weights 或 loss,可以使用列表或字典。 
# 在這裏,我們給 loss 參數傳遞單個損失函數,這個損失將用於所有的輸出。
model.compile(optimizer='rmsprop', loss='binary_crossentropy',
              loss_weights=[1., 0.2])
model.fit([headline_data, addition_data], [labels, labels], 
          epochs=50, batch_size=32)

# 方式2:通過 name 參數編譯和訓練模型
model.compile(optimizer='rmsprop',
              loss={'main_output':'binary_crossentropy', 'aux_output':'binary_crossentropy'},
              loss_weights={'main_output':1., 'aux_output':0.2})
model.fit({'main_input': headline_data, 'aux_input':additional_data},
          {'main_output': labels, 'aux_output':labels},
          epochs=50, batch_size=32)

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:獲取其輸入形狀;
## 該層有單個輸入
a = Input(shape=(280, 256))

lstm = LSTM(32)
encoded_a = lstm(a)

assert lstm.output == encoded_a

注意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)		# 輸入2

assert 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, Input

input_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, Input

x = 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 TimeDistributed

video_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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章