1. 程式人生 > 實用技巧 >08-01 通過線性迴歸瞭解演算法流程

08-01 通過線性迴歸瞭解演算法流程

目錄
更新、更全的《機器學習》的更新網站,更有python、go、資料結構與演算法、爬蟲、人工智慧教學等著你:https://www.cnblogs.com/nickchen121/p/11686958.html

通過線性迴歸帶你瞭解演算法流程

一、1. 1 線性迴歸引入

相信我們很多人可能都有去售樓處買房而無奈回家的行為,就算你沒去過售樓處,相信你也應該聽說過那令人嘆而驚止的房價吧?對於高房價你沒有想過這房價是怎麼算出來的呢?難道就是房地產商拍拍腦門,北京的一概1000萬,上海的一概800萬,杭州的一概600萬嗎?看到這相信你應該有動力想要學好機器學習走向人生巔峰了。

其實仔細想想這房價大有來頭,首先房價不可能只和地區有關,北京有1000萬的房子,又會有800萬、600萬的房子,那這些房價不和地區有關還和什麼有關呢?如果你真的買過房就知道,房子的價格首先和地區是有著比較大的聯絡的,北京五環外的房子可能都高於杭州任何地區的房子,在同一個地區內,房子的價格大多和房子的佔地面積、戶型、採光度等等因素有關係。

這個時候就有某位聰明的投機者想到了,我是不是可以找到一個方法來預測房價呢?如果這個房子的房價明顯小於這所房子該有的房價(注:房價可能在某段時間由於某種不為人知的因素有小幅波動),就把那所買過來了,等房價漲回去了再賣出去,這樣看起來也是生財之道。(注:純屬虛構)

可是如果去預測房價呢?上面講到了房價和房子所在地區x1、佔地面積x2、戶型x3和採光度x4有關,那麼我是不是可以把這些因素假想成房子的特徵,然後給這些每個特徵都加上一個相應的權重ω,既可以得到如下的決策函式

Y^=ω1x1+ω2x2+ω3x3+ω4x4+b

其中b可以理解為偏差,你也可以想成房子的這些特徵再差也可能會有一個底價。

基於上述給出房價的決策函式,我們就可以對一個某個不知名的房子輸入它的這些特徵,然後就可以得到這所房子的預測價格了。

理想總是美好的,即一條生財之道就在眼前,但是我們如何去得到這個決策函式呢?我們可以得到這個特徵值,但是這個ω怎麼得到呢?這就是我們的線性迴歸需要解決的問題,下面讓我們一起走向這條生財之道吧!

二、1. 2 決策函式

你可以簡單的認為線性迴歸就是找到一條曲線去擬合所有樣本點,上面提及買房的問題有四個特徵,因此我們得到的決策函式為

Y^=ω1x1+ω2x2+ω3x3+ω4x4+b

對於n個特徵的線性迴歸模型,你可能需要找到一條曲線,也可以說成是一個決策函式

Y^=fθ(X)=θ1x1+θ2x2++θnxn+b=θTX+b

擬合所有樣本點。其中b為未知引數偏置(bias);θ為未知引數向量[θ1,θ2,,θn]X為樣本在各個特徵上的特徵值,用向量表示為[x1,x2,,xn]θT為向量θ的轉置

[θ1θ2θn]

θTX=[θ1θ2θn][x1,x2,,xn]=θ1x1+θ2x2++θnxn

如果你對矩陣運算不熟悉,牢記fθ(X)=θ1x1+θ2x2++θnxn+b=θTX+b即可。

如果把未知引數b看成θ0,曲線為

Y^=fθ(X)=θ0x0+θ1x1+θ2x2++θnxn+b=θTX

其中x0=1

雖然其他機器學習演算法的決策函式不一定是線性迴歸的fθ(X)=θTX,但是決策函式中一般都會有一個未知引數θ,以後對於所有的機器學習演算法都會逐一講解為什麼會有這個引數。

三、1. 3 損失函式

# 損失函式圖例
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
from sklearn.datasets.samples_generator import make_regression
%matplotlib inline
font = FontProperties(fname='/Library/Fonts/Heiti.ttc')

# 生成隨機資料
# X為樣本特徵,y為樣本輸出,coef為迴歸係數,共100個樣本,5個噪聲,每個樣本1個特徵,資料集隨機種子為1
X, y, coef = make_regression(
n_samples=100, n_features=1, noise=50, coef=True, random_state=1)

# 散點圖+直線
plt.scatter(X, y, color='g', s=50, label='房子資訊')
plt.plot(X, X*coef, color='r', linewidth=2)

plt.xlabel('房子面積', fontproperties=font, fontsize=15)
plt.ylabel('房價', fontproperties=font, fontsize=15)
plt.title('房子面積-房價', fontproperties=font, fontsize=20)
# 去掉x,y軸尺度
plt.xticks(())
plt.yticks(())
plt.legend(prop=font)
plt.show()

如上圖所示,上圖假設每一個綠點表示一所房子的資訊,紅色的直線為我們通過某種方法得到一個決策函式Y^=fθ(X)=θTX+b=θ1x+b。對於監督模型中的通過房子面積預測房價例子,我們是假設已知θ1=10,b=0

但是如果你眼力勁還不錯,你可能會發現我們的這個決策函式並沒有完全經過這些資料點,也可以說是沒有完全擬合這些資料點。一般我們的決策函式都是無法經過所有點的,你要知道機器學習是不可能做到預言的,而只能做到預測,預言有時候都會不準確,更別說預測了,也就是說機器學習對新資料的預測是有誤差的。通常我們使用一個損失函式(loss function)或代價函式(cost function)度量模型預測錯誤的程度

L(YY^)=L(Yfθ(X))

其中Y為樣本的真實值,Y^為樣本的預測值。

四種常用的損失函式:

  1. 平方損失函式(quadratic loss function)

L(Y,fθ(X))=(Yfθ(X))2

  1. 絕對值損失函式(absolute loss fuction)

L(Y,fθ(X))=|Yfθ(X)|

  1. 0-1損失函式(0-1 loss function)

L(Y,fθ(X)){1,Yfθ(X)0,Y=fθ(X)

  1. 對數損失函式(logarithmic loss function)或對數似然損失函式(log-likelihood loss function)

L(Y,fθ(X))=logP(Y|X)

四、1. 4 目標函式

損失函式一般是對某個樣本損失的計算,但是我們的模型很明顯不是由一個樣本生成的,而是由一組樣本生成的。由於XY我們可以通過資料獲得,但是未知引數θ是未知的,因此我們在這裡給出關於θ的目標函式(objective function),即所有樣本的誤差加和取平均

J(θ)=i=1mL(yi,fθi(xi))

其中m是樣本總數,i=1mL(yi,fθi(xi))=L(y1,fθ1(x1))+L(y2,fθ2(x2))++L(ym,fθm(xm))

五、1. 5 目標函式最小化

假設我們得到了目標函式,那麼我們接下來要幹什麼呢?目標函式是所有樣本的誤差加和取平均,那麼是不是這個誤差越小越好呢?對,你暫時可以這樣想,誤差越小,則我們的預測值會越來越接近真實值,接下來我們就是需要最小化目標函式,由於目標函式在統計學中被稱為經驗風險(empirical risk),所以有時候也會最小化目標函式也會被稱為經驗風險最小化(empirical risk minimization)。

minJ(θ)=min1mi=1mL(yi,fθi(xi))

其中minJ(θ)表示最小化J(θ)函式。

通過線性迴歸舉例,由於fθ(X)=θTX,則它的損失函式是

L(Y,fθ(X))=L(Y,θTX)

它的目標函式是

J(θ)=1mi=1mL(yi,θixi)

假設上述目標函式使用了平方損失函式,則目標函式變成

J(θ)=1mi=1m(yiθixi)2

最小化目標函式為

(1)minJ(θ)=min1mi=1m(yiθixi)2(2)=min1m[(y1θ1x1)2+(y2θ2x2)2++(ymθmxm)2]

其中{x1,x2,,xm}{y1,y2,,ym}m都是已知的,即我們可以把他們看成一個常數。

如果我們考慮一個極端情況,即假設xi=1,(i=1,2,,m)yi=2,(y=1,2,,m)m=100θ1=θ2==θm=θj,則最小化目標函式變為

(3)minJ(θ)=min1100[(2θj1)2+(2θj1)2++(2θj1)2]100(4)=min1100100[(2θj1)2](5)=min(2θj1)2

# 目標函式最小化圖例
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

# 生成一個數組(-4.98,-4.96,...,4.98,5)
theta_j = np.arange(-5, 5, 0.02)
# 構造J_theta曲線
J_theta_j = (2-theta_j)**2

# 描繪曲線
plt.plot(theta_j, J_theta_j, color='r', linewidth=2)

plt.xlabel('\(θ\)', fontproperties=font, fontsize=15)
plt.ylabel('\(min{J(θ)}\)', fontproperties=font, fontsize=15)
plt.title('\(\min{J(θ)}=(2-θ_j*1)^2\)', fontproperties=font, fontsize=20)
plt.show()

上圖即我們假設的目標函式的影象,從上圖可以看出,如果要最小化目標函式則需要找到能使目標函式最小化的引數向量θ,通過公式可以表示為

argminθJ(θ)=1mi=1mL(yi,fθi(xi))

其中argminθJ(θ)表示找到能使J(θ)最小化的引數向量θ

由於這裡只介紹目標函和目標函式最小化問題,怎麼找能使得目標函式最小化的θ不在此處介紹範圍,以後會詳細介紹。相信你對目標函式的構造、目標函式最小化(目標函式優化問題)有了一個明確的認知,至於目標函式中埋下的幾處伏筆,以後都會詳細介紹,目前的你只需要瞭解這個流程,以後我們會通過具體的機器學習演算法來再一次解釋這個過程。並且以後你會發現其實我們接下來要介紹的所有機器學習演算法都是基於這個流程,所以你會反覆再反覆接觸這個流程,如果現在能有個明確的認知很好,如果不可以等把這個流程與某個機器學習演算法聯絡在一起的時候相信你能理解他。

六、1. 6 過擬合

在這裡我必須得明確告訴你,理論上模型可能是越小越好,但是在工業上模型並不是誤差越小越好。你可以這樣想想,假設我們有一個數據集,這個資料集難道不會有噪音(noise)或噪聲嗎?首先我可以很明確的告訴你,一般的工業上的資料都會有噪聲,如果我們的模型經過了包括噪聲的所有樣本點,也就是說模型對我們的訓練集做到了完美擬合,這就是我們常說的過擬合(over-fitting),並且過擬合時模型也會變得相對複雜。

產生噪聲的原因:

  1. 訓練資料的標籤錯誤,即A類的資料標記為B類;B類的資料標記為A類
  2. 輸入資料某一維特徵值不準確的,下圖所示的紅點
# 過擬合圖例
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
font = FontProperties(fname='/Library/Fonts/Heiti.ttc')
%matplotlib inline

# 自定義資料並處理資料
data_frame = {'x': [2, 1.5, 3, 3.2, 4.22, 5.2, 6, 6.7],
'y': [0.5, 3.5, 5.5, 5.2, 5.5, 5.7, 5.5, 6.25]}
df = pd.DataFrame(data_frame)
X, y = df.iloc[:, 0].values.reshape(-1, 1), df.iloc[:, 1].values.reshape(-1, 1)

# 線性迴歸
lr = LinearRegression()
lr.fit(X, y)

def poly_lr(degree):
"""多項式迴歸"""
poly = PolynomialFeatures(degree=degree)
X_poly = poly.fit_transform(X)
lr_poly = LinearRegression()
lr_poly.fit(X_poly, y)
y_pred_poly = lr_poly.predict(X_poly)

<span class="hljs-keyword">return</span> y_pred_poly

def plot_lr():
"""對線性迴歸生成的圖線畫圖"""
plt.scatter(X, y, c='k', edgecolors='white', s=50)
plt.plot(X, lr.predict(X), color='r', label='lr')
# 噪聲
plt.scatter(2, 0.5, c='r')
plt.text(2, 0.5, s='\((2,0.5)\)')

plt.xlim(<span class="hljs-number">0</span>, <span class="hljs-number">7</span>)
plt.ylim(<span class="hljs-number">0</span>, <span class="hljs-number">8</span>)
plt.xlabel(<span class="hljs-string">'x'</span>)
plt.ylabel(<span class="hljs-string">'y'</span>)
plt.legend()

def plot_poly(degree, color):
"""對多項式迴歸生成的圖線畫圖"""
plt.scatter(X, y, c='k', edgecolors='white', s=50)
plt.plot(X, poly_lr(degree), color=color, label='m={}'.format(degree))
# 噪聲
plt.scatter(2, 0.5, c='r')
plt.text(2, 0.5, s='\((2,0.5)\)')

plt.xlim(<span class="hljs-number">0</span>, <span class="hljs-number">7</span>)
plt.ylim(<span class="hljs-number">0</span>, <span class="hljs-number">8</span>)
plt.xlabel(<span class="hljs-string">'x'</span>)
plt.ylabel(<span class="hljs-string">'y'</span>)
plt.legend()

def run():
plt.figure()
plt.subplot(231)
plt.title('圖1(線性迴歸)', fontproperties=font, color='r', fontsize=12)
plot_lr()
plt.subplot(232)
plt.title('圖2(一階多項式迴歸)', fontproperties=font, color='r', fontsize=12)
plot_poly(1, 'orange')
plt.subplot(233)
plt.title('圖3(三階多項式迴歸)', fontproperties=font, color='r', fontsize=12)
plot_poly(3, 'gold')
plt.subplot(234)
plt.title('圖4(五階多項式迴歸)', fontproperties=font, color='r', fontsize=12)
plot_poly(5, 'green')
plt.subplot(235)
plt.title('圖5(七階多項式迴歸)', fontproperties=font, color='r', fontsize=12)
plot_poly(7, 'blue')
plt.subplot(236)
plt.title('圖6(十階多項式迴歸)', fontproperties=font, color='r', fontsize=12)
plot_poly(10, 'violet')
plt.show()

run()

如上圖所示每張圖都有相同分佈的8個樣本點,紅點明顯是一個噪聲點,接下來將講解上述8張圖。暫時不用太關心線性迴歸和多項式迴歸是什麼,這兩個以後你都會學習到,此處引用只是為了方便舉例。

  • 圖1:線性迴歸擬合樣本點,可以發現樣本點距離擬合曲線很遠,這個時候一般稱作欠擬合(underfitting)
  • 圖2:一階多項式迴歸擬合樣本點,等同於線性迴歸
  • 圖3:三階多項式迴歸擬合樣本點,表現還不錯
  • 圖4:五階多項式迴歸擬合樣本點,明顯過擬合
  • 圖5:七階多項式迴歸擬合樣本點,已經擬合了所有的樣本點,毋庸置疑的過擬合
  • 圖7:十階多項式迴歸擬合樣本點,擬合樣本點的曲線和七階多項式已經沒有了區別,可以想象十階之後的曲線也類似於七階多項式的擬合曲線

從上圖可以看出,過擬合模型將會變得複雜,對於線性迴歸而言,它可能需要更高階的多項式去擬合樣本點,對於其他機器學習演算法,也是如此。這個時候你也可以想象,過擬合雖然對擬合的樣本點的誤差接近0,但是對於未來新資料而言,如果新資料的x=2,如果使用過擬合的曲線進行擬合新資料,那麼會給出y=0.5的預測值,也就是說把噪聲的值給了新資料,這樣明顯是不合理的。

七、1. 7 正則化

上面給大家介紹了機器學習中避不開的一個話題,即模型很有可能出現過擬合現象,出現了問題就應該解決,我講講機器學習中最常用的解決過擬合問題的方法——正則化(regularization)。給目標函式加上正則化項(regularizer)或懲罰項(penalty term),即新的目標函式變成

J(θ)=1mi=1mL(yi,fθi(xi))+λ(R(f))

其中λ0為超引數,類似於引數,但是引數可以通過演算法求解,超引數需要人工手動調整;λ(R(f))為正則化項。

這個時候你可能在想為什麼加上正則化項就可以解決過擬合問題呢?對於線性迴歸而言,由於涉及線性迴歸、梯度下降法、最小角迴歸法等概念,此處不多贅述,講線性迴歸時會詳細講述。下面將通過線性迴歸中正則化的兩種形式L1正則化和L2正則化做簡單解釋。

7.1 1. 7.1 L1正則化

L1正則化(Lasso)是在目標函式上加上L1正則化項,即新的目標函式為

J(θ)=1mi=1mL(yi,fθi(xi))+λ||θ||1

其中||θ||1為引數向量θ的1範數。

假設樣本有n特徵,則θn維向量,1範數為

||θ||1=j=1n|θj|

7.2 1. 7.2 L2正則化

L2正則化(Ridge)是在目標函式上加上L2正則化項,即新的目標函式為

J(θ)=1mi=1mL(yi,fθi(xi))+λ2||θ||22

其中||θ||22為引數向量θ的2範數的平方。

假設樣本有n特徵,則θn維向量,2範數為

||θ||2=j=1nθj2

多說一嘴,假設樣本有n特徵,則θn維向量,p範數為

||θ||p=j=1nθjpp

八、1. 8 訓練集、驗證集、測試集

通常情況下我們不會使用資料集中的所有資料作為訓練資料訓練模型,而是會按照某種比例,將資料集中的資料隨機分成訓練集、驗證集、測試集學得一個較優模型,如可以把資料集按照7:2:1的比例分成訓練集、驗證集、測試集,對於不同的問題一般分配的比例不同,下面將介紹這三者各自的作用。

8.1 1. 8.1 訓練集

一般情況下我們都會使用帶有正則項的目標函式去構建模型,即我們的目標函式為

J(θ)=1mi=1mL(yi,fθi(xi))+λ(R(f))

一般會通過訓練集得到引數θ。如線性迴歸的目標函式中有兩個引數θb,一般會通過訓練集得到這兩個引數θb

8.2 1. 8.2 驗證集

一般情況下我們都會使用帶有正則項的目標函式去構建模型,即我們的目標函式為

J(θ)=1mi=1mL(yi,fθi(xi))+λ(R(f))

一般會通過給定一組超引數,然後通過驗證集得到最優超引數λ,有時候會把驗證集得到超引數的步驟劃分到訓練集中。如線性迴歸的目標函式有一個超引數λ,一般會通過驗證集得到該超引數λ

8.3 1. 8.3 測試集

測試集一般被當做未來新資料集,然後通過度量模型效能的工具測試模型的誤差大小。

九、1. 9 本章小結

本章主要通過線性迴歸介紹了決策函式、四種損失函式、目標函式及目標函式的問題,其實其他的機器學習演算法也是這樣的套路,在在一部分演算法原理時我們會細講,此處你有一個大概的概念即可。

最小化目標函式我們假設誤差越小越好,然而工業上資料總是會有噪聲,也就是說0誤差也許並不是最好的,因此引出了我們的過擬合問題,之後講解了解決過擬合問題的兩個方法,一個是在目標函式上加上正則化項,另一個則把訓練集分成訓練集、驗證集和測試集。