首先暴露一個問題伴挚,對卷積的CNN和RNN不太熟悉靶衍,額哈哈~~~
然后,深度學(xué)習(xí)模型一般由各種模型層組合而成茎芋。
tf.keras.layers內(nèi)置了非常豐富的各種功能的模型層颅眶。例如,
layers.Dense,layers.Flatten,layers.Input,layers.DenseFeature,layers.Dropout
layers.Conv2D,layers.MaxPooling2D,layers.Conv1D
layers.Embedding,layers.GRU,layers.LSTM,layers.Bidirectional等等田弥。
如果這些內(nèi)置模型層不能夠滿足需求涛酗,我們也可以通過編寫tf.keras.Lambda匿名模型層或繼承tf.keras.layers.Layer基類構(gòu)建自定義的模型層。其中tf.keras.Lambda匿名模型層只適用于構(gòu)造沒有學(xué)習(xí)參數(shù)的模型層偷厦。
1商叹、基礎(chǔ)層
Dense:密集連接層。參數(shù)個數(shù) = 輸入層特征數(shù)× 輸出層特征數(shù)(weight)+ 輸出層特征數(shù)(bias)
Activation:激活函數(shù)層只泼。一般放在Dense層后面剖笙,等價于在Dense層中指定activation。
Dropout:隨機置零層请唱。訓(xùn)練期間以一定幾率將輸入置0弥咪,一種正則化手段。
BatchNormalization:批標(biāo)準(zhǔn)化層十绑。通過線性變換將輸入批次縮放平移到穩(wěn)定的均值和標(biāo)準(zhǔn)差聚至。可以增強模型對輸入不同分布的適應(yīng)性本橙,加快模型訓(xùn)練速度扳躬,有輕微正則化效果。一般在激活函數(shù)之前使用。
SpatialDropout2D:空間隨機置零層坦报。訓(xùn)練期間以一定幾率將整個特征圖置0库说,一種正則化手段,有利于避免特征圖之間過高的相關(guān)性片择。
Input:輸入層潜的。通常使用Functional API方式構(gòu)建模型時作為第一層。
DenseFeature:特征列接入層字管,用于接收一個特征列列表并產(chǎn)生一個密集連接層啰挪。
Flatten:壓平層,用于將多維張量壓成一維嘲叔。
Reshape:形狀重塑層亡呵,改變輸入張量的形狀。
Concatenate:拼接層硫戈,將多個張量在某個維度上拼接锰什。
Add:加法層。
Subtract: 減法層丁逝。
Maximum:取最大值層汁胆。
Minimum:取最小值層。
卷積網(wǎng)絡(luò)相關(guān)層
Conv1D:普通一維卷積霜幼,常用于文本嫩码。參數(shù)個數(shù) = 輸入通道數(shù)×卷積核尺寸(如3)×卷積核個數(shù)
Conv2D:普通二維卷積,常用于圖像罪既。參數(shù)個數(shù) = 輸入通道數(shù)×卷積核尺寸(如3乘3)×卷積核個數(shù)
Conv3D:普通三維卷積铸题,常用于視頻。參數(shù)個數(shù) = 輸入通道數(shù)×卷積核尺寸(如3乘3乘3)×卷積核個數(shù)
MaxPooling2D: 二維最大池化層琢感。也稱作下采樣層丢间。池化層無參數(shù),主要作用是降維猩谊。
AveragePooling2D: 二維平均池化層千劈。
GlobalMaxPool2D: 全局最大池化層祭刚。每個通道僅保留一個值牌捷。一般從卷積層過渡到全連接層時使用,是Flatten的替代方案涡驮。
GlobalAvgPool2D: 全局平均池化層暗甥。每個通道僅保留一個值。
循環(huán)網(wǎng)絡(luò)相關(guān)層
Embedding:嵌入層捉捅。一種比Onehot更加有效的對離散特征進(jìn)行編碼的方法撤防。一般用于將輸入中的單詞映射為稠密向量。嵌入層的參數(shù)需要學(xué)習(xí)棒口。
LSTM:長短記憶循環(huán)網(wǎng)絡(luò)層寄月。最普遍使用的循環(huán)網(wǎng)絡(luò)層辜膝。具有攜帶軌道,遺忘門漾肮,更新門厂抖,輸出門】税茫可以較為有效地緩解梯度消失問題忱辅,從而能夠適用長期依賴問題。設(shè)置return_sequences = True時可以返回各個中間步驟輸出谭溉,否則只返回最終輸出墙懂。
GRU:門控循環(huán)網(wǎng)絡(luò)層。LSTM的低配版扮念,不具有攜帶軌道损搬,參數(shù)數(shù)量少于LSTM,訓(xùn)練速度更快柜与。
SimpleRNN:簡單循環(huán)網(wǎng)絡(luò)層场躯。容易存在梯度消失,不能夠適用長期依賴問題旅挤。一般較少使用踢关。
ConvLSTM2D:卷積長短記憶循環(huán)網(wǎng)絡(luò)層。結(jié)構(gòu)上類似LSTM粘茄,但對輸入的轉(zhuǎn)換操作和對狀態(tài)的轉(zhuǎn)換操作都是卷積運算签舞。
Bidirectional:雙向循環(huán)網(wǎng)絡(luò)包裝器∑獍辏可以將LSTM儒搭,GRU等層包裝成雙向循環(huán)網(wǎng)絡(luò)。從而增強特征提取能力芙贫。
RNN:RNN基本層搂鲫。接受一個循環(huán)網(wǎng)絡(luò)單元或一個循環(huán)單元列表,通過調(diào)用tf.keras.backend.rnn函數(shù)在序列上進(jìn)行迭代從而轉(zhuǎn)換成循環(huán)網(wǎng)絡(luò)層磺平。
LSTMCell:LSTM單元魂仍。和LSTM在整個序列上迭代相比,它僅在序列上迭代一步拣挪〔磷茫可以簡單理解LSTM即RNN基本層包裹LSTMCell。
GRUCell:GRU單元菠劝。和GRU在整個序列上迭代相比赊舶,它僅在序列上迭代一步。
SimpleRNNCell:SimpleRNN單元。和SimpleRNN在整個序列上迭代相比笼平,它僅在序列上迭代一步园骆。
AbstractRNNCell:抽象RNN單元。通過對它的子類化用戶可以自定義RNN單元寓调,再通過RNN基本層的包裹實現(xiàn)用戶自定義循環(huán)網(wǎng)絡(luò)層遇伞。
Attention:Dot-product類型注意力機制層〈防危可以用于構(gòu)建注意力模型鸠珠。
AdditiveAttention:Additive類型注意力機制層∏雉铮可以用于構(gòu)建注意力模型渐排。
TimeDistributed:時間分布包裝器。包裝后可以將Dense灸蟆、Conv2D等作用到每一個時間片段上驯耻。
自定義模型層
如果自定義模型層沒有需要被訓(xùn)練的參數(shù),一般推薦使用Lamda層實現(xiàn)炒考。
如果自定義模型層有需要被訓(xùn)練的參數(shù)可缚,則可以通過對Layer基類子類化實現(xiàn)。
Lamda層由于沒有需要被訓(xùn)練的參數(shù)斋枢,只需要定義正向傳播邏輯即可帘靡,使用比Layer基類子類化更加簡單。
Lamda層的正向邏輯可以使用Python的lambda函數(shù)來表達(dá)瓤帚,也可以用def關(guān)鍵字定義函數(shù)來表達(dá)描姚。
for example:自定義模型呀~~~
Layer的子類化一般需要重新實現(xiàn)初始化方法,Build方法和Call方法戈次。下面是一個簡化的線性層的范例轩勘,類似Dense.
import tensorflow as tf
from tensorflow.keras import layers,models,regularizers
?#Layer的子類化一般需要重新實現(xiàn)初始化方法,Build方法和Call方法怯邪。下面是一個簡化的線性層的范例绊寻,類似Dense.
?15 class Linear(layers.Layer):
?16? ? def __init__(self, units=32, **kwargs):
?17? ? ? ? super(Linear, self).__init__(**kwargs)
?18? ? ? ? self.units = units
?19?
?20? ? #build方法一般定義Layer需要被訓(xùn)練的參數(shù)。? ?
?21? ? def build(self, input_shape):
?22? ? ? ? #求列數(shù)
?23? ? ? ? self.w = self.add_weight(shape=(input_shape[-1], self.units),
?24?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? initializer='random_normal',
?25?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? trainable=True)
?26? ? ? ? self.b = self.add_weight(shape=(self.units,),
?27?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? initializer='random_normal',
?28?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? trainable=True)
?29? ? ? ? super(Linear,self).build(input_shape) # 相當(dāng)于設(shè)置self.built = True
?30?
?31? ? #call方法一般定義正向傳播運算邏輯悬秉,__call__方法調(diào)用了它澄步。? ?
?32? ? def call(self, inputs):
?33? ? ? ? return tf.matmul(inputs, self.w) + self.b
?34?
?35? ? #如果要讓自定義的Layer通過Functional API 組合成模型時可以序列化,需要自定義get_config方法搂捧。
?36? ? def get_config(self):
?37? ? ? ? config =super(Linear, self).get_config()
?38? ? ? ? config.update({'units': self.units})
?39? ? ? ? return config
?40?
?41linear = Linear(units = 8)
?42print(linear.built)
?43#指定input_shape驮俗,顯式調(diào)用build方法懂缕,第0維代表樣本數(shù)量允跑,用None填充
?44linear.build(input_shape = (None,16))
?45print(linear.built)
?46?
?47linear = Linear(units = 8)
?48print(linear.built)
?49linear.build(input_shape = (None,16))
?50print(linear.compute_output_shape(input_shape = (None,16)))
?51?
?52linear = Linear(units = 16)
?53print(linear.built)
?54#如果built = False,調(diào)用__call__時會先調(diào)用build方法, 再調(diào)用call方法。
?55linear(tf.random.uniform((100,64)))
?56print(linear.built)
?57config = linear.get_config()
?58print(config)
?59?
?60?
?61tf.keras.backend.clear_session()
?62?
?63model = models.Sequential()
?64#注意該處的input_shape會被模型加工聋丝,無需使用None代表樣本數(shù)量維
?65model.add(Linear(units = 16,input_shape = (64,)))
?66print("model.input_shape: ",model.input_shape)
?67print("model.output_shape: ",model.output_shape)
?68model.summary()