一元線性回歸
由於筆者的數學不太好,而且網上關於一元線性回歸的文章有很多,所以相關內容大家可以查找一下,這里我就簡單的搬運一下簡單概念。
一元線性回歸的方程:
h ( x ) = β 0 + β 1 x h(x)=β_0+β_1x h(x)=β0+β1x
其中第一個參數 β 0 β_0 β0為截距,第二個參數 β 1 β_1 β1為斜率。
代價函數
回歸分析的主要目的是通過已有的信息,去推測出未知的信息。通過一個例子大家可能會更深刻的理解回歸分析的目的。
上圖為廣告費與銷售額的關系圖,虛線為我們的一元線性回歸方程,通過回歸分析,我們可以預測當廣告費為14萬元時,我們的銷售額可能是30萬元。
回歸分析屬於統計學問題,這就說明在給定自變量x時,我們是無法准確的得出因變量y的。但是我們可以通過一些方法去**“減少誤差”**,使得預測的結果盡量的接近真實值。所以我們引入了代價函數,其使用最小二乘法的理論去減少這種誤差。代價函數數學公式如下:
J ( β 0 , β 1 ) = 1 2 m ∑ i = 1 m [ y i − h ( x i ) ] 2 J(β_0,β_1)=\frac{1}{2m}\sum_{i=1}^m[y_i-h(x_i)]^2 J(β0,β1)=2m1i=1∑m[yi−h(xi)]2
為了更好的理解代價函數,這里使第一個參數為零,然后觀察一下圖片(由於是從視頻中截取的圖片,所以這里的參數又β變成了θ,是我太懶了😂)
當θ=1時,此時回歸方程貫穿每一個點,所以誤差為零,J(θ)值如右圖所示。
當θ=0.5時,我們一頓計算可得,J(θ)≈0.58
當θ=0時,我們同樣可以計算出J(θ)的值。
如果我們大量的將θ帶入,我們將得到如下的代價函數圖
由此我們可以清晰地看到,J(θ)在某一點處是可以取到最小值的,這就是我們的引入代價函數的目的:通過調整參數來減少誤差,使得預測的結果盡量的接近真實值。
注:最小二乘法的公式如下:
∑ [ y i − ( β 0 + β 1 x i ) ] 2 \sum[y_i-(β_0+β_1x_i)]^2 ∑[yi−(β0+β1xi)]2
梯度下降法
梯度下降法就是一個很好的調整參數的方法,它可以通過下面公式不斷調整 β 0 β_0 β0和 β 1 β_1 β1的值,從而得到一個全局最小值,或者是一個局部最小值。
r e p e a t u n t i l c o n v e r g e n c e { β j = β j − α ∂ ∂ β j J ( β 0 , β 1 ) f o r j = 1 a n d j = 0 } repeat\ \ \ until\ \ \ convergence\{ \\ β_j = β_j - α\frac{∂}{∂β_j}J(β_0,β_1) \\ for\ j = 1\ and\ j=0 \\ \} repeat until convergence{βj=βj−α∂βj∂J(β0,β1)for j=1 and j=0}
其中α稱為學習率(learning rate),而學習率就是步長,學習率大,一次跨越的距離就遠,這樣可能會錯過全局(局部)最小值點;學習率小,一次跨越的距離就短,這樣會花費比較多的時間來處理數據。
求偏導后:
j = 0 : β 0 = β 0 − α ( 1 m ∑ i = 1 m ( y i − β 0 − β 1 x i ) ∗ − 1 ) = β 0 − α ( − 1 m ∑ i = 1 m [ y i − ( β 1 x i + β 0 ) ] ) = β 0 − α ( − 1 m ∑ i = 1 m [ y i − ( h ( x i ) ] ) j = 1 : β 1 = β 1 − α ( 1 m ∑ i = 1 m ( y i − β 0 − β 1 x i ) ∗ − x i ) = β 1 − α ( − 1 m ∑ i = 1 m x i [ y i − ( β 1 x i + β 0 ) ] ) = β 1 − α ( − 1 m ∑ i = 1 m x i [ y i − ( h ( x i ) ] ) j=0:β_0 = β_0-α(\frac{1}{m}\sum_{i=1}^m(y_i-β_0-β_1x_i)*-1) \\ \ \ \ \ \ \ \ \ \ \ \ \ \ =β_0-α(-\frac{1}{m}\sum_{i=1}^m[y_i-(β_1x_i+β_0)]) \\ \ \ \ =β_0-α(-\frac{1}{m}\sum_{i=1}^m[y_i-(h(x_i)]) \\ j=1:β_1=β_1-α(\frac{1}{m}\sum_{i=1}^m(y_i-β_0-β_1x_i)*-x_i) \\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =β_1-α(-\frac{1}{m}\sum_{i=1}^mx_i[y_i-(β_1x_i+β_0)]) \\ \ \ \ \ =β_1-α(-\frac{1}{m}\sum_{i=1}^mx_i[y_i-(h(x_i)]) j=0:β0=β0−α(m1i=1∑m(yi−β0−β1xi)∗−1) =β0−α(−m1i=1∑m[yi−(β1xi+β0)]) =β0−α(−m1i=1∑m[yi−(h(xi)])j=1:β1=β1−α(m1i=1∑m(yi−β0−β1xi)∗−xi) =β1−α(−m1i=1∑mxi[yi−(β1xi+β0)]) =β1−α(−m1i=1∑mxi[yi−(h(xi)])
代碼實現:
import numpy as np
import matplotlib.pyplot as plt
#載入數據
data = np.genfromtxt("data.csv",delimiter=",")#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)*(y_data[j]-(k * x_data[j] + b))
k_grad += -(1/m)*x_data[j] * (y_data[j] - (k * x_data[j] + b))
#更新b和k
b = b - (lr * b_grad)
k = k - (lr * k_grad)
# 每迭代5次,輸出一次圖像
''' 方面查看變化趨勢 if i % 5==0: print("epochs:",i) plt.plot(x_data, y_data, 'b.') plt.plot(x_data, k*x_data + b, 'r') plt.show() '''
return b, k
b, k = gradient_descent_runner(x_data, y_data, b, k, lr, epochs)
#畫圖
plt.scatter(x_data, y_data, c='b')
plt.plot(x_data, k*x_data + b, 'r')
plt.show()