1. 程式人生 > 其它 >單變數線性迴歸:TensorFlow 實戰(實戰篇)

單變數線性迴歸:TensorFlow 實戰(實戰篇)

> 慕課:《深度學習應用開發-TensorFlow實踐》 > 章節:第五講 單變數線性迴歸:TensorFlow 實戰

導語

慕課:《深度學習應用開發-TensorFlow實踐》
章節:第五講 單變數線性迴歸:TensorFlow 實戰
這一講理論部分請看https://www.cnblogs.com/tangkc/p/15371331.html,TensorFlow版本為2.3

目錄

我們所要實現的是一個單變數的線性方程,這個方程可以表示為y=w*x+b。本案例通過生成人工資料集,隨機生成一個近似取樣隨機分佈,使得w=2.0b=1,並加入一個噪聲,噪聲的最大振幅為0.4

匯入庫並生成資料集

匯入庫

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
#在jupyter中使用matplotlib顯示影象需要設定為inline模式,否則不會在網頁中顯示影象
%matplotlib inline
tf.__version__

output:

2.3.0

生成資料集

首先生成輸入資料,構造滿足這個函式的x和y,同時加入一些不滿足方程的噪聲

#直接採用np生成等差數列的方法,生成100個點,取值在[-1,1]
x_data=np.linspace(-1,1,100)
np.random.seed(5)#設定隨機數種子
#產生對應的y=2x+1的值,同時加入噪聲
y_data=2*x_data+1.0+np.random.randn(*x_data.shape)*0.4

np.random.randn是從標準正態分佈中返回一個或多個樣本值,舉個簡單的例子

而原始碼中的np.random.randn(*x_data.shape)

效果和np.random.randn(100)是一樣的

下面我們畫一下生成的xy的影象

plt.scatter(x_data,y_data)
plt.xlabel('x')
plt.ylabel('y')
plt.title("Training Data")
# 畫出我們想要得到的目標函式y=2x+1
plt.plot(x_data,1.0+2*x_data,'r',linewidth=3)

構建模型

建模

這個模型還是比較的簡單的

def model(x,w,b):
    return tf.multiply(x,w)+b

建立待優化變數

w=tf.Variable(np.random.randn(),tf.float32)# 斜率
b=tf.Variable(0.0,tf.float32)#截距

定義損失函式

損失函式用於描述預測值和真實值之間的誤差,從而指導模型收斂方向,常用的有均方差(MSE)和交叉熵
這裡我們用的是均方差

#定義均方差損失函式
def loss(x,y,w,b):
    err=model(x,w,b)-y#計算預測值和真實值之間的差異
    squarred_err=tf.square(err)#求平方,得出方差
    return tf.reduce_mean(squarred_err)#求均值,得出均方差

訓練模型

設定訓練超引數

epochs=10#迭代次數
lr=0.01#學習率

定義計算梯度函式

def grad(x,y,w,b):
    with tf.GradientTape() as tape:
        loss_=loss(x,y,w,b)
    return tape.gradient(loss_,[w,b])# 返回梯度向量

這裡有一個TF1TF2不同的地方,在 TensorFlow 2 中,使用 tf.GradientTape() 這一上下文管理器封裝需要求導的計算步驟,並使用其 gradient() 方法求導。

執行訓練(SGD)

step=0# 記錄訓練步數
loss_list=[]# 儲存loss值的列表
display_step=10# 控制訓練過程資料資料顯示頻率,不是超引數
for epoch in range(epochs):
    for xs,ys in zip(x_data,y_data):
        loss_=loss(xs,ys,w,b)# 計算loss
        loss_list.append(loss_)
        delta_w,delta_b=grad(xs,ys,w,b)#計算梯度
        change_w=delta_w*lr#計算w需要調整的量
        change_b=delta_b*lr#計算b需要調整的量
        w.assign_sub(change_w)
        b.assign_sub(change_b)#將w,b變更為減去對應變化量後的值
        step=step+1
        if step%display_step==0:#顯示訓練過程
            print(f'Training Epoch:{epoch+1}  Step:{step}  Loss:{loss_}')
    plt.plot(x_data,w.numpy()*x_data+b.numpy())


這裡就展示一部分的執行結果
本案例所擬合的模型較簡單,訓練5輪之後已經接近收斂,對於複雜模型,需要更多次訓練才能收斂

顯示訓練結果並可視化

print(f'w:{w.numpy()}, b:{b.numpy()}')
plt.scatter(x_data,y_data,label='Original data')
plt.plot(x_data,x_data*2.0+1.0,label="Object line",color='g',linewidth=3)
plt.plot(x_data,x_data*w.numpy()+b.numpy(),label="Fitted line",color='r',linewidth=3)
plt.legend(loc=2)#設定圖例位置

檢視損失變化情況

plt.plot(loss_list)

進行預測

x_test=3.21
predict=model(x_test,w.numpy(),b.numpy())
target=2*x_test+1.0
print(f'預測值:{predict}, 目標值:{target}')

輸出

預測值:7.426405906677246, 目標值:7.42

批量梯度下降BGD模型訓練

隨機梯度下降法 (SGD) 每次迭代只使用一個樣本(批量大小為 1),如果進行足夠的迭代,SGD 也可以發揮作用。“隨機”這一術語表示構成各個批量的一個樣本都是隨機選擇的。
在梯度下降法中,批量指的是用於在單次迭代中計算梯度的樣本總數。
假定批量是指整個資料集,資料集通常包含很大樣本(數萬甚至數千億),此外,資料集通常包含多個特徵。因此,一個批量可能相當巨大。如果是超大批量,則單次迭代就可能要花費很長時間進行計算。
小批量隨機梯度下降法(小批量 SGD) 是介於全批量迭代與 SGD 之間的折衷方案。小批量通常包含 10-1000 個隨機選擇的樣本。小批量 SGD 可以減少 SGD 中的雜亂樣本數量,但仍然比全批量更高效。
那麼,接下來是實現,我們只需要修改一下上面的一部分程式碼就好了。

修改訓練超引數

epochs=100#迭代次數
lr=0.05#學習率

訓練週期和學習率需要做一些調整。訓練週期暫設為100,意味著所有樣本要參與100次訓練。學習率設定為0.05,比SGD版本的要大。

修改模型訓練過程

loss_list=[]# 儲存loss值的列表
for epoch in range(epochs):
    loss_=loss(x_data,y_data,w,b)# 計算loss
    loss_list.append(loss_)
    delta_w,delta_b=grad(x_data,y_data,w,b)#計算梯度
    change_w=delta_w*lr#計算w需要調整的量
    change_b=delta_b*lr#計算b需要調整的量
    w.assign_sub(change_w)
    b.assign_sub(change_b)#將w,b變更為減去對應變化量後的值
    print(f'Training Epoch:{epoch+1}  Loss={loss_}')
    plt.plot(x_data,w.numpy()*x_data+b.numpy())


顯示訓練結果並可視化

print(f'w:{w.numpy()}, b:{b.numpy()}')
plt.scatter(x_data,y_data,label='Original data')
plt.plot(x_data,x_data*2.0+1.0,label="Object line",color='g',linewidth=3)
plt.plot(x_data,x_data*w.numpy()+b.numpy(),label="Fitted line",color='r',linewidth=3)
plt.legend(loc=2)#設定圖例位置

損失值視覺化

plt.plot(loss_list)

完整程式碼

點選檢視程式碼
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
#在jupyter中使用matplotlib顯示影象需要設定為inline模式,否則不會在網頁中顯示影象
%matplotlib inline
#直接採用np生成等差數列的方法,生成100個點,取值在[-1,1]
x_data=np.linspace(-1,1,100)
np.random.seed(5)#設定隨機數種子
#產生對應的y=2x+1的值,同時加入噪聲
y_data=2*x_data+1.0+np.random.randn(*x_data.shape)*0.4
# np.random.randn是從標準正態分佈中返回一個或多個樣本值,
np.random.randn(10)
plt.scatter(x_data,y_data)
plt.xlabel('x')
plt.ylabel('y')
plt.title("Training Data")
# 畫出我們想要得到的目標函式y=2x+1
plt.plot(x_data,1.0+2*x_data,'r',linewidth=3)
def model(x,w,b):
    return tf.multiply(x,w)+b
w=tf.Variable(np.random.randn(),tf.float32)# 斜率
b=tf.Variable(0.0,tf.float32)#截距
#定義均方差損失函式
def loss(x,y,w,b):
    err=model(x,w,b)-y#計算預測值和真實值之間的差異
    squarred_err=tf.square(err)#求平方,得出方差
    return tf.reduce_mean(squarred_err)#求均值,得出均方差
def grad(x,y,w,b):
    with tf.GradientTape() as tape:
        loss_=loss(x,y,w,b)
    return tape.gradient(loss_,[w,b])# 返回梯度向量
epochs=100#迭代次數
lr=0.05#學習率
loss_list=[]# 儲存loss值的列表
for epoch in range(epochs):
    loss_=loss(x_data,y_data,w,b)# 計算loss
    loss_list.append(loss_)
    delta_w,delta_b=grad(x_data,y_data,w,b)#計算梯度
    change_w=delta_w*lr#計算w需要調整的量
    change_b=delta_b*lr#計算b需要調整的量
    w.assign_sub(change_w)
    b.assign_sub(change_b)#將w,b變更為減去對應變化量後的值
    print(f'Training Epoch:{epoch+1}  Loss={loss_}')
    plt.plot(x_data,w.numpy()*x_data+b.numpy())
print(f'w:{w.numpy()}, b:{b.numpy()}')
plt.scatter(x_data,y_data,label='Original data')
plt.plot(x_data,x_data*2.0+1.0,label="Object line",color='g',linewidth=3)
plt.plot(x_data,x_data*w.numpy()+b.numpy(),label="Fitted line",color='r',linewidth=3)
plt.legend(loc=2)#設定圖例位置
plt.plot(loss_list)

梯度下降演算法總結

批量梯度下降每次迭代都考慮了全部的樣本,做的是全域性優化,但花費的計算資源較大,如果訓練資料非常大,還無法實現全部樣本同步參與。
隨機梯度下降每次迭代只取一條樣本資料, 由於單個樣本的訓練可能會帶來很多噪聲,使得SGD並不是每次迭代都向著整體最優化方向,因此在剛開始訓練時可能收斂得很快,但是訓練一段時間後就會變得很慢。
在SGD和BGD中間,還有一個集合了兩種梯度下降法的優點的方法:小批量梯度下降(MBGD,Mini-batch gradient descent),每次迭代從訓練樣本中隨機抽取一小批進行訓練,這個一小批的數量取值也是一個超引數。

小結

通過一個簡單的例子介紹了利用Tensorflow實現機器學習的思路,重點講解了下述步驟:

  1. 生成人工資料集及其視覺化
  2. 構建線性模型
  3. 定義損失函式
  4. (梯度下降) 優化過程
  5. 訓練結果的視覺化
  6. 利用學習到的模型進行預測

學習筆記,僅供參考,如有錯誤,敬請指正!

同時釋出在CSDN中:https://blog.csdn.net/tangkcc/article/details/120624865