1. 程式人生 > >機器學習2 線性模型

機器學習2 線性模型

引言

線性模型形式簡單、易於建模,就好像“hello world”。但許多功能強大的非線性模型都是線上性模型上的延伸。我們主要介紹幾種經典的線性模型:線性迴歸,多項式迴歸,嶺迴歸,lasso迴歸,邏輯斯提回歸。

線性迴歸

以西瓜問題為例,它有三個屬性(也就做特徵),{色澤,根蒂,敲聲},根據這些屬性判斷是不是好瓜,我們自然而然想到的是:是不是可以通過屬性的線性組合來預測。即:

f(x)=w_{1}x_{1}+w_{2}x_{2}+w_{3}x_{3}+b

寫成向量形式:

f(x)=w^{T}x+b

其中w叫做權重係數,b叫做偏置項。

那麼如何確定w,b呢。關鍵在於我們的預測值和實際值間的差距。在迴歸任務中,均方誤差是最常用的效能度量。

其中f為我們的預測函式,D為包含m個樣本的資料集。

你可能會想也可以這樣度量差距啊:

當然這樣也可以,這叫做曼哈頓距離,但函式性質不好,不連續,在後續處理會很麻煩。

我們的目標是求得使均方誤差最小化的w和b:

接下來就是數學推導了;

對於包含m個樣本的資料集D,每個樣本有d個屬性描述的一般情況。我們試圖學得的模型為:

我們把w,b兩個未知的引數寫在一起:

其中:

X為(m,d+1)維,W為(d+1,1)維

這樣我們的目標函式就是:

目標函式為連續的凸函式,令其偏導數為零,不就解出需要的引數了嗎?

解得:

可以看出一下子就解出我們需要的引數了,這是求解模型的方法之一:存在閉式解。另一種情況:很難求得閉式方程,需要使用迭代優化的方法,一步步走直到引數最優。這種方法,我們會在邏輯斯提回歸中介紹。

回來看,這有一個問題:XTX這個矩陣需要可逆,在練習情況下該矩陣通常是可逆的,因為樣本數遠遠大於屬性數。而在實際情況中該矩陣往往不可逆,屬性數遠遠大於樣本數,這樣該矩陣不可逆,存在多個解。這時需要引入正則化,如嶺迴歸,lasso迴歸。我會線上性迴歸之後進行介紹。

還有一個問題:線性迴歸往往出現欠擬合,在已知資料集上很難達到很好的效能,區域性加權迴歸可以緩解這種情況。

實戰演練

線性迴歸模型很簡單,可以自己試著去實現。這裡不再介紹,直接使用sklearn。

超引數:fit_intercept:是否需要偏置項b,預設true

              normalize:是否需要歸一化。當 fit_intercept

False,忽略該引數 。歸一化方法為:減去均值,除以l2範數。如果需要 標準化, 使用 sklearn.preprocessing.StandardScaler 並設定 normalize=False.

             copy_X:是否需要複製X

             n_jobs:cpu使用數,-1代表全部使用。

屬性:coef_:權重係數w

           intercept_:偏置項b

程式碼走起:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression

'''
建立資料集
'''
#rand(100,1)產生100*1的矩陣,數為0到1的隨機數
X = 2 * np.random.rand(100,1)
#randn(100,1)產生100*1的矩陣,數為正態分佈隨機數
y = 4 + 3*X + np.random.randn(100,1)

plt.figure()
plt.xlim(0,2)
plt.ylim(0,14)
plt.xlabel('x')
plt.ylabel('y')
plt.scatter(X,y)
plt.show()

結果:

 

lin_reg = LinearRegression()
lin_reg.fit(X,y)
print(lin_reg.coef_,lin_reg.intercept_)

結果:

在資料集上視覺化:

'''
視覺化
'''
plt.figure()
plt.xlim(0,2)
plt.ylim(0,14)
plt.xlabel('x')
plt.ylabel('y')
plt.plot([0,2],
         [lin_reg.intercept_[0],2*lin_reg.coef_[0][0]+lin_reg.intercept_[0]],
         c='black')
plt.scatter(X,y)
plt.title('LinearRegression')
plt.show()

結果:

還不錯吧。

多項式迴歸

如果資料比簡單的直線複雜,我們也可以用線性模型來進行擬合。一個簡單的方法就是將每個特徵的冪次方新增為一個新的特徵,然後在這個拓展過的訓練集上訓練線性模型,這種方法稱為多項式迴歸。

'''
建立資料集
'''
np.random.seed(42)
#rand(100,1)產生100*1的矩陣,數為0到1的隨機數
X = 6 * np.random.rand(100,1) - 3
#randn(100,1)產生100*1的矩陣,數為正態分佈隨機數
y = 0.5 * X**2 + X + 2 + np.random.randn(100,1)

'''
視覺化
'''
plt.figure()
plt.xlim(-3,3)
plt.ylim(0,10)
plt.xlabel('x')
plt.ylabel('y')
plt.scatter(X,y)
plt.show()

結果:

顯然,直線不可能很好的擬合它。

'''
訓練
'''
#利用PolynomialFeatures對資料進行轉換,將每個屬性的平方作為新特徵加入資料集
poly_features = PolynomialFeatures(degree=2,include_bias=False)
X_poly = poly_features.fit_transform(X)
lin_reg = LinearRegression()
lin_reg.fit(X_poly,y)
'''
視覺化
'''
plt.figure()
plt.xlim(-3,3)
plt.ylim(0,10)
plt.xlabel('x')
plt.ylabel('y')
x = np.arange(-3,3,0.1)
Y = lin_reg.coef_[0][1]*x**2 + lin_reg.coef_[0][0]*x + lin_reg.intercept_
plt.plot(x,Y,c='black')
plt.scatter(X,y)
plt.show()

結果:

嶺迴歸

前面我們提到過,有時XTX矩陣不可逆時可以使用嶺迴歸。簡單來說,嶺迴歸就是在XTX上加上一個lamda*I使得矩陣非奇異。

矩陣I是m*m的單位矩陣(單位矩陣,值1貫穿對角線,其餘全是0,像不像一條‘嶺’)。這樣閉式解變成:

嶺迴歸最初就是為了解決矩陣奇異的情況,現在也用於在估計中加入偏差,引入懲罰項相當於l2範數,降低過擬合。

這裡引入了方差和偏差的概念:在機器學習領域,一個模型的泛化誤差可以表示成三種誤差的和

1)偏差 該誤差的原因在於模型欠擬合

2)方差 該誤差的原因在於使用的模型複雜,導致過擬合

3)不可避免的誤差:資料本身的噪聲

我們經常回去權衡偏差和方差,增加模型的複雜度就會提升方差,減小偏差。反過來,降低模型的複雜度就會降低方差,增大偏差。

引數:

alpha:正則化強度; 必須是正浮點數。 較大的值指定較強的正則化。

copy_X:與線性迴歸相同

fit_intercept:與線性迴歸相同

max_iter:int,可選,共軛梯度求解器的最大迭代次數。 對於’sparse_cg’和’lsqr’求解器,預設值由scipy.sparse.linalg確定。 對於’sag’求解器,預設值為1000。

normalize:與線性迴歸相同

solver:{‘auto’,’svd’,’cholesky’,’lsqr’,’sparse_cg’,’sag’,‘saga’}
用於計算的求解方法:
‘auto’根據資料型別自動選擇求解器。
‘svd’使用X的奇異值分解來計算Ridge係數。對於奇異矩陣比’cholesky’更穩定。
‘cholesky’使用標準的scipy.linalg.solve函式來獲得閉合形式的解,即上述的閉式解的一種變體
‘sparse_cg’使用在scipy.sparse.linalg.cg中找到的共軛梯度求解器。作為迭代演算法,這個求解器比大規模資料的“cholesky”更合適。
‘lsqr’使用專用的正則化最小二乘常數scipy.sparse.linalg.lsqr。它是最快的,使用迭代過程。
‘sag’使用隨機平均梯度下降。‘saga’是它的改進。都使用迭代過程,並且當n_samples和n_feature都很大時,通常比其他求解器更快。注意,“sag”快速收斂僅在具有近似相同尺度的特徵上被保證。您可以使用sklearn.preprocessing的縮放器預處理資料。
所有最後五個求解器支援密集和稀疏資料。但是,當fit_intercept為True時,只有’sag’,‘saga’支援稀疏輸入。
新版本0.17支援:sag。

新版本0.19支援:saga。

tol:float解的精度。

random_state:隨機種子發生器。當為int時,生成固定資料,只適合‘sag’求解器


返回值

coef_:與線性迴歸相同

intercept_:與線性迴歸相同

n_iter_:每個目標的實際迭代次數。 僅適用於sag和lsqr求解器。 其他求解器將返回None。在版本0.17中出現。
 


'''
訓練
'''
#利用PolynomialFeatures對資料進行轉換,將每個屬性的平方作為新特徵加入資料集
poly_features = PolynomialFeatures(degree=2,include_bias=False)
X_poly = poly_features.fit_transform(X)
lin_reg = LinearRegression()
lin_reg.fit(X_poly,y)

#嶺迴歸
ridge_reg = Ridge(alpha=100,solver='cholesky')
ridge_reg.fit(X_poly,y)
'''
視覺化
'''
plt.figure()
plt.xlim(-3,3)
plt.ylim(0,10)
plt.xlabel('x')
plt.ylabel('y')
x = np.arange(-3,3,0.1)
Y1 = lin_reg.coef_[0][1]*x**2 + lin_reg.coef_[0][0]*x + lin_reg.intercept_
plt.plot(x,Y1,c='black',label='lin_reg')
Y2 = ridge_reg.coef_[0][1]*x**2 + ridge_reg.coef_[0][0]*x + ridge_reg.intercept_
plt.plot(x,Y2,c='red',label='ridge_reg')
plt.scatter(X,y)
plt.legend(loc='best')
plt.show()

結果:

alpha越大,越接近線性模型。

lasso迴歸

與嶺迴歸一樣,它也能緩解過擬合,引入懲罰項,相當於L1範數。Lasso迴歸有一個重要的特點,它會傾向於完全消除掉那些最不重要的權重,我們因此能更好的瞭解到哪些特徵是無用的。

 alpha:正則化程度,較大的值指定較強的正則化。

fit_intercept:與線性迴歸相同

normalize:與線性迴歸相同

precompute:是否使用預計算的 Gram 矩陣來加速計算。如果設定為 ‘auto’ 則機器決定。Gram 矩陣也可以 pass。對於 sparse input 這個選項永遠為 True。

max_iter:最大迴圈次數

tol:優化誤差率

warm_start:為 True 時, 重複使用上一次學習作為初始化,否則直接清除上次方案

positive:設為 True 時,強制使係數為正。

random_state:隨機種子生成器

selection:若設為 ‘random’, 每次迴圈會隨機更新引數,而按照預設設定則會依次更新。設為隨機通常會極大地加速交點(convergence)的產生,尤其是 tol 比 1e-4 大的情況下。

返回值

coef_:同線性迴歸

intercept_:同線性迴歸

n_iter_:達到誤差率的迴圈次數

sparse_coef_:擬合係數的稀疏表示

 

#Lasso迴歸

Lasso_reg = Lasso(alpha=2)
Lasso_reg.fit(X_poly,y)
'''
視覺化
'''
plt.figure()
plt.xlim(-3,3)
plt.ylim(0,10)
plt.xlabel('x')
plt.ylabel('y')
x = np.arange(-3,3,0.1)
Y1 = lin_reg.coef_[0][1]*x**2 + lin_reg.coef_[0][0]*x + lin_reg.intercept_
plt.plot(x,Y1,c='black',label='lin_reg')
Y2 = Lasso_reg.coef_[1]*x**2 + Lasso_reg.coef_[0]*x + Lasso_reg.intercept_
plt.plot(x,Y2,c='red',label='Lasso_reg')
plt.scatter(X,y)
plt.legend(loc='best')
plt.show()

結果:

小結

本節主要介紹線性模型中的線性迴歸,並引出了多項式迴歸來解決非線性資料問題。還介紹了嶺迴歸和Lasso迴歸來解決過擬合問題。那如何利用線性模型進行分類學習呢?

下節我們將要介紹邏輯斯提回歸。雖說它有迴歸字樣,卻叛變為分類學習方法。