1. 程式人生 > >TensorFlow實現簡單神經網路

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 官方文件中文版