線性迴歸做爲監督學習中經典的迴歸模型之一,是初學者入門很是好的開始。宏觀上考慮理解性的概念,我想咱們在初中可能就接觸過,y=ax,x爲自變量,y爲因變量,a爲係數也是斜率。若是咱們知道了a係數,那麼給我一個x,我就能獲得一個y,由此能夠很好地爲未知的x值預測相應的y值。這很符合咱們正常邏輯,不難理解。那統計學中的線性迴歸是如何解釋的呢?算法
對於統計模型線性迴歸,我想從如下六個方面來展開,並分兩篇文章進行詳細解讀:app
線性迴歸模型定義dom
線性迴歸的損失函數ide
線性迴歸參數估計函數
線性迴歸預測學習
線性迴歸擬合優度優化
線性迴歸假設檢驗spa
線性迴歸診斷3d
▌線性迴歸模型定義code
線性迴歸按變量數量的多少能夠分爲:一元線性迴歸(簡單線性迴歸)和多元線性迴歸。
一元線性迴歸,也就是有一個自變量,其模型能夠表示以下:
公式中參數解釋以下:
x:自變量
y:因變量
β 0:截距
β 1:變量回歸係數
ϵ:偏差項的隨機變量1
這些參數中,(β 0+β 1x)反映了因爲x的變化而引發的y的線性變化;ϵ反映了除了x和y之間的線性關係以外的隨機因素對y的影響,是不能由x和y之間的線性關係所解釋的變異性。能夠這麼來理解ϵ:咱們對y的預測是不可能達到與真實值徹底同樣的,這個真實值只有上帝知道,所以必然會產生偏差,咱們就用ϵ來表示這個沒法預測的偏差。
一樣的,多元線性迴歸模型的表示以下:
咱們經過引入了ϵ可讓模型達到完美狀態,也就是理論的迴歸模型。可是咱們要如何定義這個沒法預測的偏差項呢?爲此,偉人們提出了一些假設條件:
在統計學中,高斯-馬爾可夫定理陳述的是:在偏差零均值,同方差,且互不相關的線性迴歸模型中,迴歸係數的最佳無偏線性估計(BLUE)就是最小方差估計。
總結一下,有以下幾個主要的假設條件:
(1)偏差項ϵ是一個指望爲0的隨機變量,即E(ϵ)=0
(2)對於自變量的全部值,ϵ的方差σ^2
都相同
(3)偏差項ϵ是一個服從正態分佈的隨機變量,且相互獨立,即ϵ~N(0,σ^2
)
ϵ正態性意味着對於給定的自變量,因變量y也是一個服從正態分佈的隨機變量。根據迴歸模型的假設,有以下多元迴歸方程:
▌線性迴歸的損失函數
從樣本數據考慮,若是想讓咱們預測值儘可能準確,那麼咱們就必須讓真實值與預測值的差值最小,即讓偏差平方和ϵ最小,用公式來表達即:
用平方而沒用偏差絕對值是由於:平方對於後續求導比較方便。
雖然咱們獲得了損失函數,可是若是從統計理論的角度出發來推導損失函數,我認爲更有說服力,也能更好地理解線性迴歸模型,以及爲何開始要提出那些假設條件。
根據上面假設條件:ϵ 服從均值爲0,方差爲σ的正態分佈,且獨立,所以隨機變量ϵ 的機率密度函數(正態分佈的機率密度函數)爲:
咱們把前面的多元線性迴歸模型簡單地變換一下,以下:
而後將獲得的ϵ公式帶入上面機率密度函數:
有了機率密度函數,咱們天然會想到用最大似然估計推導損失函數:
而後咱們將似然函數取對數,這樣能夠將機率密度的乘法轉換爲加法:
再而後咱們對似然函數取最大值,即最大化似然函數:
這樣咱們就從統計理論的角度獲得了咱們要找的損失函數,與咱們最小化偏差平方和獲得的結果是同樣的,也從側面證明了前面提出假設的正確性。所以,多元線性迴歸模型的損失函數爲:
公式裏的1/2對損失函數沒有影響,只是爲了能抵消求導後的乘數2。
▌線性迴歸參數估計
損失函數只是一種策略,有了策略咱們還要用適合的算法進行求解。在線性迴歸模型中,求解損失函數就是求與自變量相對應的各個迴歸係數和截距。有了這些參數,咱們才能實現模型的預測(輸入x,給出y)。
對於偏差平方和損失函數的求解方法有不少,典型的如最小二乘法,梯度降低等。下面咱們分別用這兩種方法來進行求解。
最小二乘法
最小二乘法能夠將偏差方程轉化爲有肯定解的代數方程組(其方程式數目正好等於未知數的個數),從而可求解出這些未知參數。這個有肯定解的代數方程組稱爲最小二乘法估計的正規方程。
咱們將代數方程組用矩陣來代替能夠簡化推導過程,以及代碼實現。
這裏會涉及到矩陣求導的用法,詳細介紹請看下面wiki的參考連接:
https://en.wikipedia.org/wiki/Matrix_calculus#Scalar-by-vector_identities
咱們令上面獲得的公式等於0,便可獲得最終的求解:
Python中對於矩陣的各類操做能夠經過Numpy庫的一些方法來實現,很是方便。但在這個代碼實現中須要注意:X矩陣不能爲奇異矩陣,不然是沒法求解矩陣的逆的。下面是手擼最小二乘法的代碼實現部分。
def standRegres(xArr,yArr):
"""
函數說明:計算迴歸係數w
Parameters:
xArr - x數據集
yArr - y數據集
Returns:
ws - 迴歸係數
"""
xMat = np.mat(xArr); yMat = np.mat(yArr).T
#根據文中推導的公示計算迴歸係數
xTx = xMat.T * xMat
if np.linalg.det(xTx) == 0.0:
print("矩陣爲奇異矩陣,不能求逆")
return
ws = xTx.I * (xMat.T*yMat)
return ws
梯度降低法
梯度降低是另外一種經常使用的方法,能夠用來求解凸優化問題。它的原理有別於最小二乘法,它是經過一步步迭代(與最小二乘法的區別在後面介紹)求解,不斷逼近正確結果,直到與真實值之差小於一個閾值,從而獲得最小化損失函數的模型參數值的。它的公式以下:
對於損失函數的梯度(即求偏導的過程),上面在最小二乘法部分已經給出推導過程和結果。不一樣的是,咱們不會將公式等於0來求極值,而是帶入上面梯度下面公式來迭代完成求解,如下是梯度降低矩陣形式的最終求解結果。
最小二乘法 vs 梯度降低法
經過上面推導,咱們不難看出,兩者都對損失函數的迴歸係數進行了求偏導,而且所獲得的推導結果是相同的,那麼究竟哪裏不一樣呢?
若是仔細觀察,能夠觀察到:最小二乘法經過使推導結果等於0,從而直接求得極值,而梯度降低則是將推導結果帶入迭代公式中,一步一步地獲得最終結果。簡單地說,最小二乘法是一步到位的,而梯度降低是一步步進行的。
於是經過以上的異同點,總結以下
最小二乘法:
獲得的是全局最優解,由於一步到位,直接求極值,於是步驟簡單
線性迴歸的模型假設,這是最小二乘方法的優越性前提,不然不能推出最小二乘是最佳(即方差最小)的無偏估計
梯度降低法:
獲得的是局部最優解,由於是一步步迭代的,而非直接求得極值
既能夠用於線性模型,也能夠用於非線性模型,沒有特殊的限制和假設條件
▌線性迴歸預測
上面咱們已經手擼了最小二乘法和梯度降低法求解偏差平方和損失函數的過程,即咱們經過以上算法已經獲得了咱們想要的參數值。固然,咱們也可使用statsmodels或者sklearn庫中已經被封裝好了的模型來進行預測。不過,爲了更好的瞭解模型,優化算法,而不只僅是作一個調包俠,咱們最好對每種算法都本身實現一遍。
爲了更好的說明整個建模到預測的過程,咱們經過一個例子來詳細說明。對於一個數據集,咱們經過本身手擼的最小二乘法來建模,求解參數而後進行預測。
class LeastSquared(object):
def __init__(self):
self.xArr = []
self.yArr = []
self.params = []
self.y_predict = []
def fit(self,xArr,yArr):
self.xArr = xArr
self.yArr = yArr
xMat = np.mat(xArr)
yMat = np.mat(yArr).T
xTx = xMat.T*xMat
if np.linalg.det(xTx) == 0.0:
print('矩陣爲奇異矩陣')
params = xTx.I*(xMat.T*yMat)
self.params = params
def predict(self,x_new):
y_predict = x_new*self.params
self.y_predict = y_predict
return y_predict
能夠看到這是一個簡單的二維平面,藍色表明一個變量X和因變量Y的散點圖,紅色是咱們經過最小二乘法擬合出來的直線。若是是多自變量,那麼擬合結果將是一個平面,或者超平面。使用這個模型,咱們就能對未知的X值進行預測。
而後,咱們在x的範圍內再取10個隨機數,並進行預測感覺一下。
# 生成最小二乘法類
xArr, yArr = loadDataSet('ex0.txt')
ls = LeastSquared()
ls.fit(xArr,yArr) #訓練模型
y_predict = ls.predict(xArr) #預測模型
# 在x範圍內,隨機生成10個新的x值
x_min = np.min(np.array(xArr)[:,1])
x_max = np.max(np.array(xArr)[:,1])
x_random = np.random.uniform(x_min,x_max,[10,1])
x_new = np.c_[np.ones(10),x_random.flatten()]
y_new = ls.predict(x_new)
y_new = y_new.flatten().tolist()[0]
x_new = x_random.flatten().tolist()
# 可視化
n = len(xArr)
xcord = [];ycord = [];y_hat = []
for i in range(n):
xcord.append(xArr[i][1])
ycord.append(yArr[i])
y_hat.append(y_predict.tolist()[i][0])
fig = plt.figure()
#添加subplot
ax = fig.add_subplot(111)
#繪製樣本點
ax.plot(xcord, y_hat, c = 'red')
ax.scatter(xcord, ycord, s = 20, c = 'blue',alpha = .5)
ax.scatter(x_new,y_new, s=150, c='r', alpha = 0.8)
#繪製title
plt.title('LeastSquareMethod')
plt.xlabel('X')
plt.show()
這時咱們看到,生成的10個隨機數都在咱們的擬合直線上,對應的y值就是咱們的預測值。一樣的,咱們也手擼了梯度降低算法進行的求解過程,兩者獲得的結果參數幾乎相等。兩者可視化效果以下所示(能夠看到兩個擬合直線是重合的,紅色和綠色):
兩者所得參數對好比下,其中梯度降低迭代了500次,能夠看到參數結果是幾乎同樣的。
#最小二乘法
ls.params
>>matrix([[3.00774324],
[1.69532264]])
#梯度降低法,迭代500次
gd.params
>>matrix([[3.00758726],
[1.69562035]])
▌總結
本篇主要介紹了線性迴歸的前幾個部分:模型定義假設,模型參數估計,模型預測。可是預測完模型以後,咱們並不知道結果時好時壞,而且咱們也不知道開始的假設是否成立,這些內容涉及模型擬合優度,模型假設檢驗,和模型診斷,將在下一篇進行介紹。