1. 程式人生 > >機器學習入門——使用TensorFlow搭建一個簡單的神經網路實現非線性迴歸

機器學習入門——使用TensorFlow搭建一個簡單的神經網路實現非線性迴歸

TensorFlow是一個基於資料流程式設計的符號數學系統,被廣泛應用於各類機器學習演算法的程式設計實現。

迴歸是一種基本演算法,也是機器學習中比較重要的內容。

迴歸的英文是regression,單詞原型regress的意思是“回退,退化,倒退”。其實 regression——迴歸分析的意思是借用裡面“倒退,倒推”的含義。簡單說就是“由果索因” 的過程,是一種歸納的思想——當我看到大量的事實所呈現的樣態,我推斷出原因或客觀蘊含的關係是如何的;當我看到大量的觀測而來的向量是某種樣態,我設計一種假說來描述它們之間蘊含的關係是如何的。

在機器學習領域,最常用的迴歸有兩大類----類是線性迴歸,一類是非線性迴歸。

所謂線性迴歸,就是在觀察和歸納樣本的過程中認為向量和最終的函式值呈現線性的關係。而後設計這種關係為:

y=f(x)=Wx+b

這裡的W和x分別是1*n和n*1的矩陣,Wx則指的是這兩個矩陣的內積。具體一點說, 例如,如果你在一個實驗中觀察到一名病患的幾個指標呈現線性關係(注意這個是大前提, 如果你觀察到的不是線性關係而用線性模型來建模的話,會得到欠擬合的結果)。拿到的x是一個5維的向量,分別代表一名患者的年齡、身高、體重、血壓、血脂這幾個指標值,y 標籤是描述他們血糖程度的指標值,x和y都是觀測到的值。在拿到大量樣本(就是大量的 x和y)後,我猜測向量(年齡,身髙,體重,血壓,血脂)和與其有關聯關係的血糖程度y值有這樣的關係:

y= w1*年齡+ w2*身高+w3*體重+w4*血壓+ w5*血脂+b

那麼就把每一名患者的(年齡,身高,體重,血壓,血脂)具體向量值代入,並把其血糖程 度少值也代入。這樣一來,在所有的患者資料輸入後,會出現一系列的六元一次方程,未 知數是w1~w5和b——也就是W矩陣的內容和偏置b的內容。而下面要做的事情就是要對 w矩陣的內容和偏置b的內容求出一個最“合適”的解來。這個“合適”的概念就是要得 到一個全域性範圍內由/(x)對映得到的y和我真實觀測到的那個y的差距加和,寫出來是這種方式:

Loss=Σ|Wxi+b-yi|

怎麼理解這個的含義呢?加和的內容是Wxi+b和yi的差值, 每一個訓練向量xi在通過我們剛剛假設的關係f(Wx+b) 對映後與實際觀測值yi的差距值。取絕對值的含義就是指這個差距不論是比觀測值大還是比觀測值小,都是一樣的差距。 將全域性範圍內這n個差距值都加起來,得到所謂的總差距值,就是這個的含義。那麼 顯而易見,如果對映關係中W和b給的理想的話,這個差距值應該是0,因為每個X經過 對映都“嚴絲合縫”地和觀測值一致了——這種狀況太理想了,在實際應用中是見不到的。 不過,Loss越小就說明這個對映關係描述越精確,這個還是很直觀的。那麼想辦法把Loss描述成:

Loss=f(W, b)

再使用相應的方法找出保證Loss儘可能小的W和b的取值,就算是大功告成了。一旦得到一 個誤差足夠小的W和b,並能夠在驗證用的資料集上有滿足當前需求的精度表現後就可以了。例如,預測病患的血糖誤差是取誤差平均小於等於0.3為容忍上線,訓練後在驗證集上的表現是誤差平均為0.2,那就算是合格了。

非線性迴歸訓練的過程跟普通線性迴歸也是一樣的,只不過損失函式的形式不同。但是,它的損失函式的含義仍舊是表示這種擬合殘差與待定係數的關係,並通過相應的手段進行迭代式的優化,最後通過逐步調整待定係數減小殘差。

import tensorflow as tf #匯入TensorFlow
import numpy as np#匯入Numpy
import matplotlib.pyplot as plt#匯入Matplotlib
#使用numpy生成200個隨機點
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])

#定義神經網路中間層,10個神經元
#變數引數用tf.Variable表示
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)#tanh激勵函式

#定義神經網路輸出層
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))
#使用梯度下降法訓練
train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss)

#建立一個會話(Session)
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())#初始化所有變數,分配記憶體
    #進行2000次梯度下降優化
    for _ in range(2000):
        sess.run(train_step,feed_dict={x:x_data,y:y_data})#將x_data和y_data餵給tf變數x,y
        
    #獲得預測值
    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.xticks(color='white')
    plt.yticks(color='white')
    plt.xlabel('x',fontproperties = 'Times New Roman', fontsize=20, fontstyle = 'italic', color='white')
    plt.ylabel('y',fontproperties = 'Times New Roman', fontsize=20, fontstyle = 'italic', color='white')
    plt.show()

 該程式的神經網路結構如下:

 結果如下,藍色散點為樣本,紅色曲線為迴歸曲線