TensoFlow實(shí)戰(zhàn)(一)單變量線性回歸問題

一、監(jiān)督式機(jī)器學(xué)習(xí)的基本術(shù)語

1. 樣本、特征、標(biāo)簽與模型

標(biāo)簽是我們要預(yù)測的真實(shí)事物:y線性回歸中的y變量

特征是指用于描述數(shù)據(jù)的輸入變量:xi 線性回歸中的{x1,x2,...,xn}變量

樣本是指數(shù)據(jù)的特征實(shí)例:x

  • 有標(biāo)簽樣本具有{特征, 標(biāo)簽}:{x, y} 用于訓(xùn)練模型
  • 無標(biāo)簽樣本具有{特征, ?}:{x, ?} 用于對新數(shù)據(jù)做出預(yù)測

模型可將樣本映射到預(yù)測標(biāo)簽:y',由模型的內(nèi)部參數(shù)定義,這些內(nèi)部參數(shù)值是通過學(xué)習(xí)得到的。

2. 訓(xùn)練與損失

訓(xùn)練模型表示通過有標(biāo)簽樣本來學(xué)習(xí)(確定)所有權(quán)重偏差的理想值,在監(jiān)督式學(xué)習(xí)中,機(jī)器學(xué)習(xí)算法通過以下方式構(gòu)建模型:檢查多個樣本并嘗試找出可最大限度減少損失的模型,這一過程稱為經(jīng)驗(yàn)風(fēng)險最小化。

損失是一個數(shù)值,表示對于單個樣本而言模型預(yù)測的準(zhǔn)確程度。訓(xùn)練模型的目標(biāo)是從所有樣本中找到一組平均損失較小的權(quán)重和偏差。

定義損失函數(shù)

  • L1損失:基于模型預(yù)測的值與標(biāo)簽的實(shí)際值之差的絕對值
  • 平方損失:一種常見的損失函數(shù),又稱為L2損失
    均方誤差(MSE)指的是每個樣本的平均平方損失
MSE = \frac{1}{N}\sum_{(x,y)∈D}(y - prediction(x))^2

3. 模型訓(xùn)練與降低損失

訓(xùn)練模型的迭代方法

模型訓(xùn)練要點(diǎn)

  • 對權(quán)重w和偏差b進(jìn)行初始猜測
  • 反復(fù)調(diào)整這些猜測
  • 直到獲得損失可能最低的權(quán)重和偏差為止

在學(xué)習(xí)優(yōu)化過程中,機(jī)器學(xué)習(xí)系統(tǒng)可以不斷迭代,直到總體損失不再變化或至少變化極其緩慢為止,這時候可以說該模型已收斂

計算損失例子

4. 梯度下降法

梯度:一個向量(矢量),表示某一函數(shù)在該點(diǎn)處的方向導(dǎo)數(shù)沿著該方向取得最大值,即函數(shù)在該點(diǎn)處沿著該方向(此梯度的方向)變化最快,變化率最大。

梯度下降法

5. 學(xué)習(xí)率與超參數(shù)

用梯度乘以一個稱為學(xué)習(xí)速率(步長)的標(biāo)量,以確定下一個點(diǎn)的位置
例如:如果梯度大小為2.5,學(xué)習(xí)速率為0.01,則梯度下降法算法會選擇距離前一個點(diǎn)0.025的位置作為下一個點(diǎn)。

梯度學(xué)習(xí)率

超參數(shù)是在開始學(xué)習(xí)過程之前設(shè)置值的參數(shù),如:學(xué)習(xí)率、神經(jīng)網(wǎng)絡(luò)的隱含層數(shù)量等

二、線性回歸問題TensorFlow實(shí)戰(zhàn)

1. 產(chǎn)生人工數(shù)據(jù)集

單變量的線性方程可以表示為:y = w * x + b
本例通過生成人工數(shù)據(jù)集,隨機(jī)生成一個近似采樣隨機(jī)分布,使得 w = 2.0, b = 1, 并加入一個噪聲,噪聲的最大振幅為0.4。

    #在Jupyter中,使用matplotlib顯示圖像需要設(shè)為inline模式,否則不會顯示圖像
    %matplotlib inline
    
    import matplotlib.pyplot as plt #載入matplotlib
    import numpy as np #載入numpy
    import tensorflow as tf #載入TensorFlow
    
    #設(shè)置隨機(jī)數(shù)種子
    np.random.seed(5)
    #直接采用np生成等差數(shù)列的方法,生成100個點(diǎn),每個點(diǎn)的取值在-1~1之間
    x_data = np.linspace(-1, 1, 100)
    #y = 2x  + 1 + 噪聲,其中,噪聲的維度與x_data一致
    y_data = 2 * x_data + 1.0 + np.random.randn(*x_data.shape) * 0.4

2. 利用matplotlib畫圖

    #畫出隨機(jī)生成數(shù)據(jù)的散點(diǎn)圖
    plt.scatter(x_data, y_data)
    #畫出我們想要學(xué)習(xí)到的線性函數(shù) y = 2x + 1
    plt.plot(x_data, 2 * x_data + 1.0, color = 'red', linewidth = 3)
散點(diǎn)圖

3. 定義模型

使機(jī)器自動求出最合適的 w 和 b,使得對于生成的100個樣本,總損失最小。

    #構(gòu)建模型
    #定義訓(xùn)練數(shù)據(jù)的占位符,x是特征值,y是標(biāo)簽值
    x = tf.placeholder("float", name = "x")
    y = tf.placeholder("float", name = "y")
    #定義模型函數(shù)
    def model(x, w, b):
        return tf.multiply(x, w) + b
    
    #定義模型結(jié)構(gòu)
    #構(gòu)建線性函數(shù)的斜率,變量w
    w = tf.Variable(1.0, name = "w0")
    #構(gòu)建線性函數(shù)的截距,變量b
    b = tf.Variable(0.0, name = "b0")
    #pred是預(yù)測值,前向計算
    pred = model(x, w, b)

4. 模型訓(xùn)練

設(shè)置訓(xùn)練參數(shù)

    #迭代次數(shù)(訓(xùn)練輪數(shù))
    train_epochs = 10
    #學(xué)習(xí)率
    learning_rate = 0.05

定義損失函數(shù)

  • 損失函數(shù)用于描述預(yù)測值與真實(shí)值間的誤差,從而指導(dǎo)模型收斂方向
  • 常見損失函數(shù):均方差和交叉熵
    #采用均方差作為損失函數(shù)
    loss_function = tf.reduce_mean(tf.square(y - pred)) #標(biāo)簽值和預(yù)測差值平方的均值

定義優(yōu)化器,設(shè)置學(xué)習(xí)率和優(yōu)化目標(biāo):最小化損失

    #梯度下降優(yōu)化器
    optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss_function)

創(chuàng)建會話

    #聲明會話
    sess = tf.Session()
    #初始化所有變量
    init = tf.global_variables_initializer()
    sess.run(init)

迭代訓(xùn)練:設(shè)置迭代輪次,每次通過將樣本逐個輸入模型,進(jìn)行梯度下降優(yōu)化操作,每輪迭代后,繪制出模型曲線。

    #step = 0 #記錄訓(xùn)練步數(shù)
    #loss_list = [] #用于保存loss值的列表
    #開始訓(xùn)練,輪數(shù)為epoch,采用SGD隨機(jī)梯度下降優(yōu)化方法
    for epoch in range(train_epochs):
        for xs, ys in zip(x_data, y_data):
            _, loss = sess.run([optimizer, loss_function], feed_dict={x: xs, y: ys})
        #顯示損失值loss
        #display_step:控制報告的粒度
        #例如,如果display_step設(shè)為2,則將每訓(xùn)練2個樣本輸出一次損失值
        #與超參數(shù)不同,修改display_step不會更改模型所學(xué)習(xí)的規(guī)律
        #loss_list.append(loss)
        #step = step + 1
        #if step % display_step == 0:
        #    print("Train Epoch:", '%02d' %(epoch+1), "Step: %03d" %(step), "loss=",\
        #    "{:.9f}".format(loss))
        #圖形化顯示損失值:plt.plot(loss_list,'r+')
        b0temp = b.eval(session=sess)
        w0temp = w.eval(session=sess)
        plt.plot(x_data, w0temp * x_data + b0temp) #畫圖
模型曲線

[注]:本案例訓(xùn)練輪數(shù)設(shè)置為10,然而只出現(xiàn)了3根直線(其它覆蓋了),說明訓(xùn)練3次后已接近收斂。

結(jié)果查看和可視化:訓(xùn)練完成后,打印查看參數(shù)(數(shù)據(jù)每次運(yùn)行會有所不同,機(jī)器自動調(diào)整賦值w、b)

    #查看結(jié)果:本例是通過逐漸降低損失值來訓(xùn)練參數(shù) w和b 擬合 y = 2x + 1 中的系數(shù) 2 和 1
    print("w:", sess.run(w)) #w的值應(yīng)該在2附近
    print("b:", sess.run(b)) #b的值應(yīng)該在1附近
    #結(jié)果可視化
    plt.scatter(x_data, y_data, label = 'Original data') #原始散點(diǎn)圖
    plt.plot(x_data, x_data * sess.run(w) + sess.run(b), \
            label = 'Fitted line', color = 'r', linewidth = 3) 
            #優(yōu)化出來的 w、b畫出來的直線(TensorFlow線性擬合)
    plt.legend(loc=2) #通過參數(shù)loc指定圖例位置
線性擬合結(jié)果

利用模型進(jìn)行預(yù)測

    #利用模型進(jìn)行預(yù)測
    x_test = 3.21
    
    predict = sess.run(pred, feed_dict = {x: x_test})
    print("預(yù)測值:%f" % predict)
    
    target = 2 * x_test + 1.0
    print("目標(biāo)值: %f" % target)
    # 預(yù)測值:7.405184
    # 目標(biāo)值: 7.420000
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容