Keras深度學(xué)習(xí)實踐8—Keras高階實踐

內(nèi)容參考以及代碼整理自“深度學(xué)習(xí)四大名“著之一《Python深度學(xué)習(xí)》
查看完整代碼,請看: https://github.com/ubwshook/MachineLearning

一、Keras函數(shù)式API

我們之前討論的深度學(xué)習(xí)模型都是用Sequential模型實現(xiàn)的息罗。Sequential模型假設(shè),網(wǎng)絡(luò)只有一個輸入和一個輸出鳞绕,而且網(wǎng)絡(luò)是層的線性堆疊京办。但有些網(wǎng)絡(luò)需要多個獨立的輸入矛缨,有些網(wǎng)絡(luò)則需要多個輸出斯辰,而有些網(wǎng)絡(luò)在層與層之間具有內(nèi)部分支舶担,這使得網(wǎng)絡(luò)看起來像是層構(gòu)成的,而不是線性堆疊彬呻。

使用函數(shù)式API衣陶,你可以直接操作向量,也可以把層當(dāng)作函數(shù)來使用闸氮,接收張量并返回張量剪况,因此叫函數(shù)式API。

from keras import Input, layers

input_tensor = Input(shape=(32,))   # 一個張量
dense = layers.Dense(32, activation='relu')  # 一個層是一個函數(shù)
output_tensor = dense(input_tensor)  #  可以在一個張量上調(diào)用一個層蒲跨,返回時一個張量

1.函數(shù)式API簡介

一個簡單的示例译断,展示簡單Sequential模型以及對應(yīng)函數(shù)式API實現(xiàn)

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

# Sequential模型方式構(gòu)建模型
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'))

# 函數(shù)式API實現(xiàn)模型
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()  # 查看模型

函數(shù)式API的編譯、訓(xùn)練或評估财骨,API與Sequential相同。

model.compile(optimizer='rmsprop', loss='categorical_crossentropy')
import numpy as np
x_train = np.random.random((1000, 64))
y_train = np.random.random((1000, 10))
model.fit(x_train, y_train, epochs=10, batch_size=128)
score = model.evaluate(x_train, y_train)

2.多輸入模型

一個簡單的多輸入模型例示—— 一個問答模型:一個自然語言描述的問題和一個文本片段(比如新聞文章)藏姐,后者提供用于回答問題的信息隆箩。然后模型要生成一個回答,最簡單的情況下羔杨,這個回答只包含一個詞捌臊,可以通過摸個預(yù)定義的詞表做softmax得到。

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

# 文本輸入時一個長度可變的整數(shù)序列兜材±砼欤可以對輸入進(jìn)行命名。
text_input = Input(shape=(None,), dtype='int32', name='text')
# 輸入嵌入長度為64的向量
embedded_text = layers.Embedding(64, text_vocabulary_size)(text_input)
# 利用LSTM將向量編碼為單個向量
encoded_text = layers.LSTM(32)(embedded_text)

# 問題文本做相同的處理
question_input = Input(shape=(None,), dtype='int32', name='question')
embedded_question = layers.Embedding(32, question_vocabulary_size)(question_input)
encoded_question = layers.LSTM(16)(embedded_question)

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

# 最后加上softmax分類器
answer = layers.Dense(answer_vocabulary_size, activation='softmax')(concatenated)
model = Model([text_input, question_input], answer)
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['acc'])

我們?nèi)绾斡?xùn)練這個雙輸入的API模型曙寡?有兩個可用的API:我們可以向模型輸入一個由Numpy數(shù)組組成的列表糠爬,或者也可以輸入一個名稱映射為Numpy數(shù)據(jù)的字典。當(dāng)然举庶,只有輸入具有名稱時才能使用后一種方法执隧。

import numpy as np

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(0, 1, size=(num_samples, answer_vocabulary_size))

# 使用輸入組合的列表來擬合
model.fit([text, question], answers, epochs=10, batch_size=128)
# 使用輸入組成的字典來擬合,這種方式只能應(yīng)用于對輸入命名的情況
model.fit({'text': text, 'question': question}, answers, epochs=10, batch_size=128)

3.多輸出模型

多輸出模型,一個簡單的例子就是一個網(wǎng)絡(luò)試圖預(yù)測數(shù)據(jù)的不同性質(zhì)镀琉,比如一個網(wǎng)絡(luò)峦嗤,輸入摸個匿名人士的一系列社交媒體發(fā)帖,然后嘗試預(yù)測人的屬性屋摔,比如年齡烁设、性別和收入水平。

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)

# 分別有3個輸出層钓试,都有自己名字
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)
model = Model(posts_input,
[age_prediction, income_prediction, gender_prediction])

這種訓(xùn)練模型需要能夠?qū)W(wǎng)絡(luò)的各個頭指定不同的損失函數(shù)装黑,例如,年齡預(yù)測是標(biāo)量回歸任務(wù)亚侠,而性別預(yù)測是二分類任務(wù)曹体,二者需要的不同訓(xùn)練過程。但是梯度下降要求講一個標(biāo)量最小化硝烂,所以為了能夠訓(xùn)練模型箕别,我們必須將這些損失合并為單個標(biāo)量。合并不同損失最簡單的方法就是對所有損失求和滞谢。在Keras中串稀,你可以在編譯時使用損失組成的列表或字典為不同輸出指定損失函數(shù),然后將得到損失值相加得到一個全局損失狮杨,并在訓(xùn)練中將這個損失最小化母截。

model.compile(optimizer='rmsprop', loss=['mse', 'categorical_crossentropy', 'binary_crossentropy'])
model.compile(optimizer='rmsprop', loss={'age': 'mse', 'income': 'categorical_crossentropy','gender': 'binary_crossentropy'})

為了平衡不同損失的貢獻(xiàn),我們可以分配給各個損失不同的權(quán)重橄教。

model.compile(optimizer='rmsprop', loss=['mse', 'categorical_crossentropy', 'binary_crossentropy'], loss_weights=[0.25, 1., 10.])

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

4.有向無環(huán)圖模型

函數(shù)式API用于實現(xiàn)多輸入和多輸出模型清寇,可以實現(xiàn)具有復(fù)雜的內(nèi)部拓?fù)浣Y(jié)構(gòu)的網(wǎng)絡(luò)。一些常見的神經(jīng)網(wǎng)絡(luò)組件都是以圖的形式實現(xiàn)的护蝶。

Inception模塊

Inception是一種流行的卷積神經(jīng)網(wǎng)絡(luò)的構(gòu)架類型华烟。它是模塊的堆疊,這些模塊本身看起來像是小型獨立網(wǎng)絡(luò)持灰,被分為多個并行分支盔夜。Inception模塊最基本的形式包括3~4個分支,首先是1 * 1 卷積堤魁,然后是一個 3 * 3 卷積, 最后將所得到的特征連接在一起喂链。這種設(shè)置有助于網(wǎng)絡(luò)分別學(xué)習(xí)空間特征和逐通道的特征,這比聯(lián)合學(xué)習(xí)這兩種特征更加有效妥泉。Inception模塊可能具有更復(fù)雜的形式椭微,通常會包含池化運算、不同尺寸的空間卷積和不同空間卷積的分支盲链。

我們可以使用函數(shù)式API來實現(xiàn)以上結(jié)構(gòu)赏表。

from keras import layers

branch_a = layers.Conv2D(128, 1, activation='relu', strides=2)(x)

branch_b = layers.Conv2D(128, 1, activation='relu')(x)
branch_b = layers.Conv2D(128, 3, activation='relu', strides=2)(branch_b)

branch_c = layers.AveragePooling2D(3, strides=2)(x)
branch_c = layers.Conv2D(128, 3, activation='relu')(branch_c)

branch_d = layers.Conv2D(128, 1, activation='relu')(x)
branch_d = layers.Conv2D(128, 3, activation='relu')(branch_d)
branch_d = layers.Conv2D(128, 3, activation='relu', strides=2)(branch_d)

output = layers.concatenate([branch_a, branch_b, branch_c, branch_d], axis=-1)

殘差連接

殘差連接是一種常見的類圖網(wǎng)絡(luò)組建检诗。殘差橋接解決了困擾所有大規(guī)模深度學(xué)習(xí)的兩個共性問題:梯度消失表示瓶頸。通常來說瓢剿,向任何多于10層的模型中添加殘差連接逢慌,都可能有所幫助。

深度學(xué)習(xí)的表示瓶頸: 在Sequential模型中间狂,每個連續(xù)的表示都構(gòu)建于前一層之上攻泼,這意味著它只能訪問前一層激活中包含的信息。如果抹一層太小鉴象,那么模型將會受限于該層激活中能夠塞入多少信息忙菠。

梯度消失: 反向傳播是用于訓(xùn)練深度神經(jīng)網(wǎng)絡(luò)的主要算法,其中工作原理是將來自輸出損失的反饋向下傳播到更底部的底層纺弊。如果這個反饋信信號需要經(jīng)過很多層牛欢,那么這個信號可能變的非常微弱,甚至完全丟失淆游,導(dǎo)致網(wǎng)絡(luò)無法訓(xùn)練傍睹。

殘差連接是讓前面磨蹭的輸出作為后面某層的輸入,從而在序列網(wǎng)絡(luò)中有效地創(chuàng)造一條捷徑犹菱。前面層的輸出沒有與后面層的激活連接在一起拾稳,而是與后面層的激活相加。如果他們的形狀不同腊脱,我們可以用一個線性變換將前面的激活改變成目標(biāo)形狀访得。

恒等殘差
x = ...
y = layers.Conv2D(128, 3, activation='relu', padding='same')(x)
y = layers.Conv2D(128, 3, activation='relu', padding='same')(y)
y = layers.Conv2D(128, 3, activation='relu', padding='same')(y)
y = layers.add([y, x])
線性殘差連接
x = ...
y = layers.Conv2D(128, 3, activation='relu', padding='same')(x)
y = layers.Conv2D(128, 3, activation='relu', padding='same')(y)
y = layers.MaxPooling2D(2, strides=2)(y)
residual = layers.Conv2D(128, 1, strides=2, padding='same')(x)
y = layers.add([y, residual])

5.共享層權(quán)重

函數(shù)式API還有一個重要的特性,就是能夠多次重復(fù)使用一個層實例陕凹。如果你對一個層實例調(diào)用兩次悍抑,而不是每次調(diào)用都實例化一個鋅層,那么每次調(diào)用可以重復(fù)使用相同的權(quán)重杜耙。這樣你可以構(gòu)建具有共享分支的模型搜骡,即每個分支都共享相同的知識并執(zhí)行相同的運算。也就是說泥技,這些分支共享相同的表示浆兰,并同時對不同的輸入集合學(xué)習(xí)這些表示磕仅。

舉例珊豹,一個模型想要評估兩個句子之間的語義相似度。這個模型有兩個輸入榕订,并輸出一個范圍在0~1的分?jǐn)?shù)店茶,0表示兩個句子毫不相關(guān),1表示兩個句子完全相同或只是換了一種表述劫恒。這種模型在許多應(yīng)用中都很有用贩幻,其中包含在對貨系統(tǒng)中刪除重復(fù)語言查詢轿腺。

在這種場景下,兩個輸入時可以換換的丛楚,因為語義相似度是一種對稱關(guān)系族壳。因此學(xué)習(xí)單獨模型分別來處理兩個輸入時沒有道理的。需要使用一個LSTM層來處理兩個句子趣些。這個LSTM層表示同時基于兩個輸入來學(xué)習(xí)仿荆。我們將其稱為連體LSTM或共享LSTM模型。

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

# 將一個LSTM實例化一次
lstm = layers.LSTM(32)

# 輸入時長度128的向量組成的邊長序列
left_input = Input(shape=(None, 128))
left_output = lstm(left_input)

# 構(gòu)建右側(cè)分支拢操,也是用lstm令境,共享該層
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)

# 訓(xùn)練模型
model = Model([left_input, right_input], predictions)
model.fit([left_data, right_data], targets)

6.將模型作為層

函數(shù)式API可以像層一樣使用模型。

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

# 使用keras中的xception模型
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

二玲昧、Keras回調(diào)函數(shù)

有時候訓(xùn)練足夠多的輪次栖茉,這時候模型已經(jīng)開始過擬合,想要重新啟動一次訓(xùn)練孵延,并記錄過擬合開始的輪數(shù)吕漂,這時候用就可以使用回調(diào)函數(shù)〕居Γ回調(diào)函數(shù)是調(diào)用fit時惶凝,傳入模型的一個對象,他在訓(xùn)練過程中的不同時間點都會被模型調(diào)用犬钢。它可以訪問關(guān)于模型狀態(tài)與性能的所有數(shù)據(jù),可以采取行動: 中斷訓(xùn)練玷犹、保存模型歹颓、加載一組不同的權(quán)重會改變模型的狀態(tài)坯屿∥】福回調(diào)函數(shù)用法示例如下:

  • 模型檢查點:在訓(xùn)練過程中的不同時間點保存模型的當(dāng)前權(quán)重
  • 提前終止:如果驗證損失不再改善领跛,則中斷訓(xùn)練
  • 在訓(xùn)練過程中調(diào)節(jié)默寫參數(shù)值: 比如優(yōu)化器的學(xué)習(xí)率
  • 在訓(xùn)練過程中記錄訓(xùn)練和驗證指標(biāo)喊括,或?qū)⒛P蛯W(xué)到的表示可視化:你熟悉的Keras進(jìn)度條就是一個回調(diào)函數(shù)蒲肋。

下面介紹幾個回調(diào)函數(shù)。

1.ModelCheckpoint與EarlyStopping回調(diào)函數(shù)。

EarlyStoping可以中斷訓(xùn)練,可以在訓(xùn)練出現(xiàn)擬合的時候中斷訓(xùn)練,從而避免用跟梢的輪次重新訓(xùn)練模型。這個回調(diào)函數(shù)通常與ModelCheckpoint結(jié)合使用联贩,后者可以在訓(xùn)練過程中持續(xù)不斷的保存模型。

import keras
callbacks_list = [keras.callbacks.EarlyStopping(monitor='acc',  # 監(jiān)控模型的指標(biāo)吗浩,這里是精度
                                                patience=1,),  # 如果精度多余一輪的時間不改善,中斷訓(xùn)練
                  keras.callbacks.ModelCheckpoint(filepath='my_model.h5',  # 保存模型文件的名字
                                                  monitor='val_loss',  # 如果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))

2.ReduceLROnOlateau回調(diào)函數(shù)

如果驗證損失不再改善浴滴,你可以使用這個回調(diào)函數(shù)來降低學(xué)習(xí)率拓萌。在訓(xùn)練過程中如果出現(xiàn)了平臺損失岁钓,那么增大或減小學(xué)習(xí)率都是跳出局部最小值的有效策略升略。

callbacks_list = [keras.callbacks.ReduceLROnPlateau(monitor='val_loss', # 監(jiān)控模型的驗證損失
                                                    factor=0.1,  # 觸發(fā)時將學(xué)習(xí)率除以10
                                                    patience=10,)]  # 如果驗證損失在10輪內(nèi)都米有改善就觸發(fā)回調(diào)函數(shù)
model.fit(x, y, epochs=10, batch_size=32, callbacks=callbacks_list, validation_data=(x_val, y_val))

3.定制自己的回調(diào)函數(shù)

回調(diào)函數(shù)的實現(xiàn)方式是穿件keras.callbacks.Callback類的子類微王。然后你可以實現(xiàn)下面這些方法,他們分別在訓(xùn)練過程中的不同時間點被調(diào)用品嚣。

  • on_epoch_begin: 每輪開始
  • on_epoch_end: 每輪結(jié)束
  • on_batch_begin: 每個批量處理開始
  • on_batch_end: 在處理每個批量之后被調(diào)用
  • on_train_begin: 在訓(xùn)練開始時被調(diào)用
  • on_train_end: 在倫蓮結(jié)束時被調(diào)用炕倘。

回調(diào)函數(shù)還可以訪問下列屬性。

  • self.model:調(diào)用回調(diào)函數(shù)的模型實例
  • self.validation_data: 傳入fit作為驗證數(shù)據(jù)的值罩旋。

下面是一個自定義回調(diào)函數(shù),他可以在每輪結(jié)束后將模型每層的激活保存到硬盤里眶诈。這個激活是對驗證集的第一個樣本計算得到的涨醋。

import keras
import numpy as np

class ActivationLogger(keras.callbacks.Callback):
    # 告訴回調(diào)函數(shù)是哪個模型在調(diào)用它
    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]  # 獲取驗證數(shù)據(jù)的第一個輸入樣本
        activations = self.activations_model.predict(validation_sample)  # 將數(shù)據(jù)保存到硬盤
        f = open('activations_at_epoch_' + str(epoch) + '.npz', 'w')
        np.savez(f, activations)
        f.close()

三、TensorFlow可視化框架

TensorBoard的主要用途是逝撬,在訓(xùn)練過程中幫助你可以可視化的方法監(jiān)控模型內(nèi)部發(fā)生了什么浴骂。主要功能:

  • 在訓(xùn)練過程中可以可視化的方式監(jiān)控指標(biāo)
  • 將模型架構(gòu)可視化
  • 將激活和梯度的直方圖可視化
  • 以三維的形式研究嵌入

這里我們對IMDB情感分析人物訓(xùn)練一個一維卷積神經(jīng)網(wǎng)絡(luò)。采用了詞嵌入宪潮,我們可以可視化的觀察詞嵌入的情況

import keras
from keras import layers
from keras.preprocessing import sequence
from imdb import load_local
from keras.utils import plot_model
import os
os.environ["PATH"] += os.pathsep + 'D:\\Program Files (x86)\\Graphviz2.38\\bin'


max_features = 500
max_len = 500

(x_train, y_train), (x_test, y_test) = load_local(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'])
plot_model(model, show_shapes='True', to_file='model.png')

callbacks = [keras.callbacks.TensorBoard(log_dir='my_log_dir',  # 日志寫入的位置
                                         histogram_freq=1,   # 每一輪之后記錄激活
                                         embeddings_freq=1,   # 每一輪之后記錄嵌入數(shù)據(jù)
                                         embeddings_data=x_train[:100].astype("float32"),)]
history = model.fit(x_train, y_train, epochs=20, batch_size=128, validation_split=0.2,
                    callbacks=callbacks)
TensorBoard 詞嵌入分布

使用命令啟動TensorBoard, 指定日志目錄以及服務(wù)器IP地址

tensorboard --logdir=E:\git_code\MachineLearning\keras\my_log_dir --host=127.0.0.1

在瀏覽其中打開 http://127.0.0.1:6006 來查看訓(xùn)練模型溯警。

并且可以繪制模型圖:

from keras.utils import plot_model
plot_model(model, show_shapes='True', to_file='model.png')

四、讓模型性能發(fā)揮到極致

1.高級架構(gòu)模式

批標(biāo)準(zhǔn)化

標(biāo)準(zhǔn)化:將數(shù)據(jù)減去器平均值使其中心為0狡相,然后除以器標(biāo)準(zhǔn)差使其標(biāo)準(zhǔn)差為1梯轻。

noralized_data = (data - np.mean(data, axis=...)) / np.std(data, axis=...)

之前的標(biāo)準(zhǔn)化都是在數(shù)據(jù)輸入模型前做的。但在網(wǎng)絡(luò)每一次變化之后都應(yīng)該考慮標(biāo)準(zhǔn)化尽棕。批標(biāo)準(zhǔn)化喳挑,可以及時在訓(xùn)練過程中均值和方差隨時間變化,他也可以自適應(yīng)的將數(shù)據(jù)標(biāo)準(zhǔn)化滔悉。批標(biāo)準(zhǔn)化的原理是: 訓(xùn)練過程中內(nèi)部保存已讀取每批數(shù)據(jù)均值和方差的指數(shù)移動平均值蟀悦。批標(biāo)準(zhǔn)化的主要效果是,它有助于梯度傳播氧敢,因此允許更深的網(wǎng)絡(luò)日戈。

BatchNormalization層通常在卷積層或密集連接層之后使用。

conv_model.add(layers.Conv2D(32, 3, activation='relu'))
conv_model.add(layers.BatchNormalization())
dense_model.add(layers.Dense(32, activation='relu'))
dense_model.add(layers.BatchNormalization())

深度可分離卷積

如果有一個層可以代替Conv2D孙乖,并可以讓模型更加輕量浙炼、速度更快,還可以讓任務(wù)性能提升幾個百分點唯袄,那就是深度可分離卷積層(SeparableConv2D)弯屈。它對輸入的每個通道分別執(zhí)行空間卷積,然后通過逐點積(1 * 1卷積)將輸出通道混合恋拷。這相當(dāng)于將空間特征學(xué)習(xí)和通道特征學(xué)習(xí)分開资厉,如果你假設(shè)輸入中的空間位置高度相關(guān),但不同的通道之間相對獨立蔬顾,那么這么做事很有意義的宴偿。如果有用有限的數(shù)據(jù)從頭開始訓(xùn)練小型模型湘捎,這些優(yōu)點救護(hù)變得很重要。

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

height = 64
width = 64
channels = 3
num_classes = 10

model = Sequential()
model.add(layers.SeparableConv2D(32, 3, activation='relu', input_shape=(height, width, channels,)))
model.add(layers.SeparableConv2D(64, 3, activation='relu'))
model.add(layers.MaxPooling2D(2))
model.add(layers.SeparableConv2D(64, 3, activation='relu'))
model.add(layers.SeparableConv2D(128, 3, activation='relu'))
model.add(layers.MaxPooling2D(2))
model.add(layers.SeparableConv2D(64, 3, activation='relu'))
model.add(layers.SeparableConv2D(128, 3, activation='relu'))
model.add(layers.GlobalAveragePooling2D())
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(num_classes, activation='softmax'))

model.compile(optimizer='rmsprop', loss='categorical_crossentropy')

2.超參數(shù)優(yōu)化

構(gòu)建深度學(xué)習(xí)模型時窄刘,需要制定一些參數(shù)窥妇,比如堆疊多少層,每層應(yīng)該包含多少個單元或過濾器娩践?激活應(yīng)該使用relu還是其他函數(shù)活翩?在某一層之后是否應(yīng)該使用BatchNormalization?應(yīng)該使用多的dropout比率翻伺。這些架構(gòu)層面的參數(shù)叫做超參數(shù)材泄。

參數(shù)優(yōu)化過程:

  • 選擇一組超參數(shù)(自動選擇)
  • 構(gòu)建相應(yīng)的模型。
  • 將模型在訓(xùn)練數(shù)據(jù)上擬合吨岭,并衡量器在驗證數(shù)據(jù)上的最終性能脸爱。
  • 選擇要嘗試的一下組超參數(shù)(自動選擇)
  • 重復(fù)上述過程
  • 最后,衡量模型在測試數(shù)據(jù)上的性能未妹。

3.模型集成

模型集成是指將一系列不同的模型預(yù)測結(jié)果匯集到一起簿废,從而得到更加的預(yù)測結(jié)果。每個模型都從不同的角度來做出預(yù)測络它,可能只得到了真相的一部分族檬。

要想將一組分類器的預(yù)測記過匯集咋一起,使用分類器集成化戳,最簡單方法就是取預(yù)測結(jié)果的平均值:

preds_a = model_a.predict(x_val)
preds_b = model_b.predict(x_val)
preds_c = model_c.predict(x_val)
preds_d = model_d.predict(x_val)

final_preds = 0.25 * (preds_a + preds_b + preds_c + preds_d)

或者使用加群平均单料,權(quán)重在驗證數(shù)據(jù)上學(xué)習(xí)得到:

preds_a = model_a.predict(x_val)
preds_b = model_b.predict(x_val)
preds_c = model_c.predict(x_val)
preds_d = model_d.predict(x_val)
final_preds = 0.5 * preds_a + 0.25 * preds_b + 0.1 * preds_c + 0.15 * preds_d
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市点楼,隨后出現(xiàn)的幾起案子扫尖,更是在濱河造成了極大的恐慌,老刑警劉巖掠廓,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件换怖,死亡現(xiàn)場離奇詭異,居然都是意外死亡蟀瞧,警方通過查閱死者的電腦和手機(jī)沉颂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來悦污,“玉大人铸屉,你說我怎么就攤上這事∏卸耍” “怎么了彻坛?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我昌屉,道長钙蒙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任怠益,我火速辦了婚禮,結(jié)果婚禮上瘾婿,老公的妹妹穿的比我還像新娘蜻牢。我一直安慰自己,他們只是感情好偏陪,可當(dāng)我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布抢呆。 她就那樣靜靜地躺著,像睡著了一般笛谦。 火紅的嫁衣襯著肌膚如雪抱虐。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天饥脑,我揣著相機(jī)與錄音恳邀,去河邊找鬼。 笑死灶轰,一個胖子當(dāng)著我的面吹牛谣沸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播笋颤,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼乳附,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了伴澄?” 一聲冷哼從身側(cè)響起赋除,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎非凌,沒想到半個月后举农,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡敞嗡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年并蝗,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秸妥。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡滚停,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出粥惧,到底是詐尸還是另有隱情键畴,我是刑警寧澤,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站起惕,受9級特大地震影響涡贱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜惹想,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一问词、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嘀粱,春花似錦激挪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至娃磺,卻和暖如春薄湿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背偷卧。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工豺瘤, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人听诸。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓炉奴,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蛇更。 傳聞我的和親對象是個殘疾皇子瞻赶,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內(nèi)容