tensorflow卷積神經網絡與手寫字識別


1、知識點

 

"""
基礎知識:
    1、神經網絡(neural networks)的基本組成包括輸入層、隱藏層、輸出層。而卷積神經網絡的特點在於隱藏層分為卷積層和池化層(pooling layer,又叫下采樣層)
    2、卷積層:通過在原始圖像上平移來提取特征,每一個特征就是一個特征映射
            a)提取特征:定義一個過濾器(也稱觀察窗口,奇數大小,值為權重)大小,步長
            b)移動越過圖片:
                1、VALID:不越過,直接停止觀察(一般不用)
                2、SAME:直接越過,則對圖像零填充(padding過程)
        影響因素:窗口大小,步長,零填充,窗口數目
        
        矩陣大小公式計算:
            輸入體積大小:H1*W1*D1
            四個超參數:Filter數量K、Filter大小F、步長S、零填充大小P
            輸出體積大小 H2*W2*D2
                H2=(H1-F+2P)/S+1 #如果有小數,要注意
                W2=(W1-F+2P)/S+1
                D2=K
                
        卷積API:tf.nn.conv2d(input, filter, strides=, padding=, name=None)計算給定4-D input和filter張量的2維卷積
                input:給定的輸入張量,具有[batch,heigth,width,channel],類型為float32,64  ,channel為圖片的通道數,batch為圖片的數量
                filter:指定過濾器的大小,[filter_height, filter_width, in_channels, out_channels] ,其中,in_channels=channel ,out_channels為過濾器的數量
                strides:strides = [1, stride, stride, 1],步長
                padding:“SAME”, “VALID”,使用的填充算法的類型,使用“SAME”。其中”VALID”表示滑動超出部分舍棄,“SAME”表示填充,使得變化后height,width一樣大

    3、激活函數(Relu),增加激活函數相當於增加了網絡的非線性分割能力 
        1、機器學習使用:sigmoid ,公式:f(x) = 1/1+e^(-x)
        2、深度學習使用:Relu ,公式為:f(x) = max(0,x)  
        3、API:tf.nn.relu(features, name=None)
                features:卷積后加上偏置的結果
                return:結果
  
    4、池化層:通過特征后稀疏參數來減少學習的參數,降低網絡的復雜度,(最大池化和平均池化)
        1、池化計算矩陣大小公式和卷積一樣
        2、API:tf.nn.max_pool(value, ksize=, strides=, padding=,name=None)輸入上執行最大池數
                value:4-D Tensor形狀[batch, height, width, channels]
                ksize:池化窗口大小,[1, ksize, ksize, 1]
                strides:步長大小,[1,strides,strides,1]
                padding:“SAME”, “VALID”,使用的填充算法的類型,使用“SAME”

    5、dropout:防止過擬合,直接使一些數據失效,小型網絡用不到

6、不采用sigmoid函數作為激活函數的原因?
      第一、采用sigmoid等函數,反向傳播求取誤差梯度時,計算量相對大,而采用Relu激活函數,震哥哥過程的計算節省很多
      第二、對於深層網絡,sigmoid函數反向傳播時,很容易就會出現梯度消失等情況

 

    7、tf.one_hot(indices,depth)
                indices:數據集標簽
                depth:類別數
                
卷積神經網絡實現流程:
                    1、准備數據
                    2、建立模型
                        a)准備數據占位符
                        b)卷積、激活、池化操作
                        c)全連接層,建立矩陣表達式
                    3、計算交叉熵損失
                    4、梯度下降求出損失
                    5、計算准確率
                    6、初始化變量
                    7、開始訓練

手寫字網絡結構設計:
    輸入數據:[None,784]   [None.10]
    一卷積層:
            卷積:32個filer,5*5 ,strides=1,padding="SAME" ,輸入:[None,28,28,1] 輸出:[None,28,28,32] 
            激活:輸出 [None,28,28,32]
            池化:2*2,strides=2,padding="SAME" 輸出 [None,14,14,32]
    二卷積層:
            卷積:64個filer,5*5 ,strides=1,padding="SAME" ,輸入:[None,14,14,32] 輸出:[None,14,14,64]
            激活:輸出 [None,14,14,64]
            池化: 2*2,strides=2 ,輸出:[None,7,7,64]
    全連接層:
            形狀改變:[None,7,7,64] -->[None,7*7*64]
            權重:[7*7*10]
            偏置:[10]
            輸出:[None,10]  
  輸出:[3,5,7]  -->softmax轉為概率[0.04,0.16,0.8] ---> 交叉熵計算損失值 (目標值和預測值的對數) 
"""

 

2、代碼

# coding = utf-8
import  tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

#定義一個初始化權重的函數
def weight_variables(shape):
    w = tf.Variable(tf.random_normal(shape=shape,mean=0.0,stddev=1.0))
    return w

#定義一個初始化偏置的函數
def bais_variables(shape):
    b = tf.Variable(tf.constant(0.0,shape=shape))
    return b

def model():
    """
    自定義卷積模型
    :return:
    """
    #1、准備數據的占位符 x[None,784] y_true[None,10]
    with tf.variable_scope("data"):
        x = tf.placeholder(tf.float32,[None,784])
        y_true = tf.placeholder(tf.int32,[None,10])

    #2、一卷積層 卷積: 5*5*1,32個,strides=1 激活: tf.nn.relu 池化
    with tf.variable_scope("conv1"):
        #隨機初始化權重,[5,5,1,32]--->5,5為過濾器大小,1為輸入的圖像通道數,32為過濾器的數量
        w_conv1 = weight_variables([5,5,1,32])
        b_conv1 =bais_variables([32])
        #對x進行形狀的改變[None,784] --->[None,28,28,1]
        # 改變形狀,不知道的參數填寫-1
        x_reshape= tf.reshape(x,[-1,28,28,1])

        #strides=[1,1,1,1],表示上下左右移動步長都為1  [None, 28, 28, 1]-----> [None, 28, 28, 32]
        x_relu1 = tf.nn.relu(tf.nn.conv2d(x_reshape,w_conv1,strides=[1,1,1,1],padding="SAME")+b_conv1)

        #池化  2*2 ,strides2 [None, 28, 28, 32]---->[None, 14, 14, 32]
        x_pool1 = tf.nn.max_pool(x_relu1,ksize=[1,2,2,1],strides=[1,2,2,1],padding="SAME")


    #3、二卷積層
    with tf.variable_scope("conv2"):
        # 隨機初始化權重,  權重:[5, 5, 32, 64]  偏置[64]
        w_conv2 = weight_variables([5, 5, 32, 64])
        b_conv2 = bais_variables([64])

        # 卷積,激活,池化計算
        # [None, 14, 14, 32]-----> [None, 14, 14, 64]
        x_relu2 = tf.nn.relu(tf.nn.conv2d(x_pool1,w_conv2,strides=[1,1,1,1],padding="SAME")+b_conv2)

        # 池化 2*2, strides 2, [None, 14, 14, 64]---->[None, 7, 7, 64]
        x_pool2 =tf.nn.max_pool(x_relu2,ksize=[1,2,2,1],strides=[1,2,2,1],padding="SAME")

    #4、全連接層  [None, 7, 7, 64]--->[None, 7*7*64]*[7*7*64, 10]+ [10] =[None, 10]
    with tf.variable_scope("conv2"):
        # 隨機初始化權重,
        w_fc = weight_variables([7*7*64, 10])
        b_fc = bais_variables([10])

        #修改形狀[None, 7, 7, 64] --->None, 7*7*64]
        x_fc_reshape = tf.reshape(x_pool2,[-1,7*7*64])
        #進行矩陣運算,得出每個樣本的10個結果
        y_predict = tf.matmul(x_fc_reshape,w_fc)+b_fc

    ######收集和合並變量####
    tf.summary.histogram("w1",w_conv1)
    tf.summary.histogram("b1",b_conv1)
    tf.summary.histogram("w2",w_conv2)
    tf.summary.histogram("b2",b_conv2)
    tf.summary.histogram("wfc",w_conv1)
    tf.summary.histogram("bfc",b_conv1)

    merged =tf.summary.merge_all()

    return  x,y_true,y_predict,merged

def conv_fc():
    # 獲取數據
    minist = input_data.read_data_sets("./data/mnist/input_data/", one_hot=True)
    x,y_true,y_predict,merged = model()

    # 3、計算交叉熵損失
    with tf.variable_scope("cross_entropy"):
        # 求取平均交叉熵損失
        loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=y_predict))

    # 4、梯度下降求出損失
    with tf.variable_scope("optimizer"):
        train_op = tf.train.GradientDescentOptimizer(0.0001).minimize(loss)

    # 5、計算准確率
    with tf.variable_scope("accuracy"):
        equal_list = tf.equal(tf.argmax(y_true, 1), tf.argmax(y_predict, 1))
        # equal_list  None個樣本 [1,0,1,1,0,0,0......]
        accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32))

    # 7、初始化變量
    init_op = tf.global_variables_initializer()

    ##########收集變量#############
    tf.summary.scalar("losses",loss)
    tf.summary.scalar("accuracy",accuracy)
    merged1 = tf.summary.merge_all()
    with tf.Session() as sess:
        sess.run(init_op)
        fileWriter = tf.summary.FileWriter("./event/",graph=sess.graph)
        for i in range(1000):
            # 取出數據的特征自和目標值
            mnist_x, mnist_y = minist.train.next_batch(50)
            # 訓練
            sess.run(train_op, feed_dict={x: mnist_x, y_true: mnist_y})

            summary = sess.run(merged,feed_dict={x: mnist_x, y_true:mnist_y})
            summary1 = sess.run(merged1, feed_dict={x: mnist_x, y_true: mnist_y})
            fileWriter.add_summary(summary,i)
            fileWriter.add_summary(summary1, i)

            print("訓練第%d步,准確率為:%f" % (i, sess.run(accuracy, feed_dict={x: mnist_x, y_true: mnist_y})))

    return None

if __name__ == "__main__":
    conv_fc()

3、發展歷程

4、卷積與池化輸出矩陣維度計算公式

 5、損失計算-交叉熵損失公式

6、SoftMax回歸計算公式

7、激活函數-Relu

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM