tf.nn.conv2d函式、padding型別SAME和VALID、tf.nn.max_pool函式、tf.nn.dropout函式、tf.nn.softmax函式、tf.reduce_sum函式
tf.nn.conv2d函式:
該函式是TensorFlow裡面實現卷積的函式。
函式形式:
tf.nn.conv2d (input, filter, strides, padding, use_cudnn_on_gpu=None, data_format=None, name=None)
引數:
input : 要卷積的輸入影象,要求為一個張量,shape為 [ batch, in_height, in_weight, in_channel ],batch為樣本的數量,in_height 為圖片高度,in_weight 為圖片寬度,in_channel 為圖片的通道數,灰度圖該值為1,彩色圖為3;
filter: 卷積核,要求也是一個張量,shape為 [ filter_height, filter_weight, in_channel, out_channels ],filter_height 為卷積核高度,filter_weight 為卷積核寬度,in_channel 是影象通道數 ,和 input中in_channel 要保持一致,out_channel 是卷積核數量;
strides: 卷積時在影象每一維的步長,這是一個一維的向量,[ 1, strides, strides, 1],第一位和最後一位固定必須是1;
padding: string型別,可以為“SAME” 或 “VALID”,表示的是卷積的形式,是否考慮邊界。”SAME”是考慮邊界,不足的時候用0去填充周圍,”VALID”則不考慮;
use_cudnn_on_gpu: bool型別,是否使用cudnn加速,預設為true。
該函式的返回值是一個tensor,也就是我們CNN神經網路中通常所說的feature map,其形式為[batch,height,width,channels]。
卷積核大小通常為奇數,一方面是為了方便same卷積padding對稱填充,左右兩邊對稱補零; 另一方面,奇數過濾器有中心畫素,便於確定過濾器的位置。
卷積過程圖解如下:
如上圖所示,上面有兩個卷積核w0和w1,輸入影象為5X5X3,卷積核大小為3X3X3,padding=‘SAME’,影象四條邊各填充一列0。步長為2.
以w0卷積核卷積得到的feature map(右上角綠色矩陣)為例,左上角的-3計算過程為:
從上到下三個藍色矩陣中的對應位置元素與filter的從上到下三個紅色矩陣中的對應位置元素相乘並相加,得到的和最後加上bias(值為1),結果為0+(-4)+0+1=-3。
當藍色矩陣按步長把經過padding後的影象全部掃過一遍後即形成了3X3的feature map矩陣。
舉例:
import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
input = tf.constant([[[[1], [2], [3]], [[4], [5], [6]], [[7], [8], [9]]]], dtype=tf.float32)
filter = tf.constant([[[[1]], [[2]]], [[[3]], [[4]]]], dtype=tf.float32)
op = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='SAME')
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(sess.run(op))
構建的輸入影象矩陣、過濾器矩陣、輸出矩陣即:
執行結果如下:
[[[[37.]
[47.]
[21.]]
[[67.]
[77.]
[33.]]
[[23.]
[26.]
[ 9.]]]]
Process finished with exit code 0
padding型別SAME和VALID:
SAME和VALID的區別就是,當卷積核掃到影象邊緣時,如果剩餘的影象資料不夠卷積核的大小(比如說步長為2,輸入影象5X5X3,卷積核3X3X3,那麼第3次計算時影象的資料就缺了一列),VALID資料會直接捨棄這部分影象資料,SAME則會填充相應列的資料(填充值為0),使得在邊緣的這次計算可以正常進行。
padding中VALID和SAME模式下計算輸出形狀的公式:
我們設計網路結構時需要設定輸入輸出的shape,原始碼nn_ops.py中的convolution函式和pool函式給出的計算公式如下:
dilation_rate即擴張率是一個可選的引數,預設為1,這裡我們先不管。
If padding == "SAME":
output_spatial_shape[i] = ceil(input_spatial_shape[i] / strides[i])
If padding == "VALID":
output_spatial_shape[i] =ceil((input_spatial_shape[i] -(spatial_filter_shape[i]-1) * dilation_rate[i])/ strides[i]).
對於VALID
,輸出的形狀計算如下:
對於SAME
,輸出的形狀計算如下:
其中,W為輸入的size,F為filter的size,S為步長,⌈⌉為向上取整符號。
tf.nn.max_pool函式:
函式形式:
tf.nn.max_pool(value, ksize, strides, padding, name=None)
引數:
value:池化的輸入,一般池化層接在卷積層後面,所以輸入通常是feature map,依然是[batch, height, width, channels]這樣的shape;
ksize:池化視窗的大小,取一個四維向量,一般是[1, height, width, 1],因為我們不想在
batch和
channels
上做池化,所以這兩個維度設為了1
strides:和卷積類似,視窗在每一個維度上滑動的步長,一般也是[1, stride,
stride
, 1]
padding:和卷積類似,可以取'VALID' 或者'SAME'
返回一個Tensor,型別不變,shape仍然是[batch, height, width, channels]
這種形式。batch是樣本數量,height代表影象高度,width代表影象寬度,channels代表顏色通道數。
特徵圖的行列數計算公式:
對於n*n的矩陣, 使用 f*f 的池化視窗進行池化, 填充寬度為p, 若縱向步長為s1, 橫向步長為s2,則feature map的尺寸為:
如:
tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
假設輸入影象為14X14X64,按上式池化視窗是2X2,則不需要填充,步長在長和寬兩個維度上都是2,則輸出的feature map尺寸為:
((14+2*0-2)/2+1)*((14+2*0-2)/2+1)=7X7X64(第三個維度不變)
舉例:
import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
def weight_variable(shape):
inital = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(inital)
def max_poo_2x2(x):
return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
h_conv1 = weight_variable([1, 14, 14, 1])
h_pool1 = max_poo_2x2(h_conv1)
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(h_pool1.shape)
print(sess.run(h_pool1))
執行結果如下:
(1, 7, 7, 1)
[[[[ 0.13548833]
[ 0.04882993]
[ 0.03586724]
[ 0.09933105]
[ 0.12503038]
[ 0.15395918]
[ 0.07306405]]
[[ 0.12927686]
[ 0.16856574]
[ 0.07078061]
[ 0.18828133]
[ 0.06061553]
[ 0.11684693]
[ 0.13043709]]
[[ 0.19111353]
[-0.02194273]
[ 0.0637873 ]
[ 0.04148081]
[ 0.10959595]
[ 0.1541184 ]
[ 0.06407266]]
[[ 0.04700654]
[ 0.10226708]
[ 0.16536988]
[ 0.05383656]
[-0.04101967]
[ 0.02647119]
[ 0.14546566]]
[[ 0.11602601]
[ 0.0328348 ]
[ 0.14823155]
[ 0.11772271]
[ 0.0644576 ]
[ 0.08589904]
[ 0.14601949]]
[[ 0.0338777 ]
[ 0.14439887]
[ 0.15381582]
[ 0.02794546]
[-0.0324116 ]
[ 0.12839405]
[ 0.10431063]]
[[ 0.10118591]
[ 0.02967534]
[ 0.06684441]
[ 0.11368319]
[ 0.19176225]
[ 0.06180626]
[ 0.0503093 ]]]]
Process finished with exit code 0
可以看到池化前輸入的矩陣尺寸為14X14X1,池化後矩陣的尺寸變成了7X7X1。
tf.nn.dropout函式:
tf.nn.dropout是TensorFlow裡面為了防止或減輕過擬合而使用的函式,它一般用在全連線層。Dropout就是在不同的訓練過程中隨機扔掉一部分神經元。也就是讓某個神經元的啟用值以一定的概率p,讓其停止工作,這次訓練過程中不更新權值,也不參加神經網路的計算。但是它的權重得保留下來(只是暫時不更新而已),因為下次樣本輸入時它可能又得工作了。
在tensorflow中,使用dropout函式後每個神經元仍然都要參加運算,但其輸出要乘以概率p。
函式形式:
tf.nn.dropout(x, keep_prob, noise_shape=None, seed=None,name=None)
引數:
x:輸入的tensor張量;
keep_prob:float型別,每個元素被保留下來的概率,取值為0到1;
noise_shape:一個1維的int32張量,代表了隨機產生“保留/丟棄”標誌的shape;
seed:整形變數,隨機數種子;
name :名字。
tf.nn.softmax函式:
Softmax函式,又叫歸一化指數函式,是邏輯函式的一種推廣。它能將一個含任意實數的K維向量Z“壓縮”到另一個K維實向量
中,使得每一個元素的範圍都在 之間,並且所有元素的和為1。
函式的形式:
其中, j = 1, …, K。
假設我們有一個數組,V,Vi表示V中的第i個元素,那麼這個元素的softmax值就是
通過Softmax函式可以將logistic的預測二分類的概率的問題推廣到n分類的概率問題。
tf.nn.softmax()函式形式:
tf.nn.softmax(logits,axis=None,name=None,dim=None)
這個函式的作用相當於:
softmax = tf.exp(logits) / tf.reduce_sum(tf.exp(logits), axis)
引數:
logits:一個非空張量,必須是以下型別之一:half, float32, float64。
axis:將被執行的softmax維度,預設值是-1,表示最後一個維度。
name:操作的名稱(可選)。
dim:棄用,axis的別名。
舉例:
import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
A = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
with tf.Session() as sess:
print(sess.run(tf.nn.softmax(A)))
執行結果如下:
[0.00426978 0.01160646 0.03154963 0.08576079 0.233122 0.6336913 ]
Process finished with exit code 0
tf.reduce_sum函式:
tf.reduce_sum函式將矩陣的元素相加,可以按列,也可以按行,或者先按列後按行,相加完以後壓縮一個維度。比如按行相加,則不管之前有多少列,加完以後就只剩下一列了。
reduce就是“對矩陣降維”的含義,下劃線後面的部分就是降維的方式,在reduce_sum()中就是按照求和的方式對矩陣降維。
函式形式:
reduce_sum( input_tensor, axis=None, keep_dims=False, name=None, reduction_indices=None )
input_tensor:表示輸入的張量;
axis:表示在哪個維度進行sum操作;
keep_dims:表示是否保留原始資料的維度,False相當於執行完後原始資料就會少一個維度;
reduction_indices:為了跟舊版本的相容,現在可以不用了。
如:
如上圖,當呼叫reduce_sum(arg1, arg2)時,引數arg1即為要求和的矩陣,arg2有兩個取值reduction_indices=[0]或reduction_indices=[1]。從上圖可以看出,當arg2 = 0時,是按列相加,原來矩陣有幾列就得到幾個值,行沒有了;相似地,當arg2 = 1時,是按行相加;當省略arg2引數時,預設對矩陣所有元素進行求和。