[Python深度學習](六)高級的深度學習最佳實踐

本文爲《Python深度學習》的學習筆記。

第7章 高級的深度學習最佳實踐

Keras函數式API

使用Keras回調函數

使用Tensorboard可視化工具

開發最先進模型的重要實踐

7.1 不用Sequential模型的解決方案:Keras函數式API

之前6章所有神經網絡都是用Sequential模型實現的。Sequential模型假設,網絡只有一個輸入和輸出,且網絡是線性堆疊的。

有些任務需要多模態輸入,可以合併這些不同輸入源的數據。

元數據
Dense模塊
文本描述
RNN模塊
圖片
卷積神經網絡模塊
合併模塊
價格預測

同樣,有些任務需要預測輸入數據的多個目標屬性。

小說文本
文本處理模塊
類別分類器
日期迴歸器
類別
日期

以及ResNet。

7.1.1 函數式API簡介

from keras import Input, layers

input_tensor = Input(shape = (322,))

dense = layers.Dense(32, activation = 'relu')

output_tensor = dense(input_tensor)

這裏可以直接操作張量,把層Dense當做函數使用,接受張量並返回張量。

from keras.models import Sequential, Model
from keras import layers
from keras import Input

seq_model = Sequential()
seq_model.add(layers.Dense(32, activation = 'relu', input_shape = (64,)))
seq_model.add(layers.Dense(32, activation = 'relu'))
seq_model.add(layers.Dense(10, activation = 'softmax'))

input_tensor = Input(shape=(64,))
x = layers.Dense(32, activation = 'relu')(input_tensor)
x = layers.Dense(32, activation = 'relu')(x)
output_tensor = layers.Dense(10, activation = 'softmax')(x)

model = Model(input_tensor, output_tensor)

model.summary()

在這裏插入圖片描述
這裏我們將Model對象實例化只用了一個輸入張量和一個輸出張量。

7.1.2 多輸入模型

API可用於構建多個輸入的模型。

Dense
回答
Concatenate
LSTM
LSTM
Embedding
Embedding
文本
問題
  • 下面示例如何用函數式API構建這樣的模型。
# 7-1 用函數式API實現雙輸入問答模型
from keras.models import Model
from keras import layers
from keras import Input

text_vocabulary_size = 10000
question_vocabulary_size = 10000
answer_vocabulary_size = 500

text_input = Input(shape=(None,), dtype='int32', name='text')

embedded_text = layers.Embedding(text_vocabulary_size, 64)(text_input) # 將輸入嵌入長度爲64的向量
encoded_text = layers.LSTM(32)(embedded_text)

question_input = Input(shape=(None,), dtype='int32', name='question') # 對問題進行相同的處理

embedded_question = layers.Embedding(text_vocabulary_size, 32)(question_input) 
encoded_question = layers.LSTM(15)(embedded_question)

concatenated = layers.concatenate([encoded_text, encoded_question], axis = -1) # 將編碼後的問題和文本鏈接起來

answer = layers.Dense(answer_vocabulary_size, activation='softmax')(concatenated) # 在上面添加softmax分類器

model = Model([text_input, question_input], answer)
model.compile(optimizer='rmsprop', loss = 'categorical_crossentropy', metrics=['acc'])
  • 可以向模型屬於一個numpy數組組成的列表,或者輸入一個名稱映射爲numpy的數組的字典。
# 7-2 將數據輸入到多輸入模型中
import numpy as np
from keras.utils import to_categorical

num_samples = 1000
max_length = 100

text = np.random.randint(1, text_vocabulary_size, size =(num_samples, max_length))

question = np.random.randint(1, question_vocabulary_size, size=(num_samples, max_length))
answers = np.random.randint(answer_vocabulary_size, size=(num_samples))
answers = to_categorical(answers, answer_vocabulary_size)

model.fit([text, question], answers, epochs=10, batch_size=128)

model.fit({'text': text, 'question':question}, answers, epochs=10, batch_size=128)

在這裏插入圖片描述

7.1.3 多輸出模型

  • 使用函數式API構建多個輸出的模型。
# 7-3 用函數式API實現一個三輸出模型
from keras import layers
from keras import Input
from keras.models import Model

vocabulary_size = 50000
num_income_groups = 10

posts_input = Input(shape=(None,), dtype='int32', name='posts')
embedded_posts = layers.Embedding(256, vocabulary_size)(posts_input)

x = layers.Conv1D(128, 5, activation='relu')(embedded_posts)
x = layers.MaxPooling1D(5)(x)
x = layers.Conv1D(256, 5, activation='relu')(x)
x = layers.Conv1D(256, 5, activation='relu')(x)
x = layers.MaxPooling1D(5)(x)
x = layers.Conv1D(256, 5, activation='relu')(x)
x = layers.Conv1D(256, 5, activation='relu')(x)
x = layers.GlobalMaxPooling1D()(x)
x = layers.Dense(128, activation='relu')(x)

age_prediction = layers.Dense(1, name='age')(x)
income_prediction = layers.Dense(num_income_groups, activation='softmax',name='income')(x)
gender_prediction = layers.Dense(1, activation='sigmoid', name='gender')(x)

mdoel = Model(posts_input, [age_prediction, income_prediction, gender_prediction])
社交媒體發帖
一維卷積神經網絡
Dense
Dense
Dense
性別
收入
年齡
  • 訓練這種模型需要對網絡各個頭制定不同的損失函數。
# 7-4 多輸出模型的編譯選項:多重損失
'''
model.compile(optimizer='rmsprop', 
              loss=['mse', 'categoracal_crossentropy', 'binary_crossentropy'])
'''
model.compile(optimizer='rmsprop', 
              loss={'age':'mse', 
                    'income': 'categorical_crossentropy', 
                    'gender': 'binary_crossentropy'})
  • 爲了平衡不同損失的貢獻,讓交叉熵的損失權重取10,而MSE損失的權重取0.5。
# 7-5 多輸出模型的編譯選項:損失加權
model.compile(optimizer='rmsprop', 
             loss=['mse','categorical_crossentropy','binary_crossentropy'],
             loss_weights = [0.25, 1., 10.])

# 與上面方法等效,且只有輸出層具有名稱時才採用這種寫法
model.compile(optimizer='rmsprop', 
              loss={'age':'mse', 
                    'income': 'categorical_crossentropy', 
                    'gender': 'binary_crossentropy'}
              loss_weights = {'age': 0.25, 
                    'income': 1., 
                    'gender': 10.})
# 7-6 將數據輸入到多輸出模型中
model.fit(posts, [age_targets, income_targets, gender_targets], epochs=10, batch_size=64)

mode.fit(posts, {'age': age_targets,
                'income': income_targets,
                'gender': gender_targets},
        epochs=10, batch_size=64)

7.1.4 層組成的有向無環圖

利用Keras中的神經網絡可以是層組成的任意有向無環圖。兩個著名的模型是Inception模塊和殘差連接。

  1. Inception模塊
    Google:模塊的堆疊,並行分支。InceptionV3:
輸入
Conv2D 1x1, strade=2
Conv2D 1x1
Conv2D 3x3, strade=2
AvgPool2D 3x3, stride=2
Conv2D 3x3
Conv2D 1x1
Conv2D 3x3
Conv2D 3x3, stride=2
連接
輸出
  • 1x1卷積的作用(點卷積):有助於區分開通道特徵學習和空間特徵學習。
  1. 殘差連接
    ResNet詳細解讀
    你必須要知道CNN模型:ResNet

在這裏插入圖片描述

7.1.5 共享層權重

函數APi能夠多次重複使用一個層的實例。每次調用可以重複使用相同的權重。

# 共享權重
from keras import layers
from keras import Input
from keras.models import Model

lstm = layers.LSTM(32)


# 構建模型的左右分支
left_input = Input(shape=(None, 128))
left_output = lstm(left_input)

right_input = Input(shape=(None, 128))
right_output = lstm(right_input)

# 在上面構建一個分類器
merged = layers.concatenate([left_output, right_output], axis = -1)
predictions = layers.Dense(1, activation = 'sigmoid')(merged)

# 模型實例化
model = Model([left_input, right_input], predictions)
model.fit([left_data, right_data], targets)

7.1.6 將模型作爲層

函數式APi中,可以像使用層一樣使用模型。
類似於y=model(x),如果模型具有多個輸入張量和多個輸出張量,那麼意味着可以在一個輸入張量上調用模型,並得到一個輸出張量。y1, y2 = model([x1, x2])

from keras import layers
from keras import applications
from keras import Input

xception_base = applications.Xception(weights=None, include_top = False)

left_input = Input(shape=(250, 250, 3)) 
right_input =  Input(shape=(250, 250, 3))

left_features = xception_base(left_input)
right_input = xception_base(right_input)

merged_features = layers.concatenate([left_features, right_input], axis = -1)

7.2 使用Keras回調函數和TensorBoard來檢查並監控深度學習模型

本節介紹訓練過程中如何更好訪問並控制模型內部過程的方法。

7.2.1 訓練過程中將回調函數作用於模型

  • 模型檢查點
  • 提前終止
  • 在訓練過程中動態調節某些函數值
  • 在訓練過程中記錄訓練指標和驗證指標
  1. ModelCheckpoint與EarlyStoppping回調函數
    如果監控的目標輪數不再改善,可以EarlyStopping來回調函數。
import keras

callback_list =[
    keras.callbacks.EarlyStopping(
        monitor = 'acc',
        patience = 1,
    ),
    keras.callbacks.ModelCheckpoint(
        filepath = 'my_model.h5',
        monitor = 'val_loss',
        save_best_only = True,
    )                    
]

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

'''
model.fit(x, y, epochs=10,
         batch_size = 32,
         callbacks = callbacks_list,
         validation_data = (x_val, y_val))
'''

這裏通過callback這個參數將earlystoppping和modelcheckpointliangge屬性加入模型。

  1. ReduceLROnPlateau回調函數
    如果驗證損失不再改善,可以使用這個回調函數降低學習率。
callback_list =[
    keras.callbacks.ReduceLROnPlateau(
        monitor = 'val_loss',
        factor = 0.1,
        patience = 10,
    )
]
  1. 編寫自己的回調函數
    創建keras.callbacks.Callback類的子類,實現下面的方法:
    on_epoch_begin 在每輪開始時被調用
    on_epoch_end

on_batch_begin 在處理每個批量之前被調用
on_batch_end

on_train_begin 在訓練開始時被調用
on_train_end

import keras
import numpy as np

class ActivationLogger(keras.callbacks.Callback):
    def set_model(self, model):
        self.model = model
        layer_outputs = [layer.output for layer in model.layers]
        self.activations_model = keras.models.Model(model.input, layer_outputs)
    
    def on_epoch_end(self, epoch, logs = None):
        if self.validation_data is None:
            raise RuntimeError('Requires validation_data.')
        validation_sample = self.validation_data[0][0:1]
        activations = self.activations_model.predict(validation_sample)
        f = open('actifvations_at_epoch_' + str(epoch) + '.npz', 'w')
        np.savez(f, activations)
        f.close()

7.2.2 TensorBoard簡介:TensorFlow的可視化框架

想要做好研究或者開發出好的模型,需要知道模型內部發生了什麼。

# 7-7 使用了TensorBoard的文本分類模型
import keras 
from keras import layers
from keras.datasets import imdb
from keras.preprocessing import sequence

max_features = 2000
max_len = 500

(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words = max_features)
x_train = sequence.pad_sequences(x_train, maxlen = max_len)
x_test = sequence.pad_sequences(x_test, maxlen = max_len)

model = keras.models.Sequential()
model.add(layers.Embedding(max_features, 128, input_length = max_len, name = 'embed'))
model.add(layers.Conv1D(32, 7, activation = 'relu'))
model.add(layers.MaxPooling1D(5))
model.add(layers.Conv1D(32, 7, activation = 'relu'))
model.add(layers.GlobalMaxPooling1D())
model.add(layers.Dense(1))
model.summary()
model.compile(optimizer = 'rmsprop',
             loss = 'binary_crossentropy',
             metrics = ['acc'])

在開始使用TensorBoard之前創建一個目錄,保存生成的日誌文件。在cmd窗口輸入。

# 7-8 爲TensorBoard日誌文件創建一個目標
$ mkdir my_log_dir
# 7-9 使用一個TensorBoard回調函數來訓練模型
callbacks = [
    keras.callbacks.TensorBoard(
        log_dir = 'my_log_dir',
        histogram_freq = 1,
        embeddings_freq = 1,
    )
]

history = model.fit(x_train, y_train, epochs = 20,
                   batch_size = 128,
                   validation_split = 0.2,
                   callbacks = callbacks)

下面使用命令啓動TensorBoard服務器。

S tensorboard --logdir = my_log_dir4

7.3 讓模型性能發揮到極致

7.3.1 高級架構模式

  1. 批標準化BatchNorm:訓練過程中適應性將數據標準化。
  2. 深度可分離卷積:有一個層可以替代Conv2D,讓模型跟輕量。

7.3.2 超參數優化

hyperparameter

7.3.3 模型集成

將一組分類器的預測結果彙集在一起。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章