【tensorflow2.0】模型層layers


深度學習模型一般由各種模型層組合而成。

tf.keras.layers內置了非常豐富的各種功能的模型層。例如,

layers.Dense,layers.Flatten,layers.Input,layers.DenseFeature,layers.Dropout

layers.Conv2D,layers.MaxPooling2D,layers.Conv1D

layers.Embedding,layers.GRU,layers.LSTM,layers.Bidirectional等等。

如果這些內置模型層不能夠滿足需求,我們也可以通過編寫tf.keras.Lambda匿名模型層或繼承tf.keras.layers.Layer基類構建自定義的模型層。

其中tf.keras.Lambda匿名模型層只適用於構造沒有學習參數的模型層。

一,內置模型層

一些常用的內置模型層簡單介紹如下。

基礎層

  • Dense:密集連接層。參數個數 = 輸入層特征數× 輸出層特征數(weight)+ 輸出層特征數(bias)

  • Activation:激活函數層。一般放在Dense層后面,等價於在Dense層中指定activation。

  • Dropout:隨機置零層。訓練期間以一定幾率將輸入置0,一種正則化手段。

  • BatchNormalization:批標准化層。通過線性變換將輸入批次縮放平移到穩定的均值和標准差。可以增強模型對輸入不同分布的適應性,加快模型訓練速度,有輕微正則化效果。一般在激活函數之前使用。

  • SpatialDropout2D:空間隨機置零層。訓練期間以一定幾率將整個特征圖置0,一種正則化手段,有利於避免特征圖之間過高的相關性。

  • Input:輸入層。通常使用Functional API方式構建模型時作為第一層。

  • DenseFeature:特征列接入層,用於接收一個特征列列表並產生一個密集連接層。

  • Flatten:壓平層,用於將多維張量壓成一維。

  • Reshape:形狀重塑層,改變輸入張量的形狀。

  • Concatenate:拼接層,將多個張量在某個維度上拼接。

  • Add:加法層。

  • Subtract: 減法層。

  • Maximum:取最大值層。

  • Minimum:取最小值層。

卷積網絡相關層

  • Conv1D:普通一維卷積,常用於文本。參數個數 = 輸入通道數×卷積核尺寸(如3)×卷積核個數

  • Conv2D:普通二維卷積,常用於圖像。參數個數 = 輸入通道數×卷積核尺寸(如3乘3)×卷積核個數

  • Conv3D:普通三維卷積,常用於視頻。參數個數 = 輸入通道數×卷積核尺寸(如3乘3乘3)×卷積核個數

  • SeparableConv2D:二維深度可分離卷積層。不同於普通卷積同時對區域和通道操作,深度可分離卷積先操作區域,再操作通道。即先對每個通道做獨立卷積操作區域,再用1乘1卷積跨通道組合操作通道。參數個數 = 輸入通道數×卷積核尺寸 + 輸入通道數×1×1×輸出通道數。深度可分離卷積的參數數量一般遠小於普通卷積,效果一般也更好。

  • DepthwiseConv2D:二維深度卷積層。僅有SeparableConv2D前半部分操作,即只操作區域,不操作通道,一般輸出通道數和輸入通道數相同,但也可以通過設置depth_multiplier讓輸出通道為輸入通道的若干倍數。輸出通道數 = 輸入通道數 × depth_multiplier。參數個數 = 輸入通道數×卷積核尺寸× depth_multiplier。

  • Conv2DTranspose:二維卷積轉置層,俗稱反卷積層。並非卷積的逆操作,但在卷積核相同的情況下,當其輸入尺寸是卷積操作輸出尺寸的情況下,卷積轉置的輸出尺寸恰好是卷積操作的輸入尺寸。

  • LocallyConnected2D: 二維局部連接層。類似Conv2D,唯一的差別是沒有空間上的權值共享,所以其參數個數遠高於二維卷積。

  • MaxPooling2D: 二維最大池化層。也稱作下采樣層。池化層無參數,主要作用是降維。

  • AveragePooling2D: 二維平均池化層。

  • GlobalMaxPool2D: 全局最大池化層。每個通道僅保留一個值。一般從卷積層過渡到全連接層時使用,是Flatten的替代方案。

  • GlobalAvgPool2D: 全局平均池化層。每個通道僅保留一個值。

循環網絡相關層

  • Embedding:嵌入層。一種比Onehot更加有效的對離散特征進行編碼的方法。一般用於將輸入中的單詞映射為稠密向量。嵌入層的參數需要學習。

  • LSTM:長短記憶循環網絡層。最普遍使用的循環網絡層。具有攜帶軌道,遺忘門,更新門,輸出門。可以較為有效地緩解梯度消失問題,從而能夠適用長期依賴問題。設置return_sequences = True時可以返回各個中間步驟輸出,否則只返回最終輸出。

  • GRU:門控循環網絡層。LSTM的低配版,不具有攜帶軌道,參數數量少於LSTM,訓練速度更快。

  • SimpleRNN:簡單循環網絡層。容易存在梯度消失,不能夠適用長期依賴問題。一般較少使用。

  • ConvLSTM2D:卷積長短記憶循環網絡層。結構上類似LSTM,但對輸入的轉換操作和對狀態的轉換操作都是卷積運算。

  • Bidirectional:雙向循環網絡包裝器。可以將LSTM,GRU等層包裝成雙向循環網絡。從而增強特征提取能力。

  • RNN:RNN基本層。接受一個循環網絡單元或一個循環單元列表,通過調用tf.keras.backend.rnn函數在序列上進行迭代從而轉換成循環網絡層。

  • LSTMCell:LSTM單元。和LSTM在整個序列上迭代相比,它僅在序列上迭代一步。可以簡單理解LSTM即RNN基本層包裹LSTMCell。

  • GRUCell:GRU單元。和GRU在整個序列上迭代相比,它僅在序列上迭代一步。

  • SimpleRNNCell:SimpleRNN單元。和SimpleRNN在整個序列上迭代相比,它僅在序列上迭代一步。

  • AbstractRNNCell:抽象RNN單元。通過對它的子類化用戶可以自定義RNN單元,再通過RNN基本層的包裹實現用戶自定義循環網絡層。

  • Attention:Dot-product類型注意力機制層。可以用於構建注意力模型。

  • AdditiveAttention:Additive類型注意力機制層。可以用於構建注意力模型。

  • TimeDistributed:時間分布包裝器。包裝后可以將Dense、Conv2D等作用到每一個時間片段上。

二,自定義模型層

如果自定義模型層沒有需要被訓練的參數,一般推薦使用Lamda層實現。

如果自定義模型層有需要被訓練的參數,則可以通過對Layer基類子類化實現。

Lamda層由於沒有需要被訓練的參數,只需要定義正向傳播邏輯即可,使用比Layer基類子類化更加簡單。

Lamda層的正向邏輯可以使用Python的lambda函數來表達,也可以用def關鍵字定義函數來表達。

import tensorflow as tf
from tensorflow.keras import layers,models,regularizers
 
mypower = layers.Lambda(lambda x:tf.math.pow(x,2))
mypower(tf.range(5))
<tf.Tensor: shape=(5,), dtype=int32, numpy=array([ 0,  1,  4,  9, 16], dtype=int32)>

Layer的子類化一般需要重新實現初始化方法,Build方法和Call方法。下面是一個簡化的線性層的范例,類似Dense.

class Linear(layers.Layer):
    def __init__(self, units=32, **kwargs):
        super(Linear, self).__init__(**kwargs)
        self.units = units
 
    #build方法一般定義Layer需要被訓練的參數。    
    def build(self, input_shape): 
        self.w = self.add_weight(shape=(input_shape[-1], self.units),
                                 initializer='random_normal',
                                 trainable=True)
        self.b = self.add_weight(shape=(self.units,),
                                 initializer='random_normal',
                                 trainable=True)
        super(Linear,self).build(input_shape) # 相當於設置self.built = True
 
    #call方法一般定義正向傳播運算邏輯,__call__方法調用了它。    
    def call(self, inputs): 
        return tf.matmul(inputs, self.w) + self.b
 
    #如果要讓自定義的Layer通過Functional API 組合成模型時可以序列化,需要自定義get_config方法。
    def get_config(self):  
        config = super(Linear, self).get_config()
        config.update({'units': self.units})
        return config
linear = Linear(units = 8)
print(linear.built)
# 指定input_shape,顯式調用build方法,第0維代表樣本數量,用None填充
linear.build(input_shape = (None,16)) 
print(linear.built)
False
True
linear = Linear(units = 8)
print(linear.built)
linear.build(input_shape = (None,16)) 
print(linear.compute_output_shape(input_shape = (None,16)))
False
(None, 8)
linear = Linear(units = 16)
print(linear.built)
# 如果built = False,調用__call__時會先調用build方法, 再調用call方法。
linear(tf.random.uniform((100,64))) 
print(linear.built)
config = linear.get_config()
print(config)
False
True
{'name': 'linear_3', 'trainable': True, 'dtype': 'float32', 'units': 16}
tf.keras.backend.clear_session()
 
model = models.Sequential()
# 注意該處的input_shape會被模型加工,無需使用None代表樣本數量維
model.add(Linear(units = 16,input_shape = (64,)))  
print("model.input_shape: ",model.input_shape)
print("model.output_shape: ",model.output_shape)
model.summary()
model.input_shape:  (None, 64)
model.output_shape:  (None, 16)
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
linear (Linear)              (None, 16)                1040      
=================================================================
Total params: 1,040
Trainable params: 1,040
Non-trainable params: 0

 

參考:

開源電子書地址:https://lyhue1991.github.io/eat_tensorflow2_in_30_days/

GitHub 項目地址:https://github.com/lyhue1991/eat_tensorflow2_in_30_days


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM