tensorflow基礎學習:端到端實現手寫數字驗證碼識別

手寫數字識別這個例子是學tensorflow必經的小練習喔

本次使用到的是網上的mnist數據集,官網下載速度極慢,這裏附上百度雲下載鏈接: https://pan.baidu.com/s/1O9sfNiYswBq6uKLioyVXAw 提取碼: 1965

話不多說來個正確率的圖,測試集正確率96%

在這裏插入圖片描述

啥?看着不好看?沒看到過程?莫急,看下圖,tensorboard可視化,多帥喔。

這是網絡的結構圖

在這裏插入圖片描述

訓練過程中的數據的變化

在這裏插入圖片描述

在這裏插入圖片描述

圖中可以看到asc(正確率)在隨着訓練不斷的上升,loss損失值也在不斷的下降,其中用到的

下面是code部分,大部分內容可以看代碼

創建一個簡單的神經網絡

# 這裏所說的神經網絡就是一些矩陣相乘,還要偏置的相加,最後保證輸出10個值,因爲手寫數字只有10個類別
# 可以自行改一下里面中間層的神經元個數之類的,不過要注意確保可以矩陣相乘的條件
# 裏面你可以加一層,兩層也可以的,注意輸出矩陣的格式呀求就好
# 就好比如:輸入的爲[None, 784], 因爲圖片有784個像素,也就是有784個特徵,
#所以第一層的權重必須是是 [784, 神經元的個數],偏置則是跟神經元個數一樣就行了。
# coding: utf-8
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

# 載入數據集
mnist = input_data.read_data_sets("../../tensorflow_code/mnist/", one_hot=True)

# 每個批次的大小
batch_size = 50
# 計算一共有多少個批次
n_batch = mnist.train.num_examples // batch_size

# 定義兩個placeholder
x = tf.placeholder(tf.float32, [None, 784])
y = tf.placeholder(tf.float32, [None, 10])

# 這個可以設置有多少神經元在工作
# keep_prob = tf.placeholder(tf.float32)

with tf.variable_scope("first_net"):
    # 創建一個簡單的神經網絡,
    # 所謂的神經網絡就是一些矩陣相乘,還要偏置的相加,最後保證輸出10個值,因爲手寫數字只有10個類別
    # 可以自行改一下里面中間層的神經元個數之類的,不過要注意確保可以矩陣相乘的條件
    # 裏面你可以加一層,兩層也可以的,注意輸出矩陣的格式呀求就好
    # 就好比如:輸入的爲[None, 784], 因爲圖片有784個像素,也就是有784個特徵,
    #所以第一層的權重必須是是 [784, 神經元的個數],偏置則是跟神經元個數一樣就行了。
    
    W1 = tf.Variable(tf.random_normal([784, 50], stddev=0.1))
    b1 = tf.Variable(tf.zeros([50]))
    prediction1 = tf.nn.tanh(tf.matmul(x, W1) + b1)
    
    # 設置神經元的在訓練的工作的比例,設置後,訓練的數據集拿來測試的準確率跟測試集的差不多,
    # 如果不開,每個神經元都在訓練,訓練集的測試結果達到99,測試集的測試結果只有97
    # 在數據量少的時候體會不到重要,再使用goolenet或者Alexnet的時候,幾百w的數據就非常明顯了
    # L1_drop = tf.nn.dropout(prediction1, keep_prob)
    L1_drop = prediction1
    
    # 第一層輸出的數據的類型爲: [n個樣本,784]*[784, 50個神經元]+[50個偏置值] = [n個樣本, 50]
    #也就是說 一個神經元就輸出一個值,下面類似
    
with tf.variable_scope("second_net"):
    W2 = tf.Variable(tf.random_normal([50, 50], stddev=0.1))
    b2 = tf.Variable(tf.zeros([50]))
    prediction2 = tf.nn.tanh(tf.matmul(L1_drop, W2) + b2)
    # L2_drop = tf.nn.dropout(prediction2, keep_prob)
    L2_drop = prediction2
with tf.variable_scope("third_net"):
    W3 = tf.Variable(tf.random_normal([50, 50], stddev=0.1))
    b3 = tf.Variable(tf.zeros([50]))
    prediction3 = tf.nn.tanh(tf.matmul(L2_drop, W3) + b3)
    # L3_drop = tf.nn.dropout(prediction3, keep_prob)
    L3_drop = prediction3
with tf.variable_scope("last_net"):
    W4 = tf.Variable(tf.zeros([50, 10]))
    b4 = tf.Variable(tf.zeros([10]))
    prediction = tf.nn.tanh(tf.matmul(L3_drop, W4) + b4)
# L4_drop = tf.nn.dropout(prediction3, keep_prob)


with tf.variable_scope("loss"):
    # 二次代價函數
    # loss = tf.reduce_mean(tf.square(y - prediction))
    # 使用交叉商損失計算損失,效果會比上面的方差要好
    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=prediction))

with tf.variable_scope("optimizer"):
    # 使用梯度下降法
    train_step = tf.train.GradientDescentOptimizer(0.15).minimize(loss)

# 初始化變量
init = tf.global_variables_initializer()

with tf.variable_scope("accuary"):
    # 結果存放在一個布爾型列表中
    correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(prediction, 1))  # argmax()返回一維張量中最大的值所在的位置
    
    # 求準確率
    # reduce_mean: 求這個張量裏面的值的平均值,如:[1,0,0,1],結果就是0.4
    # cast:改變數據的類型爲float32
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

# 收集變量, 單個的數字值變量
tf.summary.scalar("loss", loss)
tf.summary.scalar("asc", accuracy)

# 高維度數據收集,這裏就收集最後一層好了
# tf.summary.histogram("w1", W1)
# tf.summary.histogram("b1", b1)
# tf.summary.histogram("weights", W2)
# tf.summary.histogram("biases", b2)
# tf.summary.histogram("weights", W3)
# tf.summary.histogram("biases", b3)
tf.summary.histogram("w4", W4)
tf.summary.histogram("b4", b4)


# 定義一個初始化變量op
init_op = tf.global_variables_initializer()

# 定義一個合併變量的OP, 用於後面將變量不斷的加入到event裏面
merge = tf.summary.merge_all()


with tf.Session() as sess:
    sess.run(init)

    # 建立event事件, filewriter用於每一步保存變量的值到event裏面去
    filewriter = tf.summary.FileWriter("./model/", graph=sess.graph)
    # 用於記錄訓練的批次
    i += 1

    for epoch in range(20):
        for batch in range(n_batch):
            # 獲取一批次的訓練數據
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)
            # 傳入數據進行訓練
            # sess.run(train_step, feed_dict={x: batch_xs, y: batch_ys, keep_prob: 0.7})
            sess.run(train_step, feed_dict={x: batch_xs, y: batch_ys})

        # 每訓練100個批次寫入一次W,b,loss,accuracy的值,用於tensorboard 畫圖
            if i % 100 == 0:
                summary = sess.run(merge, feed_dict={x: batch_xs, y: batch_ys})

                # i就相當於畫圖的時候的橫座標
                filewriter.add_summary(summary, i)

        # test_acc = sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels, keep_prob: 1.0})
        # train_acc = sess.run(accuracy, feed_dict={x: mnist.train.images, y: mnist.train.labels, keep_prob: 1.0})
        test_acc = sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels})
        train_acc = sess.run(accuracy, feed_dict={x: mnist.train.images, y: mnist.train.labels})
        print("Iter " + str(epoch) + ",Testing Accuracy " + str(test_acc) + ",Training Accuracy " + str(train_acc))


小結: 這次分享的主要是比較基礎的手寫數字的識別,寫得可能不是很詳細,不過可以自行看下注釋,以及自己修改一些參數可以幫助理解,對於tensorboard不能顯示出圖的問題,會在我的另一篇博客中提到,歡迎多多指教。

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