線性迴歸——最小二乘法(公式推導和非調包實現)

接上一篇文章【線性迴歸——二維線性迴歸方程(證明和代碼實現)】

前言:
博主前面一篇文章講述了二維線性迴歸問題的求解原理和推導過程,以及使用python自己實現算法,但是那種方法只能適用於普通的二維平面問題,今天博主來講一下線性迴歸問題中更爲通用的方法,也是我們實際開發中會經常用到的一個數學模型,常用的解法就是最小二次乘法和梯度下降法.博主今天對最小二乘法進行推導並使用Python代碼自定義實現,廢話不多說,開始吧:

一、公式推導

  • 假如現在有一堆這樣的數據(x1,y1),(x2,y2),,(xn,yn)(x_1,y_1),(x_2,y_2),\dots,(x_n,y_n),然後我們已經通過某種方式得到了數據所對應的模型y^=θ0+θ1x\hat{y}=\theta_0+\theta_1x,但是因爲 y^\hat{y} 畢竟是通過訓練模型所得到的預測值,所以 y^\hat{y}yy 之間必定存在誤差如圖所示:
    在這裏插入圖片描述

也就是說存在一個這樣的等式 ω=y^y\omega=\hat{y}-y 其中 ω\omega 的值代表誤差值.現在不妨我們再來將訓練數據換一下變成(x11,x12,,x1m,y1),(x21,x22,,,x2m,y1),,(xn1,xn2,,xnm,yn)(x_{11},x_{12},\dots,x_{1m},y_1),(x_{21},x_{22},,\dots,x_{2m},y_1),\dots,(x_{n1},x_{n2},\dots,x_{nm},y_n)這裏有n項數據,其中每項數據的前 m 個數據代表特徵值,最後的一個數據代表標籤值(也就是真實的 y 值),對這個數據我們通過線性模型也可以將數據對應的模型寫出來:y^=θ0+θ1x1+θ2x2++θmxm\hat{y}=\theta_0+\theta_1x_1+\theta_2x_2+\cdots+\theta_mx_m不妨簡化一下換成矩陣的形式表示:
y^=i=0nθixi=θTx\displaystyle \hat{y}=\sum_{i=0}^n{\theta_ix_i}=\theta^Tx
其中θ=[θ0θ1θm],xi=[xi0xi1xim],xi0=1\theta=\begin{bmatrix}\theta_0 \\ \theta_1 \\ \vdots \\ \theta_m \end{bmatrix},x_i=\begin{bmatrix}x_{i0}\\x_{i1}\\ \vdots\\x_{im}\end{bmatrix},x_{i0}=1,我們再把 y^\hat{y} 換一個符號表示:
yθ(xi)=i=0mθixi=θTxi\displaystyle y_{\theta}(x_i)=\sum_{i=0}^m{\theta_ix_i}=\theta^Tx_i
上面這個函數方程即表示我們的擬合曲線,再結合我們前面分析的誤差結論可知(因爲誤差值可正可負,這裏加減就無所謂了):
yi=θTxi+ωiy_i=\theta^Tx_i+\omega_i
等式中的 右端項 yiy_i 代表真實的標籤值,等式的左端項 θTxi+ωi\theta^Tx_i+\omega_i 就代表預測值加上誤差值
在這裏插入圖片描述
上圖這個圖應該很眼熟吧,沒錯就是表示正態分佈(也稱高斯分佈)的統計圖,其實現實生活中,誤差的波動性也大多遵循這個規律.是什麼意思呢?我們可以把圖中的橫座標想作誤差值,而縱座標想成概率值,那麼從圖中我們可以發現一個很有意思的規律,誤差值的絕對值越大那麼它出現的概率反而會越小越趨近於0,誤差值在0附近時可以看它們出現的概率是最大的,也就是說那種極大或者極小的誤差值是佔少數的.我們現在要引出一個函數也就是高斯分佈的概率密度函數:
f(xμ)=12πσe((xμ)22σ2)\displaystyle f(x-\mu)= \frac{1}{\sqrt{2\pi}\sigma}e^{\displaystyle (-\frac{(x-\mu)^2}{2\sigma^2})}
不懂概率密度函數的小夥伴也別急,你就把這個函數的自變量想成事件,然後函數的值想作此事件發生的概率即可;

  • 既然誤差遵循這個規律,那麼我們就可以把前面我們得到的模型公式和概率密度函數聯合起來就有:
    {yi=θTxi+ωif(xμ)=12πσe((xμ)22σ2) \begin{cases} y_i=\theta^Tx_i+\omega_i \\ \displaystyle f(x-\mu)= \frac{1}{\sqrt{2\pi}\sigma}e^{\displaystyle (-\frac{(x-\mu)^2}{2\sigma^2})} \end{cases}
    ωi\omega_i 代入概率密度函數就有:
    f(ωi)=12πσe((yiθTxi)22σ2) \displaystyle f(\omega_i)=\frac{1}{\sqrt{2\pi}\sigma}e^{\displaystyle (-\frac{(y_i-\theta^Tx_i)^2}{2\sigma^2})}
    我們通常習慣用 p(AB)p(A|B) 來表示B事件發生後A事件發生的概率,前面的公式也就可以變成:
    p(yixi;θ)=12πσe((yiθTxi)22σ2) \displaystyle p(y_i|x_i;\theta)=\frac{1}{\sqrt{2\pi}\sigma}e^{\displaystyle (-\frac{(y_i-\theta^Tx_i)^2}{2\sigma^2})}
    上式即表示我們通過訓練模型得到準確值的概率,這個式子只是求單個數據得到真實值的概率,我們現在要來求全部數據都預測正確的概率,因爲每個預測事件都是相互獨立,的所以求全部正確概率只需要將所有單個的概率乘起來即可,那麼就有:
    L(θ)=i=1np(yixi;θ)=i=1n12πσe((yiθTxi)22σ2) \displaystyle L(\theta)=\prod_{i=1}^n{p(y_i|x_i;\theta)}=\prod_{i=1}^n{\displaystyle \frac{1}{\sqrt{2\pi}\sigma}e^{\displaystyle (-\frac{(y_i-\theta^Tx_i)^2}{2\sigma^2})}}
    這個函數有個官方的名稱叫做似然函數,它表示參數 θ\theta 所對應的模型預測值全部與真實值相匹配的概率,也可以把它看做預測模型與數據的真實模型的相似度,顯然看着上面的式子都很頭大,很難計算,不妨將它轉化一下.兩邊同時取對數:
    lnL(θ)=lni=1n12πσe((yiθTxi)22σ2) \displaystyle \ln{L(\theta)}=\ln{\prod_{i=1}^n{\displaystyle \frac{1}{\sqrt{2\pi}\sigma}e^{\displaystyle (-\frac{(y_i-\theta^Tx_i)^2}{2\sigma^2})}}}
    它表示對數似然函數,這裏圖方便後面化簡就取以 e 爲底的對數,去了對數之後不妨來看有什麼好處,我們來化簡一下:
    因爲對數內部的乘法可以展開爲外部的加法即 log(ab)=loga+logblog{(ab)}=\log{a}+\log{b},所以:
    lnL(θ)=ln12πσe((y1θTx1)22σ2)++ln12πσe((ynθTxn)22σ2) \displaystyle \ln{L(\theta)}=\ln{\displaystyle \frac{1}{\sqrt{2\pi}\sigma}e^{\displaystyle (-\frac{(y_1-\theta^Tx_1)^2}{2\sigma^2})}}+\cdots+\ln{\displaystyle \frac{1}{\sqrt{2\pi}\sigma}e^{\displaystyle (-\frac{(y_n-\theta^Tx_n)^2}{2\sigma^2})}}
    把它在弄好看一點:
    lnL(θ)=i=1nln12πσe((yiθTxi)22σ2) \displaystyle \ln{L(\theta)}=\sum_{i=1}^n{\ln{\displaystyle \frac{1}{\sqrt{2\pi}\sigma}e^{\displaystyle (-\frac{(y_i-\theta^Tx_i)^2}{2\sigma^2})}}}
    再次利用對數的乘法變加法性質展開得:
    lnL(θ)=nln12πσ+inlne((yiθTxi)22σ2) \displaystyle \ln{L(\theta)}=n\ln{\frac{1}{\sqrt{2\pi}\sigma}}+\sum_i^n{\ln{e^{\displaystyle (-\frac{(y_i-\theta^Tx_i)^2}{2\sigma^2})}}}
    我們都知對數有這樣一個性質: logaan=n\log_a{a^n}=n 那麼就有:
    lnL(θ)=nln12πσ+in[(yiθTxi)22σ2] \displaystyle \ln{L(\theta)}=n\ln{\frac{1}{\sqrt{2\pi}\sigma}}+\sum_i^n{\displaystyle \left[-\frac{(y_i-\theta^Tx_i)^2}{2\sigma^2}\right]}
    再把常數因子提到外邊來就有:
    lnL(θ)=nln12πσ1σ212in(yiθTxi)2 \displaystyle \ln{L(\theta)}=n\ln{\frac{1}{\sqrt{2\pi}\sigma}}-{\displaystyle \frac{1}{\sigma^2}\frac{1}{2}}\sum_i^n{(y_i-\theta^Tx_i)^2}
    爲了便於觀察,我們把常數項用 t 來代替掉:
    lnL(θ)=t1t212in(yiθTxi)2 \displaystyle \ln{L(\theta)}=t_1-t_2\frac{1}{2}\sum_i^n{(y_i-\theta^Tx_i)^2}
    因爲 lnL(θ)\ln{L(\theta)} 表示的是訓練模型與真實模型相似值,越大表明訓練模型越趨近於真實模型,根據方程我們可以知道,等式右端第一項 t1(nln12πσ)t_1(n\ln{\frac{1}{\sqrt{2\pi}\sigma}}) 爲一個非負常數,第二項中t2(12σ2)t_2({\displaystyle \frac{1}{2\sigma^2}})也爲非負數,顯然 t212in(yiθTxi)2t_2{\displaystyle \frac{1}{2}\sum_i^n{(y_i-\theta^Tx_i)^2}} 也爲非負數,所以一個正的常數項減去一個非負變量,似然函數的值越大越好,也就是需要讓後面這個非負變量越小那麼似然函數的值也就越大,於是就有:
    J(θ)=12in(yiθTxi)2 J(\theta)=\displaystyle \frac{1}{2}\sum_i^n{(y_i-\theta^Tx_i)^2}
    現在我們目標就是求 maxJ(θ)\max{J(\theta)},我們根據表達式可以看出這是一個開口向上的二次函數,那麼它必定存在一個極值點,而且這個極值點就是函數的最小值,所以我們只需對 J(θ)J(\theta) 進行求導,然後使其等於 0 即可,我們先將上面的式子換一種方式表達:
    我們令:
    X=[x11x1mxn1xnm],Y=[y1yn] X= \begin{bmatrix} x_{11}&\cdots&x_{1m} \\ \vdots&\ddots&\vdots\\ x_{n1}&\cdots&x_{nm} \end{bmatrix}, Y= \begin{bmatrix} y_1 \\ \vdots \\ y_n \end{bmatrix}
    那麼就有:
    J(θ)=12(XθY)T(XθY) J(\theta)=\displaystyle \frac{1}{2}(X\theta-Y)^T(X\theta-Y)
    #######################補充說明(如果上面等式你已經理解是如何來到可以跳過下面的內容)#####################
    可能有小夥伴不知道是如何變換過來的,其實你只要懂矩陣的乘法就可以了,很明顯:
    Xθ=[x11x1mxn1xnm][θ1θm]=[x11θ1++x1mθmxn1θ1++xnmθm]=[θTx1θTxn]X\theta= \begin{bmatrix} x_{11}&\cdots&x_{1m} \\ \vdots&\ddots&\vdots\\ x_{n1}&\cdots&x_{nm} \end{bmatrix} \begin{bmatrix}\theta_{1} \\ \vdots \\ \theta_{m}\end{bmatrix}= \begin{bmatrix} x_{11}\theta_1+&\cdots&+x_{1m}\theta_m \\ \vdots&\ddots&\vdots \\ x_{n1}\theta_1+&\cdots&+x_{nm}\theta_m \end{bmatrix}= \begin{bmatrix} \theta^Tx_1\\ \vdots \\ \theta^Tx_n \end{bmatrix}即它的結果是一個 n 行 1 列的矩陣,那麼:
    (XθY)=[θTx1θTxn][y1yn]=[θTx1y1θTxnyn](X\theta-Y)= \begin{bmatrix} \theta^Tx_1\\ \vdots \\ \theta^Tx_n \end{bmatrix}-\begin{bmatrix} y_1 \\ \vdots \\ y_n \end{bmatrix}=\begin{bmatrix} \theta^Tx_1-y_1\\ \vdots \\ \theta^Tx_n-y_n \end{bmatrix}
    所以:
    (XθY)T(XθY)=[θTx1y1,θTxnyn][θTx1y1θTxnyn]=(θTx1y1)2++(θTxnyn)2=in(yiθTxi)2(X\theta-Y)^T(X\theta-Y)= \begin{bmatrix} \theta^Tx_1-y_1,\cdots \theta^Tx_n-y_n \end{bmatrix} \begin{bmatrix} \theta^Tx_1-y_1\\ \vdots \\ \theta^Tx_n-y_n \end{bmatrix}\\= (\theta^Tx_1-y_1)^2+\cdots+(\theta^Tx_n-y_n)^2\\= \displaystyle \sum_i^n{(y_i-\theta^Tx_i)^2}
    ############################################ 結束 #################################################
  • 現在我們對 J(θ)J(\theta) 進行求偏導那麼就有:
    δ(J(θ))δθ=12δ((XθY)T(XθY))δθ\displaystyle \frac{\delta(J(\theta))}{\delta\theta}=\frac{1}{2}\frac{\delta((X\theta-Y)^T(X\theta-Y))}{\delta\theta}
    將轉置放在裏面來(注意在對含有乘法的項轉置時要將矩陣變換順序):
    δ(J(θ))δθ=12δ((θTXTYT)(XθY))δθ\displaystyle \frac{\delta(J(\theta))}{\delta\theta}=\frac{1}{2}\frac{\delta((\theta^TX^T-Y^T)(X\theta-Y))}{\delta\theta}
    使用分配律將括號展開:
    δ(J(θ))δθ=12δ(θTXTXθYTXθθTXTY+YTY)δθ\displaystyle \frac{\delta(J(\theta))}{\delta\theta}=\frac{1}{2}\frac{\delta(\theta^TX^TX\theta-Y^TX\theta-\theta^TX^TY+Y^TY)}{\delta\theta}
    在最終求導前要先介紹三個矩陣求導的性質:
    性質一:
    如果有 f(A)=ATBAf(A)=A^TBA 那麼 δ(f(A))δA=BA+BTA\displaystyle \frac{\delta(f(A))}{\delta A}=BA+B^TA
    性質二:
    如果有 f(A)=BTAf(A)=B^TA 那麼 δ(f(A))δA=B\displaystyle \frac{\delta(f(A))}{\delta A}=B
    性質三:
    如果有 f(A)=ATBCf(A)=A^TBC 那麼 δ(f(A))δA=BC\displaystyle \frac{\delta(f(A))}{\delta A}=BC
    有了上面三個性質,現在就可以計算上面式子的導數了(先做一下變換,方便使用上面的性質)
    δ(J(θ))δθ=12δ(θT(XTX)θ(XTY)TθθTXTY+YTY)δθ \displaystyle \frac{\delta(J(\theta))}{\delta\theta}= \frac{1}{2}\frac{\delta(\theta^T(X^TX)\theta-(X^TY)^T\theta-\theta^TX^TY+Y^TY)}{\delta\theta}
    利用性質一,二,三可得:
    δ(J(θ))δθ=12[((XTX)θ+(XTX)Tθ)XTYXTY] \displaystyle \frac{\delta(J(\theta))}{\delta\theta}= \frac{1}{2}\left[((X^TX)\theta+(X^TX)^T\theta)-X^TY-X^TY\right]
    將轉置放在擴號中去:
    δ(J(θ))δθ=12[(XTXθ+XTXθ)XTYXTY] \displaystyle \frac{\delta(J(\theta))}{\delta\theta}= \frac{1}{2}\left[(X^TX\theta+X^TX\theta)-X^TY-X^TY\right]
    合併同類項:
    δ(J(θ))δθ=12(2XTXθ2XTY)=XTXθXTY \displaystyle \frac{\delta(J(\theta))}{\delta\theta}= \frac{1}{2}\left(2X^TX\theta-2X^TY\right)=X^TX\theta-X^TY
    因爲我們要求極值點,所以令導數等於0即可:
    δ(J(θ))δθ=XTXθXTY=0 \displaystyle \frac{\delta(J(\theta))}{\delta\theta}=X^TX\theta-X^TY=0
    移項得:
    XTXθ=XTY X^TX\theta=X^TY
    兩邊同時乘以一個(XTX)1(X^TX)^{-1}:
    θ=(XTX)1XTY \theta=(X^TX)^{-1}X^TY
    這樣我們便得到了θ\theta的計算方法

二、代碼實現

  • 有了計算方式,那麼使用代碼來實現就簡單了
  • 先定義計算 θ\theta 的函數
import matplotlib.pyplot as plt
import numpy as np

def train_model(x_data,y_data):
	# 邏輯很簡單就是把求theta的公式實現了一遍
    matrix_x = np.matrix(x_data)
    matrix_y = np.matrix(y_data)
    matrix_x_T = matrix_x.T
    t1 = np.dot(matrix_x_T,matrix_x)
    t1_I = t1.I
    t2 = np.dot(t1_I,matrix_x_T)
    theta = np.dot(t2,matrix_y)
    return theta
  • 定義使用模型進行預測的函數:
def predict(model,x_data):
	# 這裏因爲我們傳入的x_data是 n×m,model是 m×1,所以反過來乘代碼邏輯就會簡單許多
    return np.dot(np.matrix(x_data),model)
  • 加載數據
# 導入自帶的波士頓房價數據
from sklearn.datasets import load_boston
boston_data = load_boston().data

train_x = boston_data[:,:-1]
# 這裏需要注意的波士頓原本數據內只有12個特徵值,前面也說過我們的模型有一個單出來的 theta0
# 那麼我們只需要在數據中認爲的假如一列特徵列,全部置一即可
# 也就是 t_0x_0+t_1x_1+...+t_12x_12
# 我們把方程中的t_0全部變爲1即可
ones_x = np.ones(train_x.shape[0])
train_x = np.column_stack((ones_x,train_x))

train_y = boston_data[:,-1:]
  • 訓練模型
model = train_model(train_x,train_y)
model.shape
# (13,1)
  • 預測數據
p_y = predict(model,train_x)
p_y = np.sort(np.array(p_y)[:,0])
  • 在圖上繪製數據
plt.scatter(np.arange(0,506),np.sort(boston_data[:,-1]),marker="x",c="r",label="label_data")
plt.plot(np.arange(0,506),p_y,label="predict_data")
plt.legend()

在這裏插入圖片描述

寫在最後的話:
感覺這篇文章寫了好久,寫這篇文章發現了幾個自身的問題,矩陣的求導方法還不是很熟悉,矩陣的有一些基本性質有遺忘現象.
感覺線性代數和高數還是要時不時的回去複習一下,不然會越學越吃力,怎麼說了寫博客還是收益挺多了,凡是不能圖快,要是地基都沒打牢,房子搭在高也是會倒的,萬丈高樓平地起.嗯.
最後如果有小夥伴發現文章有什麼錯誤的地方,歡迎指出來,將非常感謝!!!(__)

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