線性迴歸之梯度下降法求解實踐學習筆記(Python)

我通過簡單、比較容易理解的一元線性迴歸爲例,入門掌握機器學習、深度學習中基本概念和方法,例如梯度下降、代價函數、學習率等,以及與傳統統計學不一樣等思維和方法。

1. 關於線性迴歸

迴歸分析是研究相關關係的一種數學工具。他能幫助我們從一個變量取得的值去估計另一變量所取的值。例如人的身高與體重之間存在着關係,一般來說,人身高一些,則體重要重一些;再例如房價與房屋面積的關係,往往房屋面積大,房價高些。

1.1. 線性迴歸

在統計學中,線性迴歸是指:利用稱爲線性迴歸方程的最小平方函數,對一個或多個自變量和因變量之間關係進行建模的一種迴歸分析。線性迴歸方程的損失函數通常是通過最小二乘法,或者梯度下降法進行求解。
在這裏插入圖片描述

1、一元線性迴歸
兩個變量(自變量、因變量)的關係用一條直線來模擬。
hθ(x)=θ0+θ1x1h_{\theta }(x)=\theta_{0}+\theta_{1}x_{1}
這個方程對應的圖像是一條直線,稱作迴歸線。其中, 𝜃1爲迴歸線的斜率, 𝜃0爲迴歸線的截距,x爲自變量。(附演示代碼中:𝜃1爲k和k_grad,𝜃0爲b和b_grad)

2、多元線性迴歸
當Y值的影響因素不是唯一時,採用多元線性迴歸模型,hθ(x)=θ0+θ1x1h_{\theta }(x)=\theta_{0}+\theta_{1}x_{1}模型如下所示:
在這裏插入圖片描述

1.2. 最小二乘

所謂最小二乘,其實也可以叫做最小平方和,其目的就是通過最小化誤差的平方和,使得擬合對象無限接近目標對象。換句話說,最小二乘法可以用於對函數的擬合。

1.3. 標準方程法

一般線性迴歸公式表示爲y=wx+by = w\cdot x + b,利用矩陣的知識對線性公式進行整合:
對於只有兩個特徵(x1,x2)的時候的線性迴歸式子爲hθ(x)=θ1x1+θ2x2h_{\theta }(x)=\theta_{1}x_{1}+\theta_{2}x_{2},假如有n個特徵,則爲hθ(x)=i=1nθi.xih_{\theta }(x)=\sum_{i=1}^{n}\theta_{i}.x_{i},矩陣表達方式如下:

[θ1θ2...θi].[x1,x2,...,xi]=i=1nθi.xi\begin{bmatrix} \theta_{1}\\ \theta_{2}\\ .\\ .\\ .\\ \theta_{i} \end{bmatrix}.\begin{bmatrix} x_{1},&x_{2},&...&,x_{i} \end{bmatrix}=\sum_{i=1}^{n}\theta_{i}.x_{i}

我們把多項式求和化簡爲hθ(x)=θT.xh_{\theta }(x)=\theta^{T}.x,式子中除了w.x,還有一個參數b,也就是偏移量,或者叫誤差項,誤差項是真實值與預測值之間的差距,我們希望誤差項越小越好。hθ(x)=θT.x+εh_{\theta }(x)=\theta^{T}.x+\varepsilon。誤差ε(i)\varepsilon^{(i)}是獨立並且具有相同的分佈,並且服從均值爲0方程爲θ2\theta^2的高斯分佈。

J(θ)=12mi=1m(yiθTxi)2 J(\theta )=\frac{1}{2m}\sum_{i=1}^{m}(y_{i}-\theta^{T}x_{i})^2

線性迴歸參數Θ=(XTX)1XTY\Theta = (X^TX)^{-1}X^TY

2. 機器學習之線性迴歸

2.1. 梯度下降

梯度下降法的基本思想可以類比爲一個下山的過程。假設這樣一個場景:一個人被困在山上,需要從山上下來(找到山的最低點,也就是山谷)。但此時山上的濃霧很大,導致可視度很低。因此,下山的路徑就無法確定,他必須利用自己周圍的信息去找到下山的路徑。這個時候,他就可以利用梯度下降算法來幫助自己下山。具體來說就是,以他當前的所處的位置爲基準,尋找這個位置最陡峭的地方,然後朝着山的高度下降的地方走,然後每走一段距離,都反覆採用同一個方法,最後就能成功的抵達山谷。
在這裏插入圖片描述
首先理解什麼是梯度?通俗來說,梯度就是表示某一函數中該點處點方向導數沿着該方向取得最大值,即函數在當前位置的導數。屬於優化算法。
在這裏插入圖片描述

2.2. 學習率

學習率(Learning rate)作爲監督學習以及深度學習中重要的超參,其決定着目標函數能否收斂到局部最小值以及何時收斂到最小值。合適的學習率能夠使目標函數在合適的時間內收斂到局部最小值。

學習速率是指導我們該如何通過損失函數的梯度調整網絡權重的超參數。學習率越低,損失函數的變化速度就越慢。雖然使用低學習率可以確保我們不會錯過任何局部極小值,但也意味着我們將花費更長的時間來進行收斂,特別是在被困在高原區域的情況下。

注:附代碼中的lr爲學習率。

2.3. 損失/代價函數

給定變量x,則擬合/預測函數輸出一個f(x),這個輸出的f(x)與真實值y存在一定的誤差,爲了表示我們擬合的好壞,我們就用一個函數來度量擬合的程度,比如: L(yf(x))=(yf(x))2L(y-f(x))=(y-f(x))^2,這個函數就稱爲損失函數(loss function),或者叫代價函數(cost function)。損失函數越小,就代表模型擬合的越好。

注:損失函數與代價函數在概念定義上有微小差別,損失函數是指單組數據,代價函數是指數據集上的損失平均值,在機器學習上沒有本質的差別,可以等同。

最小二乘法代價函數

對於一元線性迴歸方程:hθ(x)=θ0x1+θ1x2h_{\theta }(x)=\theta_{0} x_{1}+\theta_{1}x_{2},真實值爲y,預測值爲hθ(x)h_\theta (x),找到合適的參數,使得誤差平方和最小。
J(θ0,θ1)=12mi=1m(yihθ(xi))2 J(\theta_0 , \theta_1)=\frac{1}{2m}\sum_{i=1}^{m}(y_{i}-h_\theta(x_{i}))^2

2.4. 用梯度下降法來求解線性迴歸

最小二乘法的求解,對最小二乘法代價函數J(θ0,θ1)J(\theta_0 ,\theta_1),求導θjJ(θ0,θ1)\frac{\partial }{\partial \theta_j}J(\theta_0 ,\theta_1),使用泰勒展開式,例如j=1時,即對θ1求導。
在這裏插入圖片描述
j=0:θjJ(θ0,θ1)=1mi=1m(hθ(x(i)y(i)) j=0: \frac{\partial }{\partial \theta_j}J(\theta_0 ,\theta_1) = \frac{1}{m} \sum_{i=1}^{m}(h_\theta(x^{(i)} - y^{(i)})

j=1:θjJ(θ0,θ1)=1mi=1m(hθ(x(i)y(i))x(i) j=1: \frac{\partial }{\partial \theta_j}J(\theta_0 ,\theta_1) = \frac{1}{m} \sum_{i=1}^{m}(h_\theta(x^{(i)} - y^{(i)})\cdot x^{(i)}

重複直到收斂

repeat until convergence{
θ0:=θ0α1mi=1m(hθ(x(i)y(i)) \theta_0 := \theta_0 - \alpha \frac{1}{m} \sum_{i=1}^{m}(h_\theta(x^{(i)} - y^{(i)})

θ1:=θ1α1mi=1m(hθ(x(i)y(i))x(i) \theta_1 := \theta_1 - \alpha \frac{1}{m} \sum_{i=1}^{m}(h_\theta(x^{(i)} - y^{(i)})\cdot x^{(i)}
}

上述公式中的α是學習率。

2.5. 梯度下降法與標準方程法比較

內容 梯度下降法 標準方程法
優點 當特徵值非常多多時候也可以很好的工作 不需要學習率
不需要迭代
可以得到全局最優解
缺點 需要選擇合適的學習率 需要計算(XTX)1(X^TX)^{-1}
需要迭代很多個週期 時間複雜度大約是特徵數量的立方
只能得到最優解的近視值

3. 參考代碼

'''
Created on 2019年2月16日
@author: 肖永威
'''
import matplotlib.pyplot as plt
import numpy as np

data = np.genfromtxt("data.csv", delimiter=",")
x_data = data[:,0]
y_data = data[:,1]
plt.scatter(x_data,y_data)
plt.show()

# 學習率learning rate
lr = 0.0001
# 截距
b = 0
# 斜率
k = 0
# 最大迭代次數
epochs = 50

# 最小二乘法
def compute_error(b, k, x_data, y_data):
    totalError = 0
    for i in range(0, len(x_data)):
        totalError += (y_data[i] - (k * x_data[i] + b)) ** 2
    return totalError / float(len(x_data)) / 2.0


def gradient_descent_runner(x_data, y_data, b, k, lr, epochs):
    # 計算總數據量
    m = float(len(x_data))
    # 循環epochs次
    for i in range(epochs):
        b_grad = 0
        k_grad = 0
        # 計算梯度的總和再求平均
        for j in range(0, len(x_data)):
            b_grad += (1/m) * (((k * x_data[j]) + b) - y_data[j])
            k_grad += (1/m) * x_data[j] * (((k * x_data[j]) + b) - y_data[j])
        # 更新b和k
        b = b - (lr * b_grad)
        k = k - (lr * k_grad)
        # 每迭代5次,輸出一次圖像

    return b, k

print("Starting b = {0}, k = {1}, error = {2}".format(b, k, compute_error(b, k, x_data, y_data)))
print("Running...")
b, k = gradient_descent_runner(x_data, y_data, b, k, lr, epochs)
print("After {0} iterations b = {1}, k = {2}, error = {3}".format(epochs, b, k, compute_error(b, k, x_data, y_data)))

# 畫圖
plt.plot(x_data, y_data, 'b.')
plt.plot(x_data, k*x_data + b, 'r')
plt.show()

數據樣本圖及擬合結果:
在這裏插入圖片描述

Starting b = 0, k = 0, error = 2782.5539172416056
Running...
After 50 iterations b = 0.030569950649287983, k = 1.4788903781318357, error = 56.32488184238028

梯度下降,迭代過程圖像如下:
在這裏插入圖片描述
參考:
《機器學習算法基礎》 覃秉豐
《線性迴歸(最小二乘法)》 博客園 LeonHuo 2016.12

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章