我在前面的一篇部落格 深入淺出談談深度可分離卷積 中介紹了深度可分離卷積的原理,然後用 tensorflow 實作了下。
在 tensorflow 中的接口是 slim.separable_conv2d(),接口說明:
def separable_convolution2d(
inputs,
num_outputs,
kernel_size,
depth_multiplier=1,
stride=1,
padding='SAME',
data_format=DATA_FORMAT_NHWC,
rate=1,
activation_fn=nn.relu,
normalizer_fn=None,
normalizer_params=None,
weights_initializer=initializers.xavier_initializer(),
pointwise_initializer=None,
weights_regularizer=None,
biases_initializer=init_ops.zeros_initializer(),
biases_regularizer=None,
reuse=None,
variables_collections=None,
outputs_collections=None,
trainable=True,
scope=None):
"""一個2維的可分離卷積,可以選擇是否增加BN層。
這個操作首先執行逐通道的卷積(每個通道分别執行卷積),建立一個稱為depthwise_weights的變量。如果num_outputs
不為空,它将增加一個pointwise的卷積(混合通道間的資訊),建立一個稱為pointwise_weights的變量。如果
normalizer_fn為空,它将給結果加上一個偏置,并且建立一個為biases的變量,如果不為空,那麼歸一化函數将被調用。
最後再調用一個激活函數然後得到最終的結果。
Args:
inputs: 一個形狀為[batch_size, height, width, channels]的tensor
num_outputs: pointwise 卷積的卷積核個數,如果為空,将跳過pointwise卷積的步驟.
kernel_size: 卷積核的尺寸:[kernel_height, kernel_width],如果兩個的值相同,則可以為一個整數。
depth_multiplier: 卷積乘子,即每個輸入通道經過卷積後的輸出通道數。總共的輸出通道數将為:
num_filters_in * depth_multiplier。
stride:卷積步長,[stride_height, stride_width],如果兩個值相同的話,為一個整數值。
padding: 填充方式,'VALID' 或者 'SAME'.
data_format:資料格式, `NHWC` (預設) 和 `NCHW`
rate: 空洞卷積的膨脹率:[rate_height, rate_width],如果兩個值相同的話,可以為整數值。如果這兩個值
任意一個大于1,那麼stride的值必須為1.
activation_fn: 激活函數,預設為ReLU。如果設定為None,将跳過。
normalizer_fn: 歸一化函數,用來替代biase。如果歸一化函數不為空,那麼biases_initializer
和biases_regularizer将被忽略。 biases将不會被建立。如果設為None,将不會有歸一化。
normalizer_params: 歸一化函數的參數。
weights_initializer: depthwise卷積的權重初始化器
pointwise_initializer: pointwise卷積的權重初始化器。如果設為None,将使用weights_initializer。
weights_regularizer: (可選)權重正則化器。
biases_initializer: 偏置初始化器,如果為None,将跳過偏置。
biases_regularizer: (可選)偏置正則化器。
reuse: 網絡層和它的變量是否可以被重用,為了重用,網絡層的scope必須被提供。
variables_collections: (可選)所有變量的collection清單,或者是一個關鍵字為變量值為collection的字典。
outputs_collections: 輸出被添加的collection.
trainable: 變量是否可以被訓練
scope: (可選)變量的命名空間。
Returns:
代表這個操作的輸出的一個tensor
但是這個接口根據原理來看,我覺得有個缺點,如果設定 depth_multiplier 為1,則變成了單通道的點乘,那這樣是否缺乏了通道間的資訊融合?
這樣顯然能極大程度減少參數,但是網絡性能也會受到影響,至少對于low-levle 的 cv 任務來說,性能下降很大。
如有不對請指正。