TF2.0 API學習(Python)一
common.py
一、卷積層函式分析
def convolutional(input_layer, filters_shape, downsample=False, activate=True, bn=True):
if downsample:
input_layer = tf.keras.layers.ZeroPadding2D(((1, 0), (1, 0)))(input_layer)
padding = 'valid'
strides = 2
else:
strides = 1
padding = 'same'
conv = tf.keras.layers.Conv2D(filters=filters_shape[-1], kernel_size = filters_shape[0], strides=strides, padding=padding,
use_bias=not bn, kernel_regularizer=tf.keras.regularizers.l2(0.0005),
kernel_initializer=tf.random_normal_initializer( stddev=0.01),
bias_initializer=tf.constant_initializer(0.))(input_layer)
if bn: conv = BatchNormalization()(conv)
if activate == True: conv = tf.nn.leaky_relu(conv, alpha=0.1)
return conv
1、tf.keras.layers.ZeroPadding2D
tf.keras.layers.ZeroPadding2D(
padding=(1, 1), data_format=None, **kwargs
)
- 引數:
padding:
Int,或2個整數的元組,或2個整數的2個元組。
如果為int,則將相同的對稱填充應用於高度和寬度。
如果元組為2 ints:解釋為高度和寬度的兩個不同的對稱填充值:(symmetric_height_pad,symmetric_width_pad)。
如果2個元組的2個整數的元組:解釋為(((top_pad,bottom_pad),((left_pad,right_pad)))
data_format:
字串,channels_last(預設)或channels_first中的一個。 輸入中尺寸的順序。 channels_last對應於形狀(batch_size,高度,寬度,通道)的輸入,而channels_first對應於形狀(batch_size,通道,高度,寬度)的輸入。 它預設為在〜/ .keras / keras.json中的Keras配置檔案中找到的image_data_format值。 如果您從未設定,那麼它將是“ channels_last”。
2、tf.keras.layers.Conv2D
該層建立一個卷積核心,該卷積核心與該層輸入進行卷積以產生輸出張量。 如果use_bias為True,則會建立一個偏差向量並將其新增到輸出中。 最後,如果啟用不為“無”,則它也將應用於輸出。
當將此層用作模型的第一層時,請提供關鍵字引數input_shape(整數元組或None,不包括樣本軸),例如 對於data_format =“ channels_last”中的128x128 RGB圖片,input_shape =(128,128,3)。
tf.keras.layers.Conv2D(
filters, kernel_size, strides=(1, 1), padding='valid',
data_format=None, dilation_rate=(1, 1), groups=1, activation=None,
use_bias=True,
)
1)引數:
filters:整數,輸出空間的維數(即卷積中輸出過濾器的數量)。
kernel_size:2個整數的整數或元組/列表,指定2D卷積視窗的高度和寬度。 可以是單個整數,以為所有空間尺寸指定相同的值。
strides:一個整數或2個整數的元組/列表,指定沿高度和寬度的卷積步幅。 可以是單個整數,以為所有空間尺寸指定相同的值。 指定任何跨步值!= 1與指定任何dilation_rate值!= 1不相容。
padding:“valid”或“same”(不區分大小寫)之一。 “有效”表示沒有填充。 “相同”導致向輸入的左/右或上/下均勻填充,以使輸出具有與輸入相同的高度/寬度尺寸。
data_format:字串,channels_last(預設)或channels_first中的一個。 輸入中尺寸的順序。 channels_last對應於形狀(batch_size,高度,寬度,通道)的輸入,而channels_first對應於形狀(batch_size,通道,高度,寬度)的輸入。
dilation_rate:一個整數或2個整數的元組/列表,指定要用於擴張卷積的擴張率。 可以是單個整數,以為所有空間尺寸指定相同的值。
groups:一個正整數,指定輸入沿通道軸劃分的組數。 每個組分別與過濾器/組過濾器卷積。 輸出是沿著通道軸的所有組結果的串聯。 輸入通道和過濾器都必須被組整除。
activation:要使用的啟用功能。 如果您未指定任何內容,則不會應用任何啟用(請參閱keras.activations)。
use_bias:布林值,層是否使用偏差向量。
2)輸入輸出格式
Input shape:
4+D tensor with shape: batch_shape + (channels, rows, cols) if data_format=‘channels_first’ or 4+D tensor with shape: batch_shape + (rows, cols, channels) if data_format=‘channels_last’.
Output shape:
4+D tensor with shape: batch_shape + (filters, new_rows, new_cols) if data_format=‘channels_first’ or 4+D tensor with shape: batch_shape + (new_rows, new_cols, filters) if data_format=‘channels_last’. rows and cols values might have changed due to padding.
3)返回值:
代表啟用的4+級張量(conv2d(inputs,kernel)+ bias)。
4)示例:
# The inputs are 28x28 RGB images with `channels_last` and the batch
# size is 4.
input_shape = (4, 28, 28, 3)
x = tf.random.normal(input_shape)
y = tf.keras.layers.Conv2D(
2, 3, activation='relu', input_shape=input_shape[1:])(x)
print(y.shape)
(4, 26, 26, 2)
# With `dilation_rate` as 2.
input_shape = (4, 28, 28, 3)
x = tf.random.normal(input_shape)
y = tf.keras.layers.Conv2D(
2, 3, activation='relu', dilation_rate=2, input_shape=input_shape[1:])(x)
print(y.shape)
(4, 24, 24, 2)
input_shape = (4, 28, 28, 3)
x = tf.random.normal(input_shape)
y = tf.keras.layers.Conv2D(
2, 3, activation='relu', padding="same", input_shape=input_shape[1:])(x)
print(y.shape)
(4, 28, 28, 2)
3、tf.random.normal
從正態分佈輸出隨機值。
tf.random.normal(
shape, mean=0.0, stddev=1.0, dtype=tf.dtypes.float32, seed=None, name=None
)
1)引數
shape:
一維整數Tensor或Python陣列。 輸出張量的形狀
mean:
型別為dtype的Tensor或Python值,可通過stddev廣播。 正態分佈的平均值。
stddev:
dtype型別的Tensor或Python值,可通過mean廣播。 正態分佈的標準偏差。
dtype:
輸出數值型別
seed:
一個Python整數。 用於為分發建立隨機種子。 有關行為,請參見tf.random.set_seed。
2)示例:
tf.random.set_seed(5);
tf.random.normal([2,2], 0, 1, tf.float32, seed=1)
4、tf.keras.layers.BatchNormalization
tf.keras.layers.BatchNormalization(
axis=-1, momentum=0.99, epsilon=0.001, center=True, scale=True,
beta_initializer='zeros', gamma_initializer='ones',
)
批次歸一化應用了一種變換,該變換可將平均輸出保持在0左右並將輸出標準偏差保持在1附近。
重要的是,批次歸一化在訓練和推斷期間的工作方式有所不同。
在訓練期間(即,使用fit()或使用引數training = True呼叫層/模型時),此層將使用當前輸入批次的均值和標準差對輸出進行歸一化。 也就是說,對於每個標準化的通道,該層返回(batch-mean(batch))/(var(batch)+ epsilon)* gamma + beta,其中:
epsilon是一個小的常數(可作為建構函式引數的一部分進行配置)
gamma是學習的比例因子(初始化為1),可以通過將scale = False傳遞給建構函式來禁用它。
beta是學習的偏移因子(初始化為0),可以通過將center = False傳遞給建構函式來禁用它。
在推論期間(即,當使用Evaluate()或predict()或使用引數training = False(這是預設值)呼叫圖層/模型時,圖層會使用平均值和標準偏差的移動平均值對輸出進行歸一化 訓練期間看到的批次,即返回(batch-self.moving_mean)/(self.moving_var + epsilon)* gamma + beta。
self.moving_mean和self.moving_var是不可訓練的變數,每次在訓練模式下呼叫圖層時都會更新,例如:
moving_mean = moving_mean * momentum + mean(batch) * (1 - momentum)
moving_var = moving_var * momentum + var(batch) * (1 - momentum)
這樣,該層將僅在已經對具有與推斷資料相似的統計資料的資料進行訓練之後的推斷期間對其輸入進行歸一化。
5、tf.nn.leaky_relu
計算leaky_relu啟用函式
tf.nn.leaky_relu(
features, alpha=0.2, name=None
)
6、tf.concat
tf.concat(
values, axis, name=‘concat’
)
t1 = [[1, 2, 3], [4, 5, 6]]
t2 = [[7, 8, 9], [10, 11, 12]]
tf.concat([t1, t2], 0)
tf.concat([t1, t2], 1)
二、殘差塊分析
def residual_block(input_layer, input_channel, filter_num1, filter_num2):
short_cut = input_layer
conv = convolutional(input_layer, filters_shape=(1, 1, input_channel, filter_num1))
conv = convolutional(conv , filters_shape=(3, 3, filter_num1, filter_num2))
residual_output = short_cut + conv
return residual_output
三、BatchNormalization類
class BatchNormalization(tf.keras.layers.BatchNormalization):
"""
"Frozen state" and "inference mode" are two separate concepts.
`layer.trainable = False` is to freeze the layer, so the layer will use
stored moving `var` and `mean` in the "inference mode", and both `gama`
and `beta` will not be updated !
"""
def call(self, x, training=False):
if not training:
training = tf.constant(False)
training = tf.logical_and(training, self.trainable)
return super().call(x, training)
四、上取樣
def upsample(input_layer):
return tf.image.resize(input_layer, (input_layer.shape[1] * 2, input_layer.shape[2] * 2), method='nearest')
backbone.py
def darknet53(input_data):
input_data = common.convolutional(input_data, (3, 3, 3, 32))
input_data = common.convolutional(input_data, (3, 3, 32, 64), downsample=True)
for i in range(1):
input_data = common.residual_block(input_data, 64, 32, 64)
input_data = common.convolutional(input_data, (3, 3, 64, 128), downsample=True)
for i in range(2):
input_data = common.residual_block(input_data, 128, 64, 128)
input_data = common.convolutional(input_data, (3, 3, 128, 256), downsample=True)
for i in range(8):
input_data = common.residual_block(input_data, 256, 128, 256)
route_1 = input_data
input_data = common.convolutional(input_data, (3, 3, 256, 512), downsample=True)
for i in range(8):
input_data = common.residual_block(input_data, 512, 256, 512)
route_2 = input_data
input_data = common.convolutional(input_data, (3, 3, 512, 1024), downsample=True)
for i in range(4):
input_data = common.residual_block(input_data, 1024, 512, 1024)
return route_1, route_2, input_data