1. 程式人生 > >tf.nn.conv2d函式、padding型別SAME和VALID、tf.nn.max_pool函式、tf.nn.dropout函式、tf.nn.softmax函式、tf.reduce_sum函式

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引數時,預設對矩陣所有元素進行求和。