TF中的單神經網絡——利用感知器解決mnist識別

Mnist數據集介紹以及載入

  1. mnist手寫數據集,共55000個訓練樣本,5000個驗證樣本以及10000個測試樣本
  2. import tensorflow as tf
    import tensorflow.examples.tutorials.mnist.input_data as input_data
    import matplotlib.pyplot as plt
    import numpy as np
    # 數據載入
    mnist = input_data.read_data_sets("MNIST/", one_hot=True)  # 以獨熱編碼的形式載入數據
    # 訓練集訓練數據,驗證集評估調參,測試集進行最後的測試
    print("訓練集數量: ", mnist.train.num_examples)
    print("驗證集數量: ", mnist.validation.num_examples)
    print("測試集數量: ", mnist.test.num_examples)
    
    # 可以解開註釋,看裏面的數據形式
    # print("圖像形狀:", mnist.train.images.shape)  # 784即28X28
    # print("標籤形狀:", mnist.train.labels.shape)
    # print("首圖尺寸:", mnist.train.images[0].shape)
    # print("首圖內容:", mnist.train.images[0].reshape(28, 28))
    載入代碼可如上所述,即利用tf中的mnist模塊,利用其中的read_data_sets方法,並注意讀取數據時以獨熱編碼的形式讀入;上述代碼中還有一些打印信息,用以顯示相關數據維度尺寸,具體見註釋。
  3. 對於獨熱編碼的解釋:所謂獨熱編碼就是以數組的形式編碼,並且此數組中有且只有一個1,其餘值均爲0;可以利用這句代碼print(mnist.labels[1])打印實現,在mnits數據集中,若以獨熱編碼載入數據時,標籤值將會是一個獨熱的一維數組;由於mnist識別時,判斷準確程度是基於類似於歐式距離的思路,所以使用獨熱編碼更易於計算差異。

數據集的劃分

構建模型並進行訓練的最終目的是,可以對於未知的數據進行儘可能準確地預測;爲保證有效的預測,需將數據集分成數據集、測試集、驗證集。

整體的訓練爲:

並且,爲保證測試集上的效果可以很好的擬合對於位置數據的驗證效果,就要求:測試集數目夠大以及不到最後模型不要接觸測試集,並且測試集與訓練集要對於數據的整體上的分佈描述一致。

在mnist數據集中,官方已經劃分好了訓練集、測試集以及驗證集。

批量讀取數據

  1. 可利用python中的切片語句,實現數據的批量提取;如print(mnist.train.labels[0:10]),來批量打印顯示索引0到9的樣本對應的標籤值。
  2. mnist數據包,在tf中,提供了一個可以批量讀入數據的方法,
    # mnist中提供了下述方法,可以進行批量讀取數據
    batch_images_xs, batch_labels_ys = mnist.train.next_batch(batch_size=10)
    print(batch_images_xs.shape, batch_images_ys.shape)
    即next_batch;其參數包爲讀入數據的量(batch_size),返回值包括圖像集合與對應的標籤集合;通過打印語句,得到的圖像集合的維度爲[10,784],標籤集合的維度爲[10,10]。

構建模型

  1. x = tf.placeholder(tf.float32, [None, 784], name="X")
    y = tf.placeholder(tf.float32, [None, 10], name="Y")
    w = tf.Variable(tf.random_normal([784, 10]), name="W")
    b = tf.Variable(tf.zeros([10]), name="b")
    forward = tf.matmul(x, w)+b  # 前向計算
    preb = tf.nn.softmax(forward)  # 利用softmax進行結果向概率域的映射
    定義輸入、權重以及前向計算。對於輸入的維度,只限定尺寸不限定數目,用NONE進行佔位,便於與批量讀取數據配合;權重w一邊隨機初始化,但注意維度要對應,即可與x做矩陣乘法,b一般直接初始化爲0;前向計算就是定義了一個矩陣乘法在加上偏移量的計算過程,對於計算後的結果要使用softmax將計算值映射到概率域,這種映射在cnn中也經常使用,多用於最後一個FC層。
  2. 對於softmax補充說明:此方法對應於計算得到的各類標籤的得分值大小,對應的賦予一個概率值,使得總的概率值之和爲1,得分高的類別對應的概率值大,具體公式爲P_{i} = \frac{e^{^{y_{i}}}}{\sum_{k=1}^{C}e^{y_{k}}},其中C表示類數。
  3. # 超參設置
    train_epochs = 50  # 訓練輪數
    batch_size = 100  # 單批次訓練樣本數
    total_batch = int(mnist.train.num_examples/batch_size)  # 一輪訓練要訓練的批次數
    learing_rate = 0.01  # 學習率
    display_step = 1  # 顯示粒度
    定義超參數,如上所示。設置一次讀100個樣本做單次訓練,一輪訓練要做total_batch次的單次訓練,總共要訓練50輪。
  4. # 定義損失函數
    # 交叉熵損失函數
    loss_fuction = tf.reduce_mean(-tf.reduce_sum(y*tf.log(preb), reduction_indices=1))
    設定損失函數,對於多分類問題,常使用交叉熵損失函數;交叉熵本來是在信息領域比較概率的近似程度,在使用獨熱編碼後,對於softmax映射的計算結果與標籤值之間的差異,就是概率差異;交叉熵的計算公式爲H(p,q) = -\sum p(x)log(q(x))),其中p是標籤值,q是經softmax映射後的計算值,二者越接近,交叉熵值越小。
  5. # 優化器
    optimizer = tf.train.GradientDescentOptimizer(learing_rate).minimize(loss_fuction)
    定義優化;仍使用梯度下降算法,多分類問題使用L2算法做loss_function的時候,梯度下降算法可能會陷入局部極小,而使用交叉損失將避免這一問題。
  6. # 定義準確率
    correct_prediction = tf.equal(tf.argmax(preb, 1), tf.argmax(y, 1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    定義準確率操作,即計算一次訓練中的正確率;correct_prediction表示,首先預測值集合與標籤值集合分佈逐行取最大值所在的索引,因爲一行對應一個樣本,之後諸項比較得到的索引值,相同True否則False;accuracy是將True與False集合轉化爲float32類型,在將所有元素求均值,均值結果即爲準確率。

訓練與評估模型

  1. # 聲明會話以及初始化變量
    sess = tf.Session()
    init = tf.global_variables_initializer()
    sess.run(init)
    
    # 開始訓練
    print("Train Start !!!!!")
    for epoch in range(train_epochs):  # 逐輪次
        for batch_size in range(total_batch):  # 共進行total_batch次的單一批次訓練
            xs, ys = mnist.train.next_batch(batch_size)  # zip數據送入feed,此時類型已經符合
            sess.run(optimizer, feed_dict={x: xs, y: ys})  # 運行迭代優化器
        # 運行一個l輪後,利用驗證即求解損失與準確度
        loss, acc = sess.run([loss_fuction, accuracy],
                             feed_dict={x: mnist.validation.images,y:mnist.validation.labels})
        # 打印本輪訓練結果
        if(epoch+1) % display_step == 0:
            print("Train Epoch: ",'%02d'%(epoch+1), "Loss: ", "{:.9f}".format(loss),
                  "Accuracy: ", "{:.4f}".format(acc))
    
    
    print("Train Finish !!!!!")
    
    訓練模型,代碼如所述。
  2. # 測試結果可視化函數
    def plot_images_labels_prediction(images,  # 圖像列表
                                      labels,  # 標籤列表
                                      prediction,  # 預測值列表
                                      index,  # 所顯示的第一張圖的索引值
                                      num=10  # 顯示的圖像數目
    ):
        fig = plt.gcf()  # 獲取當前圖表
        fig.set_size_inches(10, 12)  # 設置總圖尺寸爲10英寸X12英寸
        if num > 25:  # 限制總的顯示數目不超過25張
            num = 25
        for i in range(0, num):  # 逐個處理子圖
            ax = plt.subplot(5, 5, i+1)
            ax.imshow(np.reshape(images[index], (28, 28)), cmap='binary')
            title = "label="+str(np.argmax(labels[index]))
            if len(prediction) > 0:
                title += ",Prediction=" + str(prediction[index])
            ax.set_title(title, fontsize=10)
            ax.set_xticks([])
            ax.set_yticks([])
            index += 1
        plt.show()
    輔助函數,用以顯示抽取到的圖片、標籤值以及預測值。
  3. # 一次檢測所有test樣本
    prediction_result = sess.run(tf.argmax(preb, 1), feed_dict={x: mnist.test.images})
    # 打印前十個檢測結果
    print(prediction_result[:10])
    # 可視化前10個檢測結果
    plot_images_labels_prediction(mnist.test.images, mnist.test.labels, prediction_result, 10, 10)
    利用模型檢測,並可視化。
  4. 檢測結果如上所述。

 

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