TensorFlow實現簡單神經網絡

本文首發於我的個人博客QIMING.INFO,轉載請帶上鍊接及署名。

在上文(TensorFlow快速上手)中,我們介紹了TensorFlow中的一些基本概念,並實現了一個線性迴歸的例子。

本文我們趁熱打鐵,接着用TensorFlow實現一下神經網絡吧。

TensorFlow中的神經網絡可以用來實現迴歸算法和分類算法,本文將分別給出實現這兩種算法的代碼。除此之外,還將介紹一個TensorFlow中重要且常用的概念——placeholder(佔位符),和一個著名的數據集:MINST數據集。

1 placeholder

在開始之前,先得說一下placeholder,中文翻譯爲佔位符

tensor不僅以常量或變量的形式存儲,TensorFlow 還提供了feed機制,該機制可以臨時替代計算圖中的任意操作中的tensor,可以對圖中任何操作提交補丁,直接插入一個tensor。具體方法即使用tf.placeholder()爲這些操作創建佔位符。簡單使用如下:

# 創建input1和input2這兩個佔位符
input1 = tf.placeholder(tf.float32)
input2 = tf.placeholder(tf.float32)
output = tf.multiply(input1,input2)

with tf.Session() as sess:
    # 通過字典的形式向input1和input2傳值
    print(sess.run(output,feed_dict={input1:[7.],input2:[2.]}))

# 輸出結果爲:[14.]

2 神經網絡實現迴歸算法

2.1 代碼及說明

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

# 使用numpy生成100個隨機點作爲假數據
x_data = np.linspace(-0.5,0.5,200)[:,np.newaxis]
noise = np.random.normal(0,0.02,x_data.shape)
y_data = np.square(x_data)+noise

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

# 定義神經網絡中間層
Weights_L1 = tf.Variable(tf.random_normal([1,10]))
biases_L1 = tf.Variable(tf.zeros([1,10]))
Wx_plus_b_L1 = tf.matmul(x,Weights_L1) + biases_L1
L1 = tf.nn.tanh(Wx_plus_b_L1)

# 定義神經網絡輸出層
Weights_L2 = tf.Variable(tf.random_normal([10,1]))
biases_L2 = tf.Variable(tf.zeros([1,1]))
Wx_plus_b_L2 = tf.matmul(L1,Weights_L2)+biases_L2
prediction = tf.nn.tanh(Wx_plus_b_L2)

# 二次代價函數
loss = tf.reduce_mean(tf.square(y-prediction))
# 定義一個梯度下降法來進行訓練的優化器 學習率0.1
train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss)

with tf.Session() as sess:
    # 變量初始化
    sess.run(tf.global_variables_initializer())
    # 訓練2000次
    for step in range(2000):
        sess.run(train_step,feed_dict={x:x_data,y:y_data})
    # 獲得預測值
    prediction_value = sess.run(prediction,feed_dict={x:x_data}) 
    # 畫圖展示結果
    plt.figure()
    plt.scatter(x_data,y_data)
    plt.plot(x_data,prediction_value,'r-',lw=5)
    plt.show()

2.2 結果

這個神經網絡比較簡單,使用了tanh()作爲激活函數,梯度下降法爲優化器,二次代價函數爲損失函數,擬合出的結果如上圖紅線所示。

3 神經網絡實現分類算法

3.1 MNIST數據集簡介

MNIST是一個入門級的計算機視覺數據集,它包含各種手寫數字圖片,它也包含每一張圖片對應的標籤,告訴我們這個是數字幾。比如,下面這四張圖片的標籤分別是5,0,4,1。

MNIST數據集有兩部分組成:60000行的訓練數據集(mnist.train)和10000行的測試數據集(mnist.test)。

每一個MNIST數據單元有兩部分組成:一張包含手寫數字的圖片和一個對應的標籤。我們把這些圖片設爲“xs”,把這些標籤設爲“ys”。訓練數據集和測試數據集都包含xs和ys,比如訓練數據集的圖片是 mnist.train.images ,訓練數據集的標籤是 mnist.train.labels

每一張圖片包含28像素X28像素。我們可以用一個數字數組來表示這張圖片:

我們把這個數組展開成一個向量,長度是 28x28 = 784。因此,在MNIST訓練數據集中,mnist.train.images 是一個形狀爲 [60000, 784] 的張量,第一個維度數字用來索引圖片,第二個維度數字用來索引每張圖片中的像素點。相對應的MNIST數據集的標籤是介於0到9的數字,用來描述給定圖片裏表示的數字。爲了用於這個教程,我們使標籤數據是"one-hot vectors"。 一個one-hot向量除了某一位的數字是1以外其餘各維度數字都是0。所以在此教程中,數字n將表示成一個只有在第n維度(從0開始)數字爲1的10維向量。比如,標籤0將表示成([1,0,0,0,0,0,0,0,0,0,0])。因此, mnist.train.labels 是一個 [60000, 10] 的數字矩陣。

3.2 代碼及說明

import tensorflow as tf
import numpy as np

from tensorflow.examples.tutorials.mnist import input_data
# 載入數據集
mnist = input_data.read_data_sets("MNIST_data",one_hot=True)

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

# 定義placeholder
x = tf.placeholder(tf.float32,[None,784])
y = tf.placeholder(tf.float32,[None,10])
# 定義dropout
keep_prob = tf.placeholder(tf.float32)
# 定義一個可變的學習率變量
lr = tf.Variable(0.001,dtype=tf.float32)

# 創建一個簡單的神經網絡
W1 = tf.Variable(tf.truncated_normal([784,1000],stddev=0.1))
b1 = tf.Variable(tf.zeros([1000])+0.1)
L1 = tf.nn.tanh(tf.matmul(x,W1)+b1)
L1_drop = tf.nn.dropout(L1,keep_prob)

W2 = tf.Variable(tf.truncated_normal([1000,500],stddev=0.1))
b2 = tf.Variable(tf.zeros([500])+0.1)
L2 = tf.nn.tanh(tf.matmul(L1_drop,W2)+b2)
L2_drop = tf.nn.dropout(L2,keep_prob)

W3 = tf.Variable(tf.truncated_normal([500,10],stddev=0.1))
b3 = tf.Variable(tf.zeros([10])+0.1)
prediction = tf.nn.softmax(tf.matmul(L2_drop,W3)+b3)

# 交叉熵代價函數
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y,logits=prediction))
# 使用Adam作爲優化器進行訓練
train_step = tf.train.AdamOptimizer(lr).minimize(loss)

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

# 結果存放在一個布爾型列表中
correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(prediction,1)) # argmax返回一維張量中最大的值所在的位置
# 求準確率
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))

with tf.Session() as sess:
    sess.run(init)
    for epoch in range(51):
        # 每訓練一輪 學習率降低 
        sess.run(tf.assign(lr,0.001 * (0.95 ** epoch)))
        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})
            
        # 計算測試數據的準確率
        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})
        # 輸出訓練輪次、測試數據準確率、訓練數據準確率
        print("Iter "+str(epoch)+",Testing Accuracy "+str(test_acc)+",Training Accuracy " + str(train_acc) )

3.3 結果

Iter 0,Testing Accuracy 0.9439,Training Accuracy 0.9438
Iter 1,Testing Accuracy 0.9515,Training Accuracy 0.9538364
Iter 2,Testing Accuracy 0.9582,Training Accuracy 0.96207273
Iter 3,Testing Accuracy 0.9616,Training Accuracy 0.9679273
Iter 4,Testing Accuracy 0.9659,Training Accuracy 0.9701818
Iter 5,Testing Accuracy 0.9668,Training Accuracy 0.9737818
Iter 6,Testing Accuracy 0.9691,Training Accuracy 0.9764364
Iter 7,Testing Accuracy 0.9718,Training Accuracy 0.979
Iter 8,Testing Accuracy 0.9707,Training Accuracy 0.9800364
Iter 9,Testing Accuracy 0.9716,Training Accuracy 0.98210907
Iter 10,Testing Accuracy 0.9744,Training Accuracy 0.9829818
Iter 11,Testing Accuracy 0.973,Training Accuracy 0.98376364
Iter 12,Testing Accuracy 0.9743,Training Accuracy 0.9856
Iter 13,Testing Accuracy 0.9749,Training Accuracy 0.9863091
Iter 14,Testing Accuracy 0.9755,Training Accuracy 0.9862546
Iter 15,Testing Accuracy 0.974,Training Accuracy 0.98661816
Iter 16,Testing Accuracy 0.9763,Training Accuracy 0.9874
Iter 17,Testing Accuracy 0.9751,Training Accuracy 0.9886909
Iter 18,Testing Accuracy 0.9768,Training Accuracy 0.98914546
Iter 19,Testing Accuracy 0.9756,Training Accuracy 0.98987275
Iter 20,Testing Accuracy 0.9766,Training Accuracy 0.9896182
Iter 21,Testing Accuracy 0.9771,Training Accuracy 0.9906545
Iter 22,Testing Accuracy 0.9786,Training Accuracy 0.9912364
Iter 23,Testing Accuracy 0.9781,Training Accuracy 0.99152726
Iter 24,Testing Accuracy 0.9782,Training Accuracy 0.9915636
Iter 25,Testing Accuracy 0.9778,Training Accuracy 0.9921273
Iter 26,Testing Accuracy 0.9799,Training Accuracy 0.99243635
Iter 27,Testing Accuracy 0.979,Training Accuracy 0.99258184
Iter 28,Testing Accuracy 0.9798,Training Accuracy 0.99285454
Iter 29,Testing Accuracy 0.9784,Training Accuracy 0.99294543
Iter 30,Testing Accuracy 0.9789,Training Accuracy 0.99307275
Iter 31,Testing Accuracy 0.9794,Training Accuracy 0.99325454
Iter 32,Testing Accuracy 0.9786,Training Accuracy 0.9934545
Iter 33,Testing Accuracy 0.9791,Training Accuracy 0.9937818
Iter 34,Testing Accuracy 0.9797,Training Accuracy 0.9938545
Iter 35,Testing Accuracy 0.9799,Training Accuracy 0.9941273
Iter 36,Testing Accuracy 0.9802,Training Accuracy 0.99407274
Iter 37,Testing Accuracy 0.9807,Training Accuracy 0.99438184
Iter 38,Testing Accuracy 0.9814,Training Accuracy 0.9944182
Iter 39,Testing Accuracy 0.9805,Training Accuracy 0.99447274
Iter 40,Testing Accuracy 0.9809,Training Accuracy 0.9945091
Iter 41,Testing Accuracy 0.9813,Training Accuracy 0.9946182
Iter 42,Testing Accuracy 0.9811,Training Accuracy 0.99474543
Iter 43,Testing Accuracy 0.9809,Training Accuracy 0.9948364
Iter 44,Testing Accuracy 0.9812,Training Accuracy 0.99485457
Iter 45,Testing Accuracy 0.9814,Training Accuracy 0.99487275
Iter 46,Testing Accuracy 0.9824,Training Accuracy 0.9948909
Iter 47,Testing Accuracy 0.9817,Training Accuracy 0.9950182
Iter 48,Testing Accuracy 0.982,Training Accuracy 0.9950909
Iter 49,Testing Accuracy 0.9821,Training Accuracy 0.9951091
Iter 50,Testing Accuracy 0.982,Training Accuracy 0.9951091

可以看出,在訓練了51輪後,測試數據的準確率已經達到了98.2%,訓練數據的準確率達到了99.5% 。

本例中神經網絡的激活函數使用的是tanh()函數,分類用了softmax()函數,損失函數用了交叉熵函數,使用了Adam作爲了優化器,爲了防止過擬合,使用了dropout這一機制。

4 小結

在本文中,分別實現了神經網絡的迴歸算法和分類算法,其中提到的有關神經網絡的一些概念,如激活函數、損失函數、優化器等,先請讀者自行參考相關資料,本人後續可能會補充。

5 參考資料

[1]視頻《深度學習框架Tensorflow學習與應用》@Youtube
[2]TensorFlow中文社區.基本用法 | TensorFlow 官方文檔中文版

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