Python 機器學習算法一之線性迴歸的推導及實戰

機器學習 算法 Python 銀行 編程python新視野 2019-06-18

線性迴歸是機器學習中最基本的算法了,一般要學習機器學習都要從線性迴歸開始講起,本節就對線性迴歸做一個詳細的解釋。

實例引入

在講解線性迴歸之前,我們首先引入一個實例,張三、李四、王五、趙六都要貸款了,貸款時銀行調查了他們的月薪和住房面積等因素,月薪越高,住房面積越大,可貸款金額越多,下面列出來了他們四個人的工資情況、住房面積和可貸款金額的具體情況:

姓名 工資(元) 房屋面積(平方) 可貸款金額(元) 張三 6000 58 30000 李四 9000 77 55010 王五 11000 89 73542 趙六 15000 54 63201 看到了這樣的數據,又來了一位孫七,他工資是 12000 元,房屋面積是 60 平,那他大約能貸款多少呢?

思路探索

那這時候應該往哪方面考慮呢?如果我們假定可貸款金額和工資、房屋面積都是線性相關的,要解決這個問題,首先我們想到的應該就是初高中所學的一次函數吧,它的一般表達方式是 y=wx+b

,x 就是自變量,y 就是因變量,w 是自變量的係數,b 是偏移量,這個式子表明 y 和 x 是線性相關的,y 會隨著 x

的變化而呈現線性變化。

現在回到我們的問題中,情況稍微不太一樣,這個例子中是可貸款金額會隨著工資和房屋面積而呈現線性變化,此時如果我們將工資定義為 x1

,房屋面積定義為 x2,可貸款金額定義為 y,那麼它們三者的關係就可以表示為: y=w1x1+w2x2+b,這裡的自變量就不再是一個了,而是兩個,分別是 x1 和 x2,自變量係數就表示為了 w1 和 w2

,我們將其轉化為表達的形式,同時將變量的名字換一下,就成了這個樣子:

$$

h_{theta}(x) = theta_0 + theta_1x_1 + theta_2x_2

$$

這裡只不過是將原表達式轉為函數形式,換了個表示名字,另外參數名稱從 w

換成了 theta,b 換成了 theta0,為什麼要換?因為在機器學習算法中 theta

用的更廣泛一些,約定俗成。

然後這個問題怎麼解?我們只需要求得一組近似的 theta

參數使得我們的函數可以擬合已有的數據,然後整個函數表達式就可以表示出來了,然後再將孫七的工資和房屋面積代入進去,就求出來他可以貸款的金額了。

思路拓展

那假如此時情景變一變,變得更復雜一些,可貸款金額不僅僅和工資、房屋面積有關,還有當前存款數、年齡等等因素有關,那我們的表達式應該怎麼寫?不用擔心,我們有幾個影響因素,就寫定義幾個變量,比如我們可以將存款數定義為 x3

,年齡定義為 x4,如果還有其他影響因素我們可以繼續接著定義,如果一共有 n 個影響因素,我們就定義到 xn

,這時候函數表達式就可以變成這樣子了:

$$

h_{theta}(x) = theta_0 + theta_1x_1 + theta_2x_2 + … + theta_nx_n

$$

這個式子看起來挺長的不好寫的吧,我們可以使用求和公式寫成如下形式:

$$

h_{\theta}(x) = \sum_{i=0}^{n}\theta_ix_i = \theta^Tx

$$

如果要使得這個公式成立,這裡需要滿足一個條件就是 x0=1

,其實在實際場景中 x0 是不存在的,因為第一個影響因素我們用 x1 來表示了,第二個影響因素我們用 x2 來表示了,依次類推。所以這裡我們直接指定 x0=1

即可。

後來我們又將公式簡化為線性代數的向量表示,這裡 thetaT

是 theta 向量轉置的結果,而 theta 向量又表示為 (theta0,theta1,…,thetan),同樣地,x 向量可以表示為 (x0,x1,…,xn)

,總之,表達成後面的式子,看起來更簡潔明瞭。

好了,這就是最基本的線性判別解析函數的寫法,是不是很簡單。

實際求解

那接下來我們怎樣實際求解這個問題呢?比如拿張三的數據代入到這個函數表達式中,這裡還是假設有兩個影響因素,張三的數據我們可以表示為 x(1)1=6000,x(1)2=58,y(1)=30000

,注意這裡我們在數據的右上角加了一個小括號,裡面帶有數字,如果我們把張三的數據看成一個條目,那麼這個數字就代表了這個條目的序號,1 就代表第一條數據,2 就代表第二條數據,為啥這麼寫?也是約定俗成,以後也會經常採用這樣的寫法,記住就好了。

所以,我們的願景是要使得我們的函數能夠擬合當前的這條數據,所以我們希望是這樣的情況:

$$

y^{(1)} = sum {i=0}^{n}theta {i}x_{i}^{(1)} = theta^Tx^{(1)}

$$

其中 y(1)

是真實值,但我們知道,哪有那麼容易十全十美,絲毫不差的擬合函數,所以上面的式子一般來說是不成立的,函數計算值和真實值還是多少還是有一定的誤差的吧,如果我們想知道函數真實擬合的結果的話,我們需要把 x

變量代入函數,會得到一個函數本身擬合的結果,是這樣的:

$$

h_{\theta}(x^{(1)}) = \sum_{i=0}^{n}\theta_{i}x_{i}^{(1)} = \theta^Tx^{(1)}

$$

這裡的 htheta(x(1))

就是我們函數得到的結果了。一般來說,二者是會存在一定的誤差的,所以誤差我們一般可以寫成他們的差的絕對值或平方的形式,使用絕對值或平方的目的是消去正負號的影響,比如寫成平方的形式就是這樣子:

$$

(h_{\theta}(x^{(1)}) – y^{(1)})^2

$$

這個式子就是我們函數真實擬合值和真實值之間的差距,沒問題吧。

相應的,如果是李四的數據,誤差就可以寫為:

$$

(h_{\theta}(x^{(2)}) – y^{(2)})^2

$$

依次類推,如果是第 i

條數據,誤差就可以寫成:

$$

(h_{\theta}(x^{(i)}) – y^{(i)})^2

$$

要使得我們的函數對所有的數據都能儘量很好地擬合,我們可以把這些誤差加起來求個平均,假設一共 m

條數據,那麼所有數據的誤差可以寫成如下形式:

$$

J(\theta) = \dfrac{1}{2m}\sum_{i=1}^{m}(h_\theta(x^{(i)}) – y^{(i)})^2

$$

注意這裡 i

指的是第幾條數據,是從 1 開始的,一直到 m 為止,然後使用了求和公式對每一條數據的誤差進行累加和,最後除以了 2m,我們的最終目的就是找出合適的 theta,使得這個 J(theta) 的值最小,即誤差最小,在機器學習中,我們就把 J(theta)

稱為損失函數(Loss Function),即我們要使得損失值最小。

有的小夥伴可能好奇損失函數前面為什麼是 2m

,而不是 m

?因為我們後面要用到這個算式的導數,所以這裡多了個 2 是為了便於求導計算。況且一個表達式要求最小值,前面乘一個常數是對結果沒影響的。

求解過程

由於我們求解的是線性迴歸問題,所以整個損失函數的圖像非常簡單清晰,如果只有 theta1

和 theta2 兩個參數,我們甚至可以直接畫出其圖像,整個損失函數大小隨 theta1 和 theta2

的變化實際上類似於這樣子:

Python 機器學習算法一之線性迴歸的推導及實戰

可以看到這是一個凸函數,豎軸代表損失函數的大小,橫縱兩軸代表 theta1

和 theta2 的變化,可見在中間的最低谷損失函數取得最小值,這時候損失函數在 theta1 和 theta2 上的導數都是 0,因此我們可以一步到位,直接用偏導置零的方式來求解損失函數取得最小值時的 theta

值的大小。

所以我們可以先對每個 theta

求解其偏導結果,這裡 theta 表示為 thetaj,代表 theta

中的某一維:

$$

dfrac{partial{J(theta)}}{partial{theta j}} = dfrac{1}{2m} dfrac{partial({sum {i=1}^{m}{(y^{(i)} – h_{theta}(x^{(i)}))^2}})}{partial{theta j}} \

{i=1}^{m}((h_{theta}(x^{(i)}) – y^{(i)})x_j^{(i)})

$$

直接將偏導置零即可直接求解 $ theta j $:

$$

{i=1}^{m} {h_{theta}(x^{(i)})x j^{(i)}} – sum {i=1}^{m}y^{(i)}x_j^{(i)} = 0

$$

這裡將所有數據代入,即可通過求解方程組的形式直接解出 thetaj

的值,但這些方程組裡面其實 thetaj

之間存在彼此依賴關係,需要聯立求解出來。

如果不用這種求解方式,我們可以使用梯度下降的方式來進行求解,在這裡 thetaj

只需要逐步更新即可:

$$

theta_j = theta_j – alphadfrac{partial{J(theta)}}{partial{theta_j}} \

= theta j – dfrac{alpha}{m}sum {i=1}^{m}((h_{theta}(x^{(i)}) – y^{(i)})x_j^{(i)})

$$

這裡 alpha

就是學習率,thetaj 每經過一步都會進行一次更新,得到新的結果,經過梯度下降過程,thetaj 都會更新為使得梯度最小化的數值,最後就完成了 theta

的求解。

以上便是線性迴歸的整個推導和求解過程。

實戰操作

現在呢,我們想要根據前面的數據來求解這個真實的問題,為了解決這個問題,我們在這裡用 Python 的 Sklearn 庫來實現。

對於線性迴歸來說,Sklearn 已經做好了封裝,直接使用 LinearRegression 即可。

它的 API 如下:

class sklearn.linear_model.LinearRegression(fit_intercept=True, normalize=False, copy_X=True, n_jobs=None)

參數解釋如下:

  • fit_intercept : 布爾值,是否使用偏置項,默認是 True。
  • normalize : 布爾值,是否啟用歸一化,默認是 False。當 fit_intercept 被置為 False 的時候,這個參數會被忽略。當該參數為 True 時,數據會被歸一化處理。
  • copy_X : 布爾值,默認是 True,如果為 True,x 參數會被拷貝不會影響原來的值,否則會被複寫。
  • n_jobs:數值或者布爾,如果設置了,則多核並行處理。

屬性如下:

  • coef_:x 的權重係數大小
  • intercept_:偏置項大小

代碼實現如下:

from sklearn.linear_model import LinearRegression
Python學習交流群:1004391443
x_data = [
[6000, 58],
[9000, 77],
[11000, 89],
[15000, 54]
]
y_data = [
30000, 55010, 73542, 63201
]

lr = LinearRegression()
lr.fit(x_data, y_data)
print('方程為:y={w1}x1+{w2}x2+{b}'.format(w1=round(lr.coef_[0], 2),
w2=round(lr.coef_[1], 2),
b=lr.intercept_))
x_test = [[12000, 60]]
print('住房面積為:', lr.predict(x_test)[0])

運行結果:

方程為:y=4.06x1+743.15x2+-37831.862532707615
住房面積為:55484.33779181102

在這裡我們首先聲明瞭 LinearRegression 對象,然後將數據整合成 x_data 和 y_data 的形式,然後通過調用 fit() 方法來對數據進行擬合。

擬合完畢之後,LinearRegression 的 coef_ 對象就是各個 x 變量的權重大小,即對應著 $ theta_1, theta 2 $,intercept 則是偏移量,對應著 theta0

,這樣我們就可以得到一個線性迴歸表達式了。

然後我們再調用 predict() 方法,將新的測試數據傳入,便可以得到其預測結果,最終結果為 55484.34,即孫七的可貸款額度為 55484.34 元。

以上便是機器學習中線性迴歸算法的推導解析和相關調用實現。

相關推薦

推薦中...