「他山之石,可以攻玉」,站在巨人的肩膀才能看得更高,走得更遠。在科研的道路上,更需藉助東風才能更快前行。為此,我們特別搜集整理了一些實用的代碼連結,數據集,軟體,編程技巧等,開闢「他山之石」專欄,助你乘風破浪,一路奮勇向前,敬請關注。
地址:https://blog.csdn.net/hurry0808
本文以CIFAR-10(https://www.cs.toronto.edu/~kriz/cifar.html)為數據集,基於Tensorflow介紹了CNN(卷積神經網絡)圖像分類模型的構建過程,著重分析了在建模過程中卷積層、池化層、扁平化層、全連接層、輸出層的運算機理,以及經過運算後圖像尺寸、數據維度等參數的變化情況。01
02
tf.nn.conv2d( input, filter, strides, padding, use_cudnn_on_gpu=True, data_format='NHWC', dilations=[1, 1, 1, 1], name=None)input:需要做卷積的輸入圖像,它要求是一個Tensor,shape為[batch, in_height, in_width, in_channels],具體含義是[訓練時一個batch的圖片數量, 圖片高度, 圖片寬度, 圖像通道數],注意這是一個4維的Tensor,要求類型為float32和float64其中之一;filter:相當於CNN中的卷積核,它要求是一個Tensor,shape為[filter_height, filter_width, in_channels, out_channels],具體含義是[卷積核的高度,卷積核的寬度,圖像通道數,卷積核個數],要求類型與參數input相同,filter的通道數要求與input的in_channels一致,有一個地方需要注意,第三維in_channels,就是參數input的第四維;strides:卷積時在圖像每一維的步長,這是一個一維的向量,長度4,strides[0]=strides[3]=1;padding:string類型的量,只能是」SAME」、」VALID」其中之一,這個值決定了不同的卷積方式;卷積運算時卷積核滑動過程中當輸入圖像(input)的in_height、in_width不是filter的filter_height、filter_width的整數倍時,」SAME」方式是在input周圍填充0以將其in_height、in_width補充為filter相應部分的整數倍,」VALID」方式將input的多餘部分丟棄,詳細介紹請參看這裡;use_cudnn_on_gpu:bool類型,是否使用cudnn加速,默認為true;data_format:指定輸入數據、輸出數據的格式,取值為」NHWC」、」NCHW」,前者對應於 [batch, height, width, channels],後者對應於 [batch, channels, height, width],默認為』NHWC』。dilations:一個可選的ints列表;默認為[1,1,1,1]。長度為4的一維張量,每個input維度的膨脹係數;如果設置為k> 1,則每個該維度上的過濾器元素之間會有k-1個跳過的單元格;維度順序由data_format的值決定;在Dilations中批次和深度尺寸必須為1;返回值:Tensor,也就是我們常說的feature map。輸入圖像經過卷積運算後,其高度、寬度變為——
『SAME』 類型的padding,其輸出的height和width計算如下:
out_height = ceil(float(in_height) / float(strides[1])) ceil:向上取整
out_width = ceil(float(in_width) / float(strides[2]))『VALID』類型的padding, 其輸出的height和width計算如下:
out_height = ceil(float(in_height – filter_height + 1) / float(strides[1]))
out_width = ceil(float(in_width – filter_width + 1) / float(strides[2]))驗證該函數的文章,請看這裡(https://blog.csdn.net/u012609509/article/details/71215859)。激活函數(Activation Function)池化層、全連接層等通過線性運算構建的是線性模型,該模型的表達能力有限;激活函數能夠加入非線性因素,從而使模型的表達能力得到極大提升。常用的激活函數有Tanh函數 、ReLU函數 、Leaky ReLU函數 、Maxout函數 等,本文使用ReLU函數作為激活函數。
Tensorflow中的relu激活函數為:tf.nn.relu( features, name=None)features: 張量,必須為以下類型中的一種:float32, float64, int32, uint8, int16, int8, int64, bfloat16, uint16, half, uint32, uint64;池化(Pooling)層池化層與卷積層的作用、計算方法類似,也有池化filter、步長、填充方式等參數,所不同的是,池化計算比較簡單,常取filter覆蓋部分的最大值、或者均值,分別稱之為最大池化、平均池化,最大池化的示意圖如下所示:
最大池化的filter shape為(2,2), 步長也為(2,2),每個filter滑動覆蓋處取最大值,得到右側所示的結果。
Tensorflow實現最大池化運算的函數為:tf.nn.max_pool( value, ksize, strides, padding, data_format='NHWC', name=None)value:輸入4D張量, 其格式由data_format指定;ksize:含有4個元素的1D張量,指定池化核的尺寸;strides:含有4個元素的1D int 張量,指定池化時在圖像每一維的步長,strides[0]=strides[3]=1;padding:邊界填充方式,string類型的量,只能是」SAME」、」VALID」其中之一;data_format:數據格式,string類型的量, 只能是』NHWC』、 『NCHW』 、』NCHW_VECT_C』 其中之一;返回值:Tensor,也就是我們常說的feature map。上層feature map經池化運算後,其batch、channels均不發生變化,只有height、width會發生變化,輸出height、width計算方式同卷積層。扁平化(Flatten)層將上一層得到的全部feature map拉直成列向量,作為全連接網絡的輸入。拉直方式為height*width*channels。
Tensorflow實現扁平化層運算的函數為:tf.contrib.layers.flatten( inputs, outputs_collections=None, scope=None)inputs:形如 [batch_size, …]的張量,注意張量的第1個元素必須為batch_size;outputs_collections:添加到輸出的集合;返回值:形如[batch_size, k]的扁平化張量。圖像分類模型訓練完成後,本層返回張量的shape(主要是k)就確定了,從而限定了模型預測時輸入圖像的尺寸——因為在模型確定的情況下,卷積層、池化層等結構、數量均不再改變,預測圖像與訓練圖像尺寸一致時,經卷積、池化等運算後,扁平化輸出shape與模型一致;預測圖像與訓練圖像尺寸不一致時,經卷積、池化等運算後,扁平化輸出的shape與模型不一致,從而無法繼續運算。這也是遷移學習時,預訓練模型均約定輸入圖像height、width的原因。從該層開始,分類模型的網絡結構類似於「多層前饋神經網絡」。全連接(Fully Connected)層全連接層在整個卷積神經網絡中起到「分類器」的作用、也是模型表示能力的「防火牆」。全連接層的運算形如X*W+b,X*W為矩陣乘法,其中X為輸入2維數組(shape為[batch_size, k]),W為權重2維數組(shape為[k,out_k]),b為偏置,W的第2個元素(out_k)決定了全連接層運算後輸出的2維數組形狀(shape為[batch_size, out_k])。
由於全連接層參數冗餘(僅全連接層參數就可佔整個網絡參數80%左右),需要使用tf.nn.dropout來隨機丟棄一些節點,或者使用一些性能優異的網絡模型如ResNet和GoogLeNet等來取代全連接層融合學到的深度特徵。tf.layers.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)units: Integer or Long, dimensionality of the output space.activation: Activation function (callable). Set it to None to maintain a linear activation.use_bias: Boolean, whether the layer uses a bias.kernel_initializer: Initializer function for the weight matrix. If None (default), weights are initialized using the default initializer used by tf.get_variable.bias_initializer: Initializer function for the bias.kernel_regularizer: Regularizer function for the weight matrix.bias_regularizer: Regularizer function for the bias.activity_regularizer: Regularizer function for the output.kernel_constraint: An optional projection function to be applied to the kernel after being updated by an Optimizer (e.g. used to implement norm constraints or value constraints for layer weights). The function must take as input the unprojected variable and must return the projected variable (which must have the same shape). Constraints are not safe to use when doing asynchronous distributed training.bias_constraint: An optional projection function to be applied to the bias after being updated by an Optimizer.trainable: Boolean, if True also add variables to the graph collection GraphKeys.TRAINABLE_VARIABLES (see tf.Variable).name: String, the name of the layer.reuse: Boolean, whether to reuse the weights of a previous layer by the same name.Returns:Output tensor the same shape as inputs except the last dimension is of size units.tf.nn.dropout( x, keep_prob, noise_shape=None, seed=None, name=None)x: A floating point tensor.keep_prob: A scalar Tensor with the same type as x. The probability that each element is kept.noise_shape: A 1-D Tensor of type int32, representing the shape for randomly generated keep/drop flags.seed: A Python integer. Used to create random seeds. See tf.set_random_seed for behavior.name: A name for this operation (optional).Returns: A Tensor of the same shape of x.輸出(Output)層輸出層運算與全連接層類似,只是在設定運算參數時輸出節點數量需與分類標記數量相一致,並且在運算完成後再使用tf.nn.softmax函數,得到測試圖像屬於各分類的概率,該所有概率值之和為1。
Tensorflow中的tf.nn.softmax函數如下所示:tf.nn.softmax( logits, axis=None, name=None, dim=None)logits: A non-empty Tensor. Must be one of the following types: half, float32, float64.axis: The dimension softmax would be performed on. The default is -1 which indicates the last dimension.name: A name for the operation (optional).dim: Deprecated alias for axis.Returns: A Tensor. Has the same type and shape as logits.訓練得到分類模型按照輸入層、卷積層與池化層(共3層)、扁平化層、全連接層(共3層)、輸出層的順序搭建好模型,以交叉熵均值作為cost,以Adam優化算法尋找全局最優點,以cost、Accuracy(分類準確率)作為評估模型的指標,各層參數設置如下圖所示:
batch為訓練時每批輸入的圖像數量,視訓練環境的硬體配置而定,本文設置為512訓練構建好的CNN圖像分類模型時,單張圖片用3D數組表示,多張圖片用4D數組表示,經過卷積、激活函數、池化、扁平化、全連接、Dropout等運算,其batch、height、width、channels、feature map數量、節點數量、數據shape有的會發生變化,有的不會發生變化,如下表所示:使用CIFAR-10訓練集進行訓練,在訓練集和測試集上的準確率均為0.73,如下圖所示:03
本文以CIFAR-10數據集為例,使用Tensorflow構建了簡單的CNN圖像分類模型,該模型包含輸入層、卷積與池化層、扁平化層、全連接層、輸出層,這些層均是構建CNN分類模型必要且重要的層;訓練後分類模型的準確率雖然不夠高,但本文重在分析各層運算時圖像數據shape的變化及其它尺寸數據的改變情況。本文目的在於學術交流,並不代表本公眾號贊同其觀點或對其內容真實性負責,版權歸原作者所有,如有侵權請告知刪除。
更多他山之石專欄文章,請點擊文章底部「閱讀原文」查看分享、點讚、在看,給個三連擊唄!