TensorFlow 中的 layers 模塊提供用於深度學習的更高層次封裝的 API,利用它咱們能夠輕鬆地構建模型,這一節咱們就來看下這個模塊的 API 的具體用法。python
layers 模塊的路徑寫法爲 tf.layers,這個模塊定義在 tensorflow/python/layers/layers.py,其官方文檔地址爲:https://www.tensorflow.org/api_docs/python/tf/layers,TensorFlow 版本爲 1.5。git
這裏面提供了多個類和方法以供使用,下面咱們分別予以介紹。github
tf.layers 模塊提供的方法有:api
Input(…): 用於實例化一個輸入 Tensor,做爲神經網絡的輸入。網絡
average_pooling1d(…): 一維平均池化層app
average_pooling2d(…): 二維平均池化層ide
average_pooling3d(…): 三維平均池化層函數
batch_normalization(…): 批量標準化層學習
conv1d(…): 一維卷積層spa
conv2d(…): 二維卷積層
conv2d_transpose(…): 二維反捲積層
conv3d(…): 三維卷積層
conv3d_transpose(…): 三維反捲積層
dense(…): 全鏈接層
dropout(…): Dropout層
flatten(…): Flatten層,即把一個 Tensor 展平
max_pooling1d(…): 一維最大池化層
max_pooling2d(…): 二維最大池化層
max_pooling3d(…): 三維最大池化層
separable_conv2d(…): 二維深度可分離卷積層
tf.layers.Input() 這個方法是用於輸入數據的方法,其實相似於 tf.placeholder,至關於一個佔位符的做用,固然也能夠經過傳入 tensor 參數來進行賦值。
Input(
shape=None,
batch_size=None,
name=None,
dtype=tf.float32,
sparse=False,
tensor=None
)
參數說明以下:
shape:可選,默認 None,是一個數字組成的元組或列表,可是這個 shape 比較特殊,它不包含 batch_size,好比傳入的 shape 爲 [32],那麼它會將 shape 轉化爲 [?, 32],這裏必定須要注意。
batch_size:可選,默認 None,表明輸入數據的 batch size,能夠是數字或者 None。
name:可選,默認 None,輸入層的名稱。
dtype:可選,默認 tf.float32,元素的類型。
sparse:可選,默認 False,指定是否以稀疏矩陣的形式來建立 placeholder。
tensor:可選,默認 None,若是指定,那麼建立的內容便再也不是一個 placeholder,會用此 Tensor 初始化。
返回值:
返回一個包含歷史 Meta Data 的 Tensor。
咱們用一個實例來感覺一下:
x = tf.layers.Input(shape=[32])
print(x)
y = tf.layers.dense(x, 16, activation=tf.nn.softmax)
print(y)
首先咱們用 Input() 方法初始化了一個 placeholder,這時咱們沒有傳入 tensor 參數,而後調用了 dense() 方法構建了一個全鏈接網絡,激活函數使用 softmax,而後將兩者輸出,結果以下:
Tensor("input_layer_1:0", shape=(?, 32), dtype=float32)
Tensor("dense/Softmax:0", shape=(?, 16), dtype=float32)
這時咱們發現,shape 它給咱們作了轉化,原本是 [32],結果它給轉化成了 [?, 32],即第一維表明 batch_size,因此咱們須要注意,在調用此方法的時候不須要去關心 batch_size 這一維。
若是咱們在初始化的時候傳入一個已有 Tensor,例如:
data = tf.constant([1, 2, 3])
x = tf.layers.Input(tensor=data)
print(x)
結果以下:
Tensor("Const:0", shape=(3,), dtype=int32)
能夠看到它能夠自動計算出其 shape 和 dtype。
此方法是批量標準化的方法,通過處理以後能夠加速訓練速度,其定義在 tensorflow/python/layers/normalization.py,論文能夠參考:http://arxiv.org/abs/1502.03167"Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift"。
batch_normalization(
inputs,
axis=-1,
momentum=0.99,
epsilon=0.001,
center=True,
scale=True,
beta_initializer=tf.zeros_initializer(),
gamma_initializer=tf.ones_initializer(),
moving_mean_initializer=tf.zeros_initializer(),
moving_variance_initializer=tf.ones_initializer(),
beta_regularizer=None,
gamma_regularizer=None,
beta_constraint=None,
gamma_constraint=None,
training=False,
trainable=True,
name=None,
reuse=None,
renorm=False,
renorm_clipping=None,
renorm_momentum=0.99,
fused=None,
virtual_batch_size=None,
adjustment=None
)
參數說明以下:
inputs:必需,即輸入數據。
axis:可選,默認 -1,即進行標註化操做時操做數據的哪一個維度。
momentum:可選,默認 0.99,即動態均值的動量。
epsilon:可選,默認 0.01,大於0的小浮點數,用於防止除0錯誤。
center:可選,默認 True,若設爲True,將會將 beta 做爲偏置加上去,不然忽略參數 beta
scale:可選,默認 True,若設爲True,則會乘以gamma,不然不使用gamma。當下一層是線性的時,能夠設False,由於scaling的操做將被下一層執行。
beta_initializer:可選,默認 zeros_initializer,即 beta 權重的初始方法。
gamma_initializer:可選,默認 ones_initializer,即 gamma 的初始化方法。
moving_mean_initializer:可選,默認 zeros_initializer,即動態均值的初始化方法。
moving_variance_initializer:可選,默認 ones_initializer,即動態方差的初始化方法。
beta_regularizer: 可選,默認None,beta 的正則化方法。
gamma_regularizer: 可選,默認None,gamma 的正則化方法。
beta_constraint: 可選,默認None,加在 beta 上的約束項。
gamma_constraint: 可選,默認None,加在 gamma 上的約束項。
training:可選,默認 False,返回結果是 training 模式。
trainable:可選,默認爲 True,布爾類型,若是爲 True,則將變量添加 GraphKeys.TRAINABLE_VARIABLES 中。
name:可選,默認 None,層名稱。
reuse:可選,默認 None,根據層名判斷是否重複利用。
renorm:可選,默認 False,是否要用 Batch Renormalization (https://arxiv.org/abs/1702.03275)
renorm_clipping:可選,默認 None,是否要用 rmax、rmin、dmax 來 scalar Tensor。
renorm_momentum,可選,默認 0.99,用來更新動態均值和標準差的 Momentum 值。
fused,可選,默認 None,是否使用一個更快的、融合的實現方法。
virtual_batch_size,可選,默認 None,是一個 int 數字,指定一個虛擬 batch size。
adjustment,可選,默認 None,對標準化後的結果進行適當調整的方法。
最後的一些參數說明不夠詳盡,更詳細的用法參考:https://www.tensorflow.org/api_docs/python/tf/layers/batch_normalization。
其用法很簡單,在輸入數據後面加一層 batch_normalization() 便可:
x = tf.layers.Input(shape=[32])
x = tf.layers.batch_normalization(x)
y = tf.layers.dense(x, 20)
dense,即全鏈接網絡,layers 模塊提供了一個 dense() 方法來實現此操做,定義在 tensorflow/python/layers/core.py 中,下面咱們來講明一下它的用法。
dense(
inputs,
units,
activation=None,
use_bias=True,
kernel_initializer=None,
bias_initializer=tf.zeros_initializer(),
kernel_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
kernel_constraint=None,
bias_constraint=None,
trainable=True,
name=None,
reuse=None
)
參數說明以下:
inputs:必需,即須要進行操做的輸入數據。
units:必須,即神經元的數量。
activation:可選,默認爲 None,若是爲 None 則是線性激活。
use_bias:可選,默認爲 True,是否使用偏置。
kernel_initializer:可選,默認爲 None,即權重的初始化方法,若是爲 None,則使用默認的 Xavier 初始化方法。
bias_initializer:可選,默認爲零值初始化,即偏置的初始化方法。
kernel_regularizer:可選,默認爲 None,施加在權重上的正則項。
bias_regularizer:可選,默認爲 None,施加在偏置上的正則項。
activity_regularizer:可選,默認爲 None,施加在輸出上的正則項。
kernel_constraint,可選,默認爲 None,施加在權重上的約束項。
bias_constraint,可選,默認爲 None,施加在偏置上的約束項。
trainable:可選,默認爲 True,布爾類型,若是爲 True,則將變量添加到 GraphKeys.TRAINABLE_VARIABLES 中。
name:可選,默認爲 None,卷積層的名稱。
reuse:可選,默認爲 None,布爾類型,若是爲 True,那麼若是 name 相同時,會重複利用。
返回值:
全鏈接網絡處理後的 Tensor。
下面咱們用一個實例來感覺一下它的用法:
x = tf.layers.Input(shape=[32])
print(x)
y1 = tf.layers.dense(x, 16, activation=tf.nn.relu)
print(y1)
y2 = tf.layers.dense(y1, 5, activation=tf.nn.sigmoid)
print(y2)
首先咱們用 Input 定義了 [?, 32] 的輸入數據,而後通過第一層全鏈接網絡,此時指定了神經元個數爲 16,激活函數爲 relu,接着輸出結果通過第二層全鏈接網絡,此時指定了神經元個數爲 5,激活函數爲 sigmoid,最後輸出,結果以下:
Tensor("input_layer_1:0", shape=(?, 32), dtype=float32)
Tensor("dense/Relu:0", shape=(?, 16), dtype=float32)
Tensor("dense_2/Sigmoid:0", shape=(?, 5), dtype=float32)
能夠看到輸出結果的最後一維度就等於神經元的個數,這是很是容易理解的。
convolution,即卷積,這裏提供了多個卷積方法,如 conv1d()、conv2d()、conv3d(),分別表明一維、二維、三維卷積,另外還有 conv2d_transpose()、conv3d_transpose(),分別表明二維和三維反捲積,還有 separable_conv2d() 方法表明二維深度可分離卷積。它們定義在 tensorflow/python/layers/convolutional.py 中,其用法都是相似的,在這裏以 conv2d() 方法爲例進行說明。
conv2d(
inputs,
filters,
kernel_size,
strides=(1, 1),
padding='valid',
data_format='channels_last',
dilation_rate=(1, 1),
activation=None,
use_bias=True,
kernel_initializer=None,
bias_initializer=tf.zeros_initializer(),
kernel_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
kernel_constraint=None,
bias_constraint=None,
trainable=True,
name=None,
reuse=None
)
參數說明以下:
inputs:必需,即須要進行操做的輸入數據。
filters:必需,是一個數字,表明了輸出通道的個數,即 output_channels。
kernel_size:必需,卷積核大小,必須是一個數字(高和寬都是此數字)或者長度爲 2 的列表(分別表明高、寬)。
strides:可選,默認爲 (1, 1),卷積步長,必須是一個數字(高和寬都是此數字)或者長度爲 2 的列表(分別表明高、寬)。
padding:可選,默認爲 valid,padding 的模式,有 valid 和 same 兩種,大小寫不區分。
data_format:可選,默認 channels_last,分爲 channels_last 和 channels_first 兩種模式,表明了輸入數據的維度類型,若是是 channels_last,那麼輸入數據的 shape 爲 (batch, height, width, channels),若是是 channels_first,那麼輸入數據的 shape 爲 (batch, channels, height, width)。
dilation_rate:可選,默認爲 (1, 1),卷積的擴張率,如當擴張率爲 2 時,卷積核內部就會有邊距,3x3 的卷積核就會變成 5x5。
activation:可選,默認爲 None,若是爲 None 則是線性激活。
use_bias:可選,默認爲 True,是否使用偏置。
kernel_initializer:可選,默認爲 None,即權重的初始化方法,若是爲 None,則使用默認的 Xavier 初始化方法。
bias_initializer:可選,默認爲零值初始化,即偏置的初始化方法。
kernel_regularizer:可選,默認爲 None,施加在權重上的正則項。
bias_regularizer:可選,默認爲 None,施加在偏置上的正則項。
activity_regularizer:可選,默認爲 None,施加在輸出上的正則項。
kernel_constraint,可選,默認爲 None,施加在權重上的約束項。
bias_constraint,可選,默認爲 None,施加在偏置上的約束項。
trainable:可選,默認爲 True,布爾類型,若是爲 True,則將變量添加到 GraphKeys.TRAINABLE_VARIABLES 中。
name:可選,默認爲 None,卷積層的名稱。
reuse:可選,默認爲 None,布爾類型,若是爲 True,那麼若是 name 相同時,會重複利用。
返回值:
卷積後的 Tensor。
下面咱們用實例感覺一下它的用法:
x = tf.layers.Input(shape=[20, 20, 3])
y = tf.layers.conv2d(x, filters=6, kernel_size=2, padding='same')
print(y)
這裏咱們首先聲明瞭一個 [?, 20, 20, 3] 的輸入 x,而後將其傳給 conv2d() 方法,filters 設定爲 6,即輸出通道爲 6,kernel_size 爲 2,即卷積核大小爲 2 x 2,padding 方式設置爲 same,那麼輸出結果的寬高和原來必定是相同的,可是輸出通道就變成了 6,結果以下:
Tensor("conv2d/BiasAdd:0", shape=(?, 20, 20, 6), dtype=float32)
但若是咱們將 padding 方式不傳入,使用默認的 valid 模式,代碼改寫以下:
x = tf.layers.Input(shape=[20, 20, 3])
y = tf.layers.conv2d(x, filters=6, kernel_size=2)
print(y)
結果以下:
Tensor("conv2d/BiasAdd:0", shape=(?, 19, 19, 6), dtype=float32)
結果就變成了 [?, 19, 19, 6],這是由於步長默認爲 1,卷積核大小爲 2 x 2,因此獲得的結果的高寬即爲 (20 - (2 - 1)) x (20 - (2 - 1)) = 19 x 19。
固然卷積核咱們也能夠變換大小,傳入一個列表形式:
x = tf.layers.Input(shape=[20, 20, 3])
y = tf.layers.conv2d(x, filters=6, kernel_size=[2, 3])
print(y)
這時咱們的卷積核大小變成了 2 x 3,即高爲 2,寬爲 3,結果就變成了 [?, 19, 18, 6],這是由於步長默認爲 1,卷積核大小爲 2 x 2,因此獲得的結果的高寬即爲 (20 - (2 - 1)) x (20 - (3 - 1)) = 19 x 18。
若是咱們將步長也設置一下,也傳入列表形式:
x = tf.layers.Input(shape=[20, 20, 3])
y = tf.layers.conv2d(x, filters=6, kernel_size=[2, 3], strides=[2, 2])
print(y)
這時卷積核大小變成了 2 x 3,步長變成了 2 x 2,因此結果的高寬爲 ceil(20 - (2- 1)) / 2 x ceil(20 - (3- 1)) / 2 = 10 x 9,獲得的結果即爲 [?, 10, 9, 6]。
運行結果以下:
Tensor("conv2d_4/BiasAdd:0", shape=(?, 10, 9, 6), dtype=float32)
另外咱們還能夠傳入激活函數,或者禁用 bias 等操做,實例以下:
x = tf.layers.Input(shape=[20, 20, 3])
y = tf.layers.conv2d(x, filters=6, kernel_size=2, activation=tf.nn.relu, use_bias=False)
print(y)
這樣咱們就將激活函數改爲了 relu,同時禁用了 bias,運行結果以下:
Tensor("conv2d_5/Relu:0", shape=(?, 19, 19, 6), dtype=float32)
另外還有反捲積操做,反捲積顧名思義即卷積的反向操做,即輸入卷積的結果,獲得卷積前的結果,其參數用法是徹底同樣的,例如:
x = tf.layers.Input(shape=[20, 20, 3])
y = tf.layers.conv2d_transpose(x, filters=6, kernel_size=2, strides=2)
print(y)
例如此處輸入的圖像高寬爲 20 x 20,通過卷積核爲 2,步長爲 2 的反捲積處理,獲得的結果高寬就變爲了 40 x 40,結果以下:
Tensor("conv2d_transpose/BiasAdd:0", shape=(?, 40, 40, 6), dtype=float32)
pooling,即池化,layers 模塊提供了多個池化方法,這幾個池化方法都是相似的,包括 max_pooling1d()、max_pooling2d()、max_pooling3d()、average_pooling1d()、average_pooling2d()、average_pooling3d(),分別表明一維二維三維最大和平均池化方法,它們都定義在 tensorflow/python/layers/pooling.py 中,這裏以 max_pooling2d() 方法爲例進行介紹。
max_pooling2d(
inputs,
pool_size,
strides,
padding='valid',
data_format='channels_last',
name=None
)
參數說明以下:
inputs: 必需,即須要池化的輸入對象,必須是 4 維的。
pool_size:必需,池化窗口大小,必須是一個數字(高和寬都是此數字)或者長度爲 2 的列表(分別表明高、寬)。
strides:必需,池化步長,必須是一個數字(高和寬都是此數字)或者長度爲 2 的列表(分別表明高、寬)。
padding:可選,默認 valid,padding 的方法,valid 或者 same,大小寫不區分。
data_format:可選,默認 channels_last,分爲 channels_last 和 channels_first 兩種模式,表明了輸入數據的維度類型,若是是 channels_last,那麼輸入數據的 shape 爲 (batch, height, width, channels),若是是 channels_first,那麼輸入數據的 shape 爲 (batch, channels, height, width)。
name:可選,默認 None,池化層的名稱。
返回值:
通過池化處理後的 Tensor。
下面咱們用一個實例來感覺一下:
x = tf.layers.Input(shape=[20, 20, 3])
print(x)
y = tf.layers.conv2d(x, filters=6, kernel_size=3, padding='same')
print(y)
p = tf.layers.max_pooling2d(y, pool_size=2, strides=2)
print(p)
在這裏咱們首先指定了輸入 x,shape 爲 [20, 20, 3],而後對其進行了卷積計算,而後池化,最後獲得池化後的結果。結果以下:
Tensor("input_layer_1:0", shape=(?, 20, 20, 3), dtype=float32)
Tensor("conv2d/BiasAdd:0", shape=(?, 20, 20, 6), dtype=float32)
Tensor("max_pooling2d/MaxPool:0", shape=(?, 10, 10, 6), dtype=float32)
能夠看到這裏池化窗口用的是 2,步長也是 2,因此本來卷積後 shape 爲 [?, 20, 20, 6] 的結果就變成了 [?, 10, 10, 6]。
dropout 是指在深度學習網絡的訓練過程當中,對於神經網絡單元,按照必定的機率將其暫時從網絡中丟棄,能夠用來防止過擬合,layers 模塊中提供了 dropout() 方法來實現這一操做,定義在 tensorflow/python/layers/core.py。下面咱們來講明一下它的用法。
dropout(
inputs,
rate=0.5,
noise_shape=None,
seed=None,
training=False,
name=None
)
參數說明以下:
inputs:必須,即輸入數據。
rate:可選,默認爲 0.5,即 dropout rate,如設置爲 0.1,則意味着會丟棄 10% 的神經元。
noise_shape:可選,默認爲 None,int32 類型的一維 Tensor,它表明了 dropout mask 的 shape,dropout mask 會與 inputs 相乘對 inputs 作轉換,例如 inputs 的 shape 爲 (batch_size, timesteps, features),但咱們想要 droput mask 在全部 timesteps 都是相同的,咱們能夠設置 noise_shape=[batch_size, 1, features]。
seed:可選,默認爲 None,即產生隨機熟的種子值。
training:可選,默認爲 False,布爾類型,即表明了是否標誌爲 training 模式。
name:可選,默認爲 None,dropout 層的名稱。
返回:
通過 dropout 層以後的 Tensor。
咱們用一個實例來感覺一下:
x = tf.layers.Input(shape=[32])
print(x)
y = tf.layers.dense(x, 16, activation=tf.nn.softmax)
print(y)
d = tf.layers.dropout(y, rate=0.2)
print(d)
運行結果:
Tensor("input_layer_1:0", shape=(?, 32), dtype=float32)
Tensor("dense/Softmax:0", shape=(?, 16), dtype=float32)
Tensor("dropout/Identity:0", shape=(?, 16), dtype=float32)
在這裏咱們使用 dropout() 方法實現了 droput 操做,並制定 dropout rate 爲 0.2,最後輸出結果的 shape 和原來是一致的。
flatten() 方法能夠對 Tensor 進行展平操做,定義在 tensorflow/python/layers/core.py。
flatten(
inputs,
name=None
)
參數說明以下:
inputs:必需,即輸入數據。
name:可選,默認爲 None,即該層的名稱。
返回結果:
展平後的 Tensor。
下面咱們用一個實例來感覺一下:
x = tf.layers.Input(shape=[5, 6])
print(x)
y = tf.layers.flatten(x)
print(y)
運行結果:
Tensor("input_layer_1:0", shape=(?, 5, 6), dtype=float32)
Tensor("flatten/Reshape:0", shape=(?, 30), dtype=float32)
這裏輸入數據的 shape 爲 [?, 5, 6],通過 flatten 層以後,就會變成 [?, 30],即將除了第一維的數據維度相乘,對原 Tensor 進行展平。
假如第一維是一個已知的數的話,它依然仍是一樣的處理,示例以下:
x = tf.placeholder(shape=[5, 6, 2], dtype=tf.float32)
print(x)
y = tf.layers.flatten(x)
print(y)
結果以下:
Tensor("Placeholder:0", shape=(5, 6, 2), dtype=float32)
Tensor("flatten_2/Reshape:0", shape=(5, 12), dtype=float32)
除了如上的方法,其實咱們還能夠直接使用類來進行操做,實際上看方法的實現就是實例化了其對應的類,下面咱們首先說明一下有哪些類可使用:
class AveragePooling1D: 一維平均池化層類
class AveragePooling2D: 二維平均池化層類
class AveragePooling3D: 三維平均池化層類
class BatchNormalization: 批量標準化層類
class Conv1D: 一維卷積層類
class Conv2D: 二維卷積層類
class Conv2DTranspose: 二維反捲積層類
class Conv3D: 三維卷積層類
class Conv3DTranspose: 三維反捲積層類
class Dense: 全鏈接層類
class Dropout: Dropout 層類
class Flatten: Flatten 層類
class InputSpec: Input 層類
class Layer: 基類、父類
class MaxPooling1D: 一維最大池化層類
class MaxPooling2D: 二維最大池化層類
class MaxPooling3D: 三維最大池化層類
class SeparableConv2D: 二維深度可分離卷積層類
其實類這些類都和上文介紹的方法是一一對應的,關於它的用法咱們能夠在方法的源碼實現裏面找到,下面咱們以 Dense 類的用法爲例來講明一下這些類的具體調用方法:
x = tf.layers.Input(shape=[32])
dense = tf.layers.Dense(16, activation=tf.nn.relu)
y = dense.apply(x)
print(y)
這裏咱們初始化了一個 Dense 類,它只接受一個必須參數,那就是 units,相比 dense() 方法來講它沒有了 inputs,所以這個實例化的類和 inputs 是無關的,這樣就至關於建立了一個 16 個神經元的全鏈接層。
但建立了不調用是沒有用的,咱們要將這個層構建到網絡之中,須要調用它的 apply() 方法,而 apply() 方法就接收 inputs 這個參數,返回計算結果,運行結果以下:
Tensor("dense/Relu:0", shape=(?, 16), dtype=float32)
所以咱們能夠發現,這些類在初始化的時候其實是比其對應的方法少了 inputs 參數,其餘的參數都是徹底一致的,另外須要調用 apply() 方法才能夠應用該層並將其構建到模型中。
因此其餘的類的用法在此就不一一贅述了,初始化的參數能夠類比其對應的方法,實例化類以後,調用 apply() 方法,能夠達到一樣的構建模型的效果。
以上即是 TensorFlow layers 模塊的詳細用法說明,更加詳細的用法能夠參考官方文檔:https://www.tensorflow.org/api_docs/python/tf/layers。本節代碼地址:https://github.com/AIDeepLearning/TensorFlowLayers。