Tensorflow的網路模型搭建
Tensorflow的網路模型搭建
1.0 引言
神經網路模型的搭建在深度學習中必不可少。從2012年至今湧現出了很多優秀的網路,例如vgg,inception系列。所以本文主要討論如何在tensorflow框架下去搭建自己的網路。(基於tensorflow1.10穩定版本)
在tensorflow框架下,有很多已經成熟的庫可以搭建網路,例如tf.keras,tf.nn,tf.layers,tensorlayer等等。如此多的庫讓人眼花繚亂,其實甭管黑貓白貓,抓住耗子的就是好貓。但是你挑的這隻貓不僅要既能過硬,還需要壽命長啊。換句話說,這些庫都能用,但是最好挑選社區強大,官方支持強大的庫,防止開發者中途跳票。綜上所述,個人推薦tensorflow的親兒子系列tf.keras,tf.nn,tf.layers-最為穩妥且穩定。
再來說說這三種庫的區別。
- tf.nn:最底層的函數,其他各種庫可以說都是基於這個底層庫來進行擴展的。
- tf.layers:比tf.nn更高級的庫,對tf.nn進行了多方位功能的擴展。用程序員的話來說,就是用tf.nn造的輪子。最大的特點就是庫中每個函數都有相應的類(函數名為大寫,看了下底層源碼,是從kears那遷移過來的)。
- tf.keras:如果說tf.layers是輪子,那麼keras可以說是汽車。tf.keras是基於tf.layers和tf.nn的高度封裝。
每個庫有每個庫的優勢,tf.nn和tf.layers靈活性相對較高,如果需要對底層進行很多操作,這兩個庫的優勢就會很明顯。但是如果工業上想搭建已經很成熟的網路並進行訓練,那麼keras相對來說會更加容易一些。具體需要在實際運用中去體會。 綜上所述,這幾種庫都可以運用,都很不錯,具體看運用背景。
2.0 構建網路
接下來我會討論構建網路的一般步驟。以構建CNN為例。
2.1 Convolution
對於卷積網路來說,卷積操作是基本操作之一。
- tf.nn
在nn庫中,根據不同的卷積方式會對應不同的卷積函數 。
tf.nn.convolution
是最基本的,
tf.nn.conv2d
能夠對二維的輸入數據進行卷積(共享卷積參數),
tf.nn.depthwise_conv2d
也能夠對二維的輸入數據進行卷積(不共享卷積參數),
tf.nn.separable_conv2d
對輸入數據進行不共享參數的方式進行卷積後,再進行一次卷積,
tf.nn.conv2d_transpose
也就是轉置卷積(反卷積)。
tf.nn.conv1d
類似於二維卷積,用來計算給定三維輸入和過濾器情況下的一維卷積。
tf.nn.conv3d
與二維卷積類似,用來計算給定五維輸入和過濾器的情況下的三維卷積.
具體的測試函數如下:
# - * - coding: utf - 8 -*-
import tensorflow as tf
import os
import numpy as np
os.environ[TF_CPP_MIN_LOG_LEVEL] = 2
# tf.nn.convolution
# 計算N維卷積的和
input_data = tf.Variable(np.random.rand(10, 9, 9, 3), dtype=np.float32)
filter_data = tf.Variable(np.random.rand(2, 2, 3, 2), dtype=np.float32)
y = tf.nn.convolution(input_data, filter_data, strides=[1, 1], padding=SAME)
print(1. tf.nn.convolution : , y)
# 1. tf.nn.convolution : Tensor("convolution:0", shape=(10, 9, 9, 2), dtype=float32)
# tf.nn.conv2d
# 對一個思維的輸入數據 input 和四維的卷積核filter 進行操作,然後對輸入的數據進行二維的卷積操作,得到卷積之後的結果
input_data = tf.Variable(np.random.rand(10, 9, 9, 3), dtype=np.float32)
filter_data = tf.Variable(np.random.rand(2, 2, 3, 2), dtype=np.float32)
y = tf.nn.conv2d(input_data, filter_data, strides=[1, 1, 1, 1], padding=SAME)
print(2. tf.nn.conv2d : , y)
#2. tf.nn.conv2d : Tensor("Conv2D:0", shape=(10, 9, 9, 2), dtype=float32)
# tf.nn.depthwise_conv2d
# input 的數據維度 [batch ,in_height,in_wight,in_channels]
# 卷積核的維度是 [filter_height,filter_heught,in_channel,channel_multiplierl]
# 講不通的卷積和獨立的應用在in_channels 的每一個通道上(從通道 1 到通道channel_multiplier)
# 然後將所有結果進行匯總,輸出通道的總數是,in_channel * channel_multiplier
input_data = tf.Variable(np.random.rand(10, 9, 9, 3), dtype=np.float32)
filter_data = tf.Variable(np.random.rand(2, 2, 3, 2), dtype=np.float32)
y = tf.nn.depthwise_conv2d(input_data, filter_data, strides=[1, 1, 1, 1], padding=SAME)
print(3. tf.nn.depthwise_conv2d : , y)
# tf.nn.separable_conv2d
# 利用幾個分離的卷積核去做卷積,在該函數中,將應用一個二維的卷積核,在每個通道上,以深度channel_multiplier進行卷積
input_data = tf.Variable(np.random.rand(10, 9, 9, 3), dtype=np.float32)
depthwise_filter = tf.Variable(np.random.rand(2, 2, 3, 5), dtype=np.float32)
poinwise_filter = tf.Variable(np.random.rand(1, 1, 15, 20), dtype=np.float32)
# out_channels >= channel_multiplier * in_channels
y = tf.nn.separable_conv2d(input_data, depthwise_filter=depthwise_filter, pointwise_filter=poinwise_filter,
strides=[1, 1, 1, 1], padding=SAME)
print(4. tf.nn.separable_conv2d : , y)
# 計算Atrous卷積,又稱孔卷積或者擴張卷積
input_data = tf.Variable(np.random.rand(1, 5, 5, 1), dtype=np.float32)
filters = tf.Variable(np.random.rand(3, 3, 1, 1), dtype=np.float32)
y = tf.nn.atrous_conv2d(input_data, filters, 2, padding=SAME)
print(5. tf.nn.atrous_conv2d : , y)
# 在解卷積網路(deconvolutional network) 中有時被稱為反卷積,但實際上是conv2d的轉置,而不是實際的反卷積
x = tf.random_normal(shape=[1, 3, 3, 1])
kernal = tf.random_normal(shape=[2, 2, 3, 1])
y = tf.nn.conv2d_transpose(x, kernal, output_shape=[1, 5, 5, 3], strides=[1, 2, 2, 1], padding=SAME)
print(6. tf.nn.conv2d_transpose : , y)
# 與二維卷積類似,用來計算給定三維輸入和過濾器的情況下的一維卷積.
# 不同的是,它的輸入維度為 3,[batch,in_width,in_channels].
# 卷積核的維度也是三維,[filter_height,in_channel,channel_multiplierl]
# stride 是一個正整數,代表一定每一步的步長
input_data = tf.Variable(np.random.rand(1, 5, 1), dtype=np.float32)
filters = tf.Variable(np.random.rand(3, 1, 3), dtype=np.float32)
y = tf.nn.conv1d(input_data, filters, stride=2, padding=SAME)
print(7. tf.nn.conv1d : , y)
# 與二維卷積類似,用來計算給定五維輸入和過濾器的情況下的三維卷積.
# 不同的是,它的輸入維度為 5,[batch,in_depth,in_height,in_width,in_channels].
# 卷積核的維度也是三維,[filter_depth,filter_height,in_channel,channel_multiplierl]
# stride 相較二維卷積多了一維,變為[strides_batch,strides_depth,strides_height,strides_width,strides_channel],必須保證strides[0] = strides[4] =1
input_data = tf.Variable(np.random.rand(1, 2, 5, 5, 1), dtype=np.float32)
filters = tf.Variable(np.random.rand(2, 3, 3, 1, 3), dtype=np.float32)
y = tf.nn.conv3d(input_data, filters, strides=[1, 2, 2, 1, 1], padding=SAME)
print(8. tf.nn.conv3d : , y)
# 與conv2d_transpose 二維反卷積類似
# 在解卷積網路(deconvolutional network) 中有時被稱為反卷積,但實際上是conv3d的轉置,而不是實際的反卷積
x = tf.random_normal(shape=[2, 1, 3, 3, 1])
kernal = tf.random_normal(shape=[2, 2, 2, 3, 1])
y = tf.nn.conv3d_transpose(x, kernal, output_shape=[2, 1, 5, 5, 3], strides=[1, 2, 2, 2, 1], padding=SAME)
print(9. tf.nn.conv3d_transpose : , y)
最後的輸出結果如下:
1. tf.nn.convolution : Tensor("convolution:0", shape=(10, 9, 9, 2), dtype=float32)
2. tf.nn.conv2d : Tensor("Conv2D:0", shape=(10, 9, 9, 2), dtype=float32)
3. tf.nn.depthwise_conv2d : Tensor("depthwise:0", shape=(10, 9, 9, 6), dtype=float32)
4. tf.nn.separable_conv2d : Tensor("separable_conv2d:0", shape=(10, 9, 9, 20), dtype=float32)
5. tf.nn.atrous_conv2d : Tensor("convolution_1/BatchToSpaceND:0", shape=(1, 5, 5, 1), dtype=float32)
6. tf.nn.conv2d_transpose : Tensor("conv2d_transpose:0", shape=(1, 5, 5, 3), dtype=float32)
7. tf.nn.conv1d : Tensor("conv1d/Squeeze:0", shape=(1, 3, 3), dtype=float32)
8. tf.nn.conv3d : Tensor("Conv3D:0", shape=(1, 1, 3, 5, 3), dtype=float32)
9. tf.nn.conv3d_transpose : Tensor("conv3d_transpose:0", shape=(2, 1, 5, 5, 3), dtype=float32)
- tf.layers
在layers庫中,就只有最為常見的卷積方式。
tf.layers.conv2d
: 二維卷積層,layers庫中的卷積函數有更多的參數選擇,例如激活函數的選擇,參數初始化方式等。
tf.layers.separable_conv2d
: 和nn類似,深度卷積
tf.layers.conv2d_transpose
: 二維反卷積層
tf.layers.conv1d
: 一維卷積層
tf.layers.conv3d
: 三維卷積層
還有一些函數可以參見官方文檔。
- tf.keras.layers
tf.keras.layers.Conv2D
:大部分參數和 tf.layers
類似,但是比較關鍵的地方就是keras
取消了trainable這個參數,意味著keras無法控制層的參數更新與否,默認是更新參數的,這樣的話不太好進行freeze操作。
其他大部分函數也都和其他庫函數類似,再次不贅述了。
2.2 Pooling
- tf.nn
tf.nn.pool
:池化操作的基本函數,後面的函數都可以根據這個函數演變。具體參考
tf.nn.max_pool
、 tf.nn.max_pool3d
: 最大值池化操作,具體參數可見官方文檔。
tf.nn.avg_pool
、tf.nn.avg_pool3d
:平均值池化操作,具體參數可見官方文檔。
- tf.layers
tf.layers.max_pooling1d
、tf.layers.max_pooling2d
、tf.layers.max_pooling3d
:最大池化操作。
tf.layers.average_pooling1d
、tf.layers.average_pooling2d
、tf.layers.average_pooling3d
:平均池化操作。
- tf.keras
tf.keras.layers.MaxPool1D
、tf.keras.layers.MaxPool2D
、tf.keras.layers.MaxPool3D
: 最大池化操作。
tf.keras.layers.AveragePool1D
、tf.keras.layers.AveragePool2D
、tf.keras.layers.AveragePool3D
: 平均池化操作。
tf.keras.layers.MaxPool1D
、tf.keras.layers.MaxPool2D
、tf.keras.layers.MaxPool3D
: 最大池化操作。
tf.keras.layers.GlobalMaxPool1D
、tf.keras.layers.GlobalMaxPool2D
、tf.keras.layers.GlobalMaxPool3D
: 時域信號的全局最大池化操作。
2.3 Full connect
- tf.nn
tf.nn.xw_plus_b
:利用公式計算全連接層的輸出。需要自己定義weight和bias。底層函數。
tf.nn.relu_layer
: 激活函數為relu的全連接層,nn庫中全連接的函數不多
tf.nn.softmax
: softmax分類層。
tf.nn.softmax_cross_entropy_with_logits
,tf.nn.softmax_cross_entropy_with_logits_v2
:分類層,並利用交叉熵計算label與預測值的loss。
還有一些其他函數,詳見官方文檔。
- tf.layers
tf.layers.dense
:全連接層,參數包含有激活函數等,具體參見官方文檔。在初始化dense函數時,常常利用nn庫中的激活函數。
tf.layers.flatten
:將多維tensor轉變為一維的,以便全連接層進行操作。
- tf.keras
·tf.keras.layers.Dense
:全連接層。
tf.keras.layers.Flatten
:將多維tensor轉變為一維的,以便全連接層進行操作。
tf.keras.layers.LeakyReLU
,tf.keras.layers.PReLU
:這些都是常見激活函數。
2.4 activation
- tf.nn
tf.nn.relu
:最基本的激活函數
tf.nn.relu6
:加入上限的激活函數。參見
tf.nn.crelu
:具體理論參見
Understanding and Improving Convolutional Neural Networks via Concatenated Rectified Linear Units
。
tf.nn.elu
:參見
tf.nn.selu
:推導過程長達102頁paper,作用和BN類似,具體效果還沒有實踐,所以還不能妄下結論。參見 Self-Normalizing Neural
tf.nn.leaky\_relu
:參見
- tf.layers
在layer中,沒有單獨的函數,需要利用tf.nn中的函數配合使用。
- tf.keras
keras的激活函數在tf.keras.activations中,種類與tf.nn中類似。詳見官方文檔。
2.5 initialization
- tf.initializers :參數初始化在單獨的初始化庫中
- tf.keras.initializers :keras庫中的初始化函數與上述類似,只不過集成到了keras庫中。
- tf.layers:在layers庫中也有兩種初始化函數。
tf.contrib.layers.xavier_initializer
,tf.contrib.layers.xavier_initializer_conv2d
:使用sigmoid和tanh,最好使用xavir。
tf.contrib.layers.variance_scaling_initializer
:如果使用relu,則最好使用這個。
2.6 regularization
- tf.nn
tf.nn.dropout
:丟棄層中某些參數,防止過擬合。
- tf.layers
tf.layers.dropout
:同上。
- tf.keras
tf.keras.layers.AlphaDropout
:同上。
2.7 總結
有了上述一些函數,就能構造出常見的網路模型了。在這裡只起到拋磚引玉的作用。以後遇到了其他相關函數還會更新的。
推薦閱讀:
TAG:深度學習(DeepLearning) | TensorFlow | 神經網路 |