多層神經網絡與應用—MNIST手寫數字識別(一)


一、單隱藏層神經網絡構建與應用

主要內容:

  1.1載入數據

  1.2建立模型

  1.3訓練模型

  1.4評估模型

  1.5應用模型

1.1載入數據

 1.2建立模型

1.2.1構建輸入層

#定義標簽數據占位符
x= tf.placeholder(tf.float32, [None, 784], name='X') #圖片大小28*28
y= tf.placeholder(tf.float32, [None, 10], name='Y')

1.2.2構建隱藏層

H1_NN=256  #自定義隱藏層神經元數量
W1 = tf.Variable(tf.random_normal([784,H1_NN])) #全連接x1,x2...
b1 = tf.Variable(tf.zeros([H1_NN]))    #偏置項
Y1 = tf.nn.relu(tf.matmul(x,W1)+b1)

1.2.3構建輸出層

W2 = tf.Variable(tf.random_normal([H1_NN,10]))
b2 = tf.Variable(tf.zeros([10]))
forward = tf.matmul(Y1, W2) + b2
pred=tf.nn.softmax(forward)  #多分類預測結果

1.3訓練模型

1.3.1定義損失函數、設置訓練參數、選擇優化器、定義准確率

loss_function = tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred),reduction_indices=1))   #定義交叉熵損失函數

#設置訓練參數
train_epochs = 40   #訓練輪數
batch_size=50      #單次訓練樣本數(批次大小)
total_batch= int(mnist.train.num_examples/batch_size)#一輪訓練有多少批次
display_step=1     #顯示粒度
learning_rate=0.01   #學習率

#選擇優化器
optimizer = tf.train.AdamOptimizer(learning_rate).minimize(loss_function)

#定義准確率
correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(pred,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))#准確率,將布爾值轉化為浮點數,並計算平均值

1.3.2訓練過程

#記錄訓練開始時間
startTime = time()

sess = tf.Session()
sess.run(tf.global_variables_initializer())

for epoch in range(train_epochs):
    for batch in range(total_batch):
          xs, ys = mnist.train.next_batch(batch_size)  # 讀取批次數據
          sess.run(optimizer,feed_dict={x:xs,y:ys})   # 執行批次訓練
    #total_batch個批次訓練完成后,使用驗證數據計算課差與准確率;驗證集沒有分批
    loss,acc = sess.run([loss_function,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))

duration = time()-startTime  #顯示運行總時間
print("Train Finished takes:","{:.2f}".format(duration))
View Code

運行結果為:

 分析原因,定義交叉熵損失函數時,有一個log項,log(0)引起的數據不穩定

# loss_function = tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred),reduction_indices=1))   #定義交叉熵損失函數
#TensorFlow提供了softmax_cross_entropy_with_logits函數,用於避免因為log(0)值為NaN造成的數據不穩定
loss_function = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=forward,labels=y))  #注意第一個參數是不做Softmax的前向計算結果

修改后,運行結果為:

從上述打印結果可以看出包含256個神經元的單隱層神經網絡的分類性能比僅包含一個網絡更優。

1.4評估模型

#使用測試集評估模型
accu_test = sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels})
print("Test Accuracy:",accu_test)

1.5應用模型

1.5.1進行預測

#由於pred預測結果是one-hot編碼格式,所以需要轉換為0-9數字
prediction_result = sess.run(tf.argmax(pred,1),feed_dict={x:mnist.test.images})
print(prediction_result[0:10])  #查看預測結果中的前10項

 1.5.2找出預測錯誤

compare_lists = prediction_result==np.argmax(mnist.test.labels,1)
print(compare_lists)

err_lists=[i for i in range(len(compare_lists)) if compare_lists[i]==False]
print(err_lists, len(err_lists))  #最后一項即為多少個預測錯了

     ........... 

 可見一共有279個預測錯誤,但這樣返回預測錯誤的下標不夠直觀,接下來進行修改。

修改一:

#定義一個輸出錯誤分類的函數
def print_predict_errs(labels, prediction):   #標簽列表,預測值列表
    count = 0
    compare_lists =(prediction==np.argmax(labels,1))
    err_lists = [i for i in range(len(compare_lists)) if compare_lists [i]==False]
    for x in err_lists:
        print("index="+str(x) + "標簽值=",np.argmax(labels[x]),"預測值=",prediction[x])
        count += 1
    print("總計:"+str(count))

print_predict_errs(labels=mnist.test.labels,prediction=prediction_result)

運行結果:

 以文本顯示,仍然不夠直觀,進一步修改。

修改二(+可視化):

https://www.cnblogs.com/HuangYJ/p/11642475.html中6.1節可視化函數修改,以便只顯示預測錯誤的樣本

#可視化
def plot_images_labels_prediction(images,labels,prediction,num=10):   #圖像列表,標簽列表,預測值列表,從第index個開始顯示 , 缺省一次顯示10幅
    j = 0
    fig = plt.gcf() #獲取當前圖表,get current figure
    fig.set_size_inches(10,12)  #1英寸等於2.54cm

    compare_lists = prediction_result == np.argmax(mnist.test.labels, 1)
    err_lists = [i for i in range(len(compare_lists)) if compare_lists[i] == False]

    if num > 25:
        num = 25  #最多顯示25個子圖

    for i in range(0, num):
        ax = plt.subplot(5,5,i+1)  #獲取當前要處理的子圖
        ax.imshow(np.reshape(images[err_lists[j]], (28, 28)),cmap='binary')  # 顯示第index個圖像
        title = "label=" + str(np.argmax(labels[err_lists[j]]))# 構建該圖上要顯示的
        if len(prediction)>0:
            title += ",predict="+ str(prediction[err_lists[j]])
        ax.set_title(title, fontsize=10)  #顯示圖上title信息
        ax.set_xticks([])  #不顯示坐標軸
        ax.set_yticks([])
        j += 1
    plt.show()

plot_images_labels_prediction(mnist.test.images,mnist.test.labels,prediction_result,25)  #最多顯示25張
View Code

 

顯示前25個預測錯誤的樣本,預測結果為:

全部代碼為:

#Created by:Huang
#Time:2019/10/15 0015.

import tensorflow as tf
import tensorflow.examples.tutorials.mnist.input_data as input_data
import matplotlib.pyplot as plt
import numpy as np
from time import time

mnist = input_data.read_data_sets("MNIST_data/",one_hot=True)

#定義標簽數據占位符
x= tf.placeholder(tf.float32, [None, 784], name='X') #圖片大小28*28
y= tf.placeholder(tf.float32, [None, 10], name='Y')

#隱藏層
H1_NN=256  #自定義隱藏層神經元數量
W1 = tf.Variable(tf.random_normal([784,H1_NN])) #全連接x1,x2...
b1 = tf.Variable(tf.zeros([H1_NN]))    #偏置項
Y1 = tf.nn.relu(tf.matmul(x,W1)+b1)

#輸出層
W2 = tf.Variable(tf.random_normal([H1_NN,10]))
b2 = tf.Variable(tf.zeros([10]))
forward = tf.matmul(Y1, W2) + b2
pred=tf.nn.softmax(forward)  #多分類預測結果


# loss_function = tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred),reduction_indices=1))   #定義交叉熵損失函數
#TensorFlow提供了softmax_cross_entropy_with_logits函數,用於避免因為log(0)值為NaN造成的數據不穩定
loss_function = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=forward,labels=y))  #注意第一個參數是不做Softmax的前向計算結果


#設置訓練參數
train_epochs = 40   #訓練輪數
batch_size=50      #單次訓練樣本數(批次大小)
total_batch= int(mnist.train.num_examples/batch_size)#一輪訓練有多少批次
display_step=1     #顯示粒度
learning_rate=0.01   #學習率

#選擇優化器
optimizer = tf.train.AdamOptimizer(learning_rate).minimize(loss_function)

#定義准確率
correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(pred,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))#准確率,將布爾值轉化為浮點數,並計算平均值

#記錄訓練開始時間
startTime = time()

sess = tf.Session()
sess.run(tf.global_variables_initializer())

for epoch in range(train_epochs):
    for batch in range(total_batch):
          xs, ys = mnist.train.next_batch(batch_size)  # 讀取批次數據
          sess.run(optimizer,feed_dict={x:xs,y:ys})   # 執行批次訓練
    #total_batch個批次訓練完成后,使用驗證數據計算課差與准確率;驗證集沒有分批
    loss,acc = sess.run([loss_function,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))

duration = time()-startTime  #顯示運行總時間
print("Train Finished takes:","{:.2f}".format(duration))

#使用測試集評估模型
accu_test = sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels})
print("Test Accuracy:",accu_test)

#模型預測
#由於pred預測結果是one-hot編碼格式,所以需要轉換為0-9數字
prediction_result = sess.run(tf.argmax(pred,1),feed_dict={x:mnist.test.images})
print(prediction_result[0:10])  #查看預測結果中的前10項

# #找出預測錯誤
# compare_lists = prediction_result==np.argmax(mnist.test.labels,1)
# print(compare_lists)
#
# err_lists=[i for i in range(len(compare_lists)) if compare_lists[i]==False]
# print(err_lists, len(err_lists))  #最后一項即為多少個預測錯了

#定義一個輸出錯誤分類的函數
# def print_predict_errs(labels, prediction):   #標簽列表,預測值列表
#     count = 0
#     compare_lists =(prediction==np.argmax(labels,1))
#     err_lists = [i for i in range(len(compare_lists)) if compare_lists [i]==False]
#     for x in err_lists:
#         print("index="+str(x) + "標簽值=",np.argmax(labels[x]),"預測值=",prediction[x])
#         count += 1
#     print("總計:"+str(count))

# print_predict_errs(labels=mnist.test.labels,prediction=prediction_result)


#可視化
def plot_images_labels_prediction(images,labels,prediction,num=10):   #圖像列表,標簽列表,預測值列表,從第index個開始顯示 , 缺省一次顯示10幅
    j = 0
    fig = plt.gcf() #獲取當前圖表,get current figure
    fig.set_size_inches(10,12)  #1英寸等於2.54cm

    compare_lists = prediction_result == np.argmax(mnist.test.labels, 1)
    err_lists = [i for i in range(len(compare_lists)) if compare_lists[i] == False]

    if num > 25:
        num = 25  #最多顯示25個子圖

    for i in range(0, num):
        ax = plt.subplot(5,5,i+1)  #獲取當前要處理的子圖
        ax.imshow(np.reshape(images[err_lists[j]], (28, 28)),cmap='binary')  # 顯示第index個圖像
        title = "label=" + str(np.argmax(labels[err_lists[j]]))# 構建該圖上要顯示的
        if len(prediction)>0:
            title += ",predict="+ str(prediction[err_lists[j]])
        ax.set_title(title, fontsize=10)  #顯示圖上title信息
        ax.set_xticks([])  #不顯示坐標軸
        ax.set_yticks([])
        j += 1
    plt.show()

plot_images_labels_prediction(mnist.test.images,mnist.test.labels,prediction_result,25)  #最多顯示25張
MNIST_NN8.1 Code


免責聲明!

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



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