神經網絡算法以及Tensorflow的實現
一、多層向前神經網絡(Multilayer Feed-Forward Neural Network)
- 多層向前神經網絡由三部分組成:輸入層(input layer), 隱藏層 (hidden layers), 輸入層 (output layers)
- 每層由單元(units)組成
- 輸入層(input layer)是由訓練集的實例特征向量傳入
- 經過連接結點的權重(weight)傳入下一層,上一層的輸出是下一層的輸入
- 隱藏層的個數可以是任意的,輸入層有一層,輸出層有一層
- 每個單元(unit)也可以被稱作神經結點(根據生物學來源定義)
- 以上成為2層的神經網絡(輸入層不算)
- 一層中加權的求和(輸入乘以權重在加上偏向),然后根據非線性方程轉化輸出
- 作為多層向前神經網絡,理論上,如果有足夠多的隱藏層(hidden layers) 和足夠大的訓練集, 可以模擬出任何方程
二、神經網絡結構設計
- 使用神經網絡訓練數據之前,必須確定神經網絡的層數,以及每層單元的個數
- 特征向量在被傳入輸入層時通常被先標准化(normalize)到0和1之間 (為了加速學習過程)
- 離散型變量可以被編碼成每一個輸入單元對應一個特征值可能賦的值
比如:特征值A可能取三個值(a0, a1, a2), 可以使用3個輸入單元來代表A。
如果A=a0, 那么代表a0的單元值就取1, 其他取0;
如果A=a1, 那么代表a1de單元值就取1,其他取0,以此類推
- 神經網絡即可以用來做分類(classification)問題,也可以解決回歸(regression)問題
對於分類問題,如果是2類,可以用一個輸出單元表示(0和1分別代表2類)
如果多於2類,每一個類別用一個輸出單元表示
所以輸入層的單元數量通常等於類別的數量
- 沒有明確的規則來設計最好有多少個隱藏層
根據實驗測試和誤差,以及准確度來實驗並改
三、Backpropagation算法
- 通過迭代思想來處理訓練集中的實例
- 對比經過神經網絡后輸入層預測值(predicted value)與真實值(target value)之間
- 反方向(從輸出層=>隱藏層=>輸入層)來以最小化誤差(error)來更新每個連接的權重(weight)
- 算法詳細介紹:
- 初始化權重(weights)和偏向(bias): 隨機初始化在-1到1之間,或者-0.5到0.5之間,每個單元有一個偏向
- 對於每一個訓練實例X,執行以下步驟:
由輸入層向前傳送(前向傳播):輸入層==>權重和偏向==>非線性處理==>輸出層(預測結果)
根據誤差(error)反向傳送:誤差==>輸出層==>隱藏層==>輸入層(通常利用梯度下降算法)(更新權重和偏向)
3.終止條件
權重的更新低於某個閾值
預測的錯誤率低於某個閾值
達到預設一定的循環次數
四、利用神經網絡實現回歸問題——非線性回歸
1 #程序: 2 import os 3 os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' 4 import tensorflow as tf 5 import numpy as np 6 import matplotlib.pyplot as plt #python中畫圖工具包 7 #使用numpy生成200個隨機點(樣本點) 8 x_data = np.linspace(-0.5, 0.5, 200)[:, np.newaxis] #使用numpy生成200個隨機點,[:, np.newaxis]增加維度(x_data 是一個200行1列的數據) 9 noise = np.random.normal(0, 0.02, x_data.shape) #生成隨機噪聲干擾項(形狀同x_data) 10 y_data = np.square(x_data) + noise #構造類似於二次函數的點圖形 11 #定義兩個placeholder 12 x = tf.placeholder(tf.float32, [None, 1]) #x、y的維度為任意行,1列(根據樣本來定義的維度) 13 y = tf.placeholder(tf.float32, [None, 1]) 14 #定義神經網絡隱藏層L1(該神經網絡的神經元數量為(1-10-1)) 15 Weights_L1 = tf.Variable(tf.random_normal([1, 10])) #隨機產生10個權重 16 Biases_L1 = tf.Variable(tf.zeros([1, 10])) #0初始化偏向 17 Wx_plus_B_L1 = tf.matmul(x, Weights_L1) + Biases_L1 #L1層進行加權求和 18 L1 = tf.nn.tanh(Wx_plus_B_L1) #根據非線性方程(雙曲正切函數)轉化輸出 19 #定義神經網絡輸出層 20 Weights_L2 = tf.Variable(tf.random_normal([10, 1])) 21 Biases_L2 = tf.Variable(tf.zeros([1, 1])) 22 Wx_plus_B_L2 = tf.matmul(L1, Weights_L2) + Biases_L2 #將L1的輸出作為輸出層的輸入 23 prediction = tf.nn.tanh(Wx_plus_B_L2) #預測值 24 #定義二次代價函數 25 loss = tf.reduce_mean(tf.square(y - prediction)) 26 #使用隨機梯度下降法進行訓練,使得二次代價函數最小 27 train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss) 28 #變量初始化 29 init = tf.global_variables_initializer() 30 #定義會話 31 with tf.Session() as sess: 32 sess.run(init) 33 for _ in range(2000): #進行2000次訓練學習 34 sess.run(train_step, feed_dict = {x:x_data, y:y_data}) 35 #獲得預測值 36 prediction_value = sess.run(prediction, feed_dict = {x:x_data}) 37 #畫圖 38 plt.figure() 39 plt.scatter(x_data, y_data) 40 plt.plot(x_data, prediction_value, 'r-', lw = 5) 41 plt.show()
#執行結果:
五、利用神經網絡實現分類問題——MNIST數據集分類相關介紹及其簡單實現
1. MNINST數據集介紹
MINST數據集官網: http://yann.lecun.com/exdb/mnist/
MINST數據集分類:MNIST手寫數字數據庫具有60000個示例的訓練集和10000個示例的測試集
每一張圖片包含28*28個像素,將其變成一個1行28*28=784列的向量。圖片中的像素值介於0-1之間。
60000個示例的訓練集是一個[60000,784]的張量。
MNIST數據集的標簽是0-9的數字。
‘one-hot vector’:某一位維度的數字是1,其余維度的數字是0.
將MNIST數據集的標簽轉換為‘one-hot vector’,比如標簽5,用該種方法表示為:[0000010000]
2. softmax函數(歸一化指數函數)
作用:
- 將一個含任意實數的k維向量‘壓縮’到另一個k維向量中,使得每一個元素的范圍都在(0,1)之間,並且所有元素的和位1。
形式:
常用於基於概率的多分類問題中
舉例理解:
比如MNIST數據集識別結果為(1,5,3)
則:
exp(1)= 2.718;exp(5)= 148.413;exp(3)= 20.086
exp(1)+ exp(5)+ exp(3)= 171.217
P1 = exp(1)% ( exp(1)+ exp(5)+ exp(3))= 0.016
P5 = exp(5)% ( exp(1)+ exp(5)+ exp(3))= 0.867
P3 = exp(3)% ( exp(1)+ exp(5)+ exp(3))= 0.117
因為結果為5的概率最大。所以,最終識別結果應該是 5.
3.構建簡單的神經網絡來進行MNIST數據集識別
784個神經元作為輸入,無隱藏層,10個神經元為輸出
4.Tensorflow程序實現
1 import os 2 os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' 3 import tensorflow as tf 4 from tensorflow.examples.tutorials.mnist import input_data 5 #載入數據集 6 mnist = input_data.read_data_sets('MNIST_data', one_hot=True) 7 #每個批次的大小(即每次訓練的圖片數量) 8 batch_size = 50 9 #計算一共有多少個批次 10 n_bitch = mnist.train.num_examples // batch_size 11 #定義兩個placeholder 12 x = tf.placeholder(tf.float32, [None, 784]) 13 y = tf.placeholder(tf.float32, [None, 10]) 14 #創建一個只有輸入層(784個神經元)和輸出層(10個神經元)的簡單神經網絡 15 Weights = tf.Variable(tf.zeros([784, 10])) 16 Biases = tf.Variable(tf.zeros([10])) 17 Wx_plus_B = tf.matmul(x, Weights) + Biases 18 prediction = tf.nn.softmax(Wx_plus_B) 19 #二次代價函數 20 loss = tf.reduce_mean(tf.square(y - prediction)) 21 #使用梯度下降法 22 train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss) 23 #初始化變量 24 init = tf.global_variables_initializer() 25 #結果存放在一個布爾型列表中 26 correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(prediction, 1)) #argmax返回一維張量中最大的值所在的位置,標簽值和預測值相同,返回為True 27 #求准確率 28 accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) #cast函數將correct_prediction的布爾型轉換為浮點型,然后計算平均值即為准確率 29 30 with tf.Session() as sess: 31 sess.run(init) 32 #將測試集循環訓練20次 33 for epoch in range(21): 34 #將測試集中所有數據循環一次 35 for batch in range(n_bitch): 36 batch_xs, batch_ys = mnist.train.next_batch(batch_size) #取測試集中batch_size數量的圖片及對應的標簽值 37 sess.run(train_step, feed_dict={x:batch_xs, y:batch_ys}) #將上一行代碼取到的數據進行訓練 38 acc = sess.run(accuracy, feed_dict={x:mnist.test.images, y:mnist.test.labels}) #准確率的計算 39 print('Iter: ' + str(epoch) + ',Testing Accuracy= ' + str(acc))
#執行結果

1 #執行結果:(因為已經下載過數據集,如果第一次運行,是提示下載成功) 2 Extracting MNIST_data\train-images-idx3-ubyte.gz 3 Extracting MNIST_data\train-labels-idx1-ubyte.gz 4 Extracting MNIST_data\t10k-images-idx3-ubyte.gz 5 Extracting MNIST_data\t10k-labels-idx1-ubyte.gz 6 Iter : 0,Testing Accuracy = 0.8599 7 Iter : 1,Testing Accuracy = 0.8806 8 Iter : 2,Testing Accuracy = 0.8909 9 Iter : 3,Testing Accuracy = 0.8963 10 Iter : 4,Testing Accuracy = 0.9006 11 Iter : 5,Testing Accuracy = 0.9034 12 Iter : 6,Testing Accuracy = 0.9047 13 Iter : 7,Testing Accuracy = 0.9069 14 Iter : 8,Testing Accuracy = 0.908 15 Iter : 9,Testing Accuracy = 0.9094 16 Iter : 10,Testing Accuracy = 0.9113 17 Iter : 11,Testing Accuracy = 0.9127 18 Iter : 12,Testing Accuracy = 0.9137 19 Iter : 13,Testing Accuracy = 0.9144 20 Iter : 14,Testing Accuracy = 0.9144 21 Iter : 15,Testing Accuracy = 0.9156 22 Iter : 16,Testing Accuracy = 0.9156 23 Iter : 17,Testing Accuracy = 0.9171 24 Iter : 18,Testing Accuracy = 0.9173 25 Iter : 19,Testing Accuracy = 0.9177 26 Iter : 20,Testing Accuracy = 0.9179
#准確率不是很高,但是我只是構建了最簡單的輸入輸出層。我會根據之后所學去優化程序,提高准確率