CNN

一.卷積神經網絡結構:
1.輸入層:爲輸入的特徵數,如圖像的像素數

2.卷積層:主要結構爲卷積核(過濾器、內核)。一般經過卷積層之後節點矩陣會變得更深
過濾器(作用、尺寸、調整結果矩陣的大小
作用:將當前層神經網絡上的一個子節點矩陣(三維的)轉化爲下一層神經網絡上的一個單位節點矩陣,其中單位節點矩陣指的長和寬都爲1,但深度不限的節點矩陣。
尺寸:長寬人工指定(33,55),處理的矩陣深度和當前神經網絡節點矩陣的深度是一致的,處理後得到的單位節點矩陣的深度稱爲過濾器的深度
如:節點矩陣223 ,單位節點矩陣115,總共需要參數個數:2235+5=65個 其中權重參數爲2235=60個,偏置參數爲5個。一個濾波器的參數是223=12個,共需要5種濾波器,每種濾波器對應一個偏置項。卷積核參數與濾波器尺寸、深度以及當前節點矩陣的深度有關。
結果矩陣的大小(主要確定長寬、深度已經提前指定):受濾波器尺寸大小的影響、步長的影響、以及是否在周邊填充0的影響。
當填充0時,out(length) = in(length)/stride(length)
當不填充0時,out(length) =( in(length)-filter(length)+1)/stride(length)
代碼實現卷積前向傳播過程:

import tensorflow as tf
# shape是四維矩陣,前兩個是卷積核尺寸(長寬),第三個是當前層的深度,第四個是過濾器的深度
filter_weights = tf.get_variable('weights',shape=[5,5,3,16],initializer=tf.truncated_normal_initializer(stddev=0.1))
# 偏置項的維度是下一層的深度,即過濾器的深度
biases = tf.get_variable("biases",shape=[16],initializer=tf.constant_initializer(0.1))
# tf.nn.conv2d實現卷積前向傳播
# input:當前層的節點矩陣——四維矩陣(batch_size,三維節點矩陣);strides:不同維度上的步長,長度爲4的數組,第一維和第四維要是1;
# padding:填充方式,VALID不添加,SAME爲全0填充
conv = tf.nn.conv2d(input=input,filter=filter_weights,strides=[1,1,1,1],padding='SAME')
#給每個節點添加一個偏置項tf.nn.bias_add
bias = tf.nn.bias_add(conv,biases)
# 添加激活函數
actived_conv = tf.nn.relu(bias)

3.池化層:最大池化;平均池化;沒有參數。不改變三維矩陣的深度,只縮小矩陣的大小,減少參數,使得訓練速度加快同時避免過擬合
需設置池化的大小、是否使用全0填充、移動步長
注意:卷積使用的過濾器是橫跨整個深度的,而池化使用的過濾器隻影響一個深度上的節點。池化層的過濾器不僅要在長和寬兩個維度上移動、還要在深度上進行移動
代碼實現最大池化前向傳播過程:

tf.nn.max_pool(actived_conv,ksize=[1,3,3,1],strides=[1,2,2,1],padding='SAME')

4.全連接層:卷積與池化相當於特徵提取過程,使用全連接神經網絡作爲分類

5.輸出層softmax層主要用於分類問題

二.與全連接神經網路不同點

1.全連接神經網絡每一層節點展示爲一列;卷積神經網絡每一層節點展示爲三維矩陣。決定了輸入格式的不一致。全連接神經網絡輸入是向量;而卷積神經網絡的輸入是矩陣(三維數組)。這裏的矩陣是指一個batch的矩陣。
2.前者相鄰兩層節點之間全部互相鏈接,後者局部連接以及參數共享。參數大大減少,同時共享參數使得圖像上的位置不受位置的影響

三.經典卷積神經網絡模型
3.1 卷積神經網絡結構設計通用模式

3.2 LeNet-5模型(99.5%準確率)

輸入層:原始圖像像素 32321

第一層,卷積層。輸入32321,過濾器(55,深度爲6,不使用0填充,步長爲1),輸出尺寸(32-5+1=28)28286。卷積層參數共5516+6=156個,連接個數有28286*(55+1)=122304個。其中下一層節點矩陣有28286=4704個節點,每個節點與55個當前層節點相連,同時有個偏置項

第二層,池化層。輸入:28286。過濾器(22,不使用0填充,步長爲2),輸出尺寸:1414*6

第三層,卷積層。輸入:14146。過濾器(55,深度爲16,不使用0填充,步長爲1),輸出尺寸(14-5+1=10)101016。卷積層參數共55616+16=2416個,連接個數有101016*(5*5+1)=41600個。

第四層:池化層。輸入:101016。過濾器(22,不使用0填充,步長爲2),輸出尺寸:55*16

第五層:全連接層。輸入:5516。過濾器(55,深度爲120,不使用0填充,步長爲1)輸出尺寸:11120 。卷積層參數共5516120+120=48120個,連接個數有11120*(5516+1)=48120個

第六層:全連接層。輸入:120個,輸出84個。參數個數84120+84=10164個,連接個數84(120+1)=10164個

第七層:全連接層。輸入84個,輸出10個。參數個數84*10+10=850個

tensorflow實現:輸入爲一個四維矩陣,全連接神經網絡是一維的。調整輸入數據的格式

# 調整輸入格式
x = tf.placeholder(tf.float32,shape=[batch_size,mnist_inference.image_size,mnist_inference.image_size,mnist_inference.num_channels],name='x-input')
reshaped_xs = np.reshape(xs,(batch_size,mnist_inference.image_size,mnist_inference.image_size,mnist_inference.num_channels))

# 修改前向傳播過程
input_node = 784
output_node = 10

image_size = 28
num_channels = 1
num_labels = 10

# 第一層卷積的尺寸以及深度
conv1_size = 5
conv1_deep = 32
# 第二層卷積的尺寸以及深度
conv2_size = 5
conv2_deep = 64
# 全連接層的節點個數
fc_size = 512
# 添加參數train表示訓練或者測試,同時添加dropout在訓練時使用,只在全連接層使用,而不在卷積或者池化層使用
def inference(input_tensor,train,regularizer):

    with tf.variable_scope("layer1-conv1"):
        conv1_weights = tf.get_variable("weight",[conv1_size,conv1_size,num_channels,conv1_deep],initializer=tf.truncated_normal_initializer(stddev=0.1))
        conv1_biases = tf.get_variable("bias",[conv1_deep],initializer=tf.constant_initializer(0.0))
        conv1 = tf.nn.conv2d(input_tensor,conv1_weights,strides=[1,1,1,1],padding='SAME')
        relu1 = tf.nn.relu(tf.nn.bias_add(conv1,conv1_biases))
        # 輸入:28*28*1 矩陣
        # 輸出:28*28*16 矩陣


    with tf.variable_scope("layer2-pooling1"):
        pooling1 = tf.nn.max_pool(relu1,ksize=[1,2,2,1],strides=[1,2,2,1],padding="SAME")
        # 輸入:28*28*16 矩陣
        # 輸出:14*14*16 矩陣


    with tf.variable_scope("layer3-conv2"):
        conv2_weights = tf.get_variable("weight",shape=[conv2_size,conv2_size,num_channels,conv2_deep],initializer=tf.truncated_normal_initializer(stddev=0.1))
        conv2_biases = tf.get_variable('bias',shape=[conv2_deep],initializer=tf.constant_initializer(0.0))
        conv2 = tf.nn.conv2d(pooling1,conv2_weights,strides=[1,1,1,1],padding="SAME")
        relu2 = tf.nn.relu(tf.nn.bias_add(conv2,conv2_biases))
        # 輸入:14*14*16 矩陣
        # 輸出:14*14*64 矩陣


    with tf.variable_scope("layer4-pooling2"):
        pooling2 = tf.nn.max_pool(input=relu2,ksize=[1,2,2,1],strides=[1,2,2,1],padding="SAME")
        # 輸入:14*14*64 矩陣
        # 輸出:7*7*64 矩陣


    #注意這裏全連接神經網絡的輸入是向量,而第四層池化層的輸出是矩陣,將矩陣中的節點拉直轉化爲向量。其中通過get_shape函數可以得到矩陣的維度,返回的是元組
    # as_list()轉化爲列表
    #只有張量纔可以使用get_shape這種方法,tf.shape()都可以
    pool_shape = pooling2.get_shape().as_list() #四維,第0維是一個batch的數據個數
    nodes = pool_shape[1]+pool_shape[2]+pool_shape[3]
    # 通過tf.reshape函數將第四層的輸出變成一個batch的向量
    reshaped = tf.reshape(pooling2,[pool_shape[0],nodes])
    with tf.variable_scope('layer5-fc'):
        fc1_weights = tf.get_variable("weight",[nodes,fc_size],initializer=tf.truncated_normal_initializer(stddev=0.1))
        if regularizer!=None:
            tf.add_to_collection('losses',regularizer(fc1_weights))
        fc1_biases = tf.get_variable('bias',shape=[fc_size],initializer=tf.constant_initializer(0.1))
        fc1 = tf.nn.relu(tf.matmul(reshaped,fc1_weights)+fc1_biases)
        if train:
            fc1 = tf.nn.dropout(fc1,0.5)
            # 注意:dropout只在全連接層使用,不在卷積層以及池化層使用;同時在訓練過程中使用,在測試過程中不使用
        # 輸入:14*14*64 =3136向量
        # 輸出:512向量


    with tf.variable_scope('layer6-fc2'):
        fc2_weights = tf.get_variable('weight',shape=[fc_size,num_labels],initializer=tf.truncated_normal_initializer(stddev=0.1))
        if regularizer!=None:
            tf.add_to_collection('losses',regularizer(fc2_weights))
        fc2_biases = tf.get_variable('bias',shape=[num_labels],initializer=tf.constant_initializer(0.1))
        fc2 = tf.matmul(fc1,fc2_weights)+fc2_biases
        # 輸入:512向量
        # 輸出:10向量
    return fc2

3.3 Inception 模型

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章