机器学习实战之路—— 1 线性回归 (二)
機器學習實戰之路 —— 1 線性回歸二
- 1. 欠擬合和過擬合問題
- 2. 模型優化
- 2.1 局部加權線性回歸(LWLR)
- 2.2 嶺回歸
- 2.3 Lasso回歸
- 2.4 前向逐步回歸
- 2.5 時間序列分析ARIMA
- 3. 實戰:廣告花費與銷售額
- 3.1 線性回歸
- 3.2 嶺回歸(Ridge)
- 3.3 Lasso
- 4. 參考學習的書目及論文
1. 欠擬合和過擬合問題
線性回歸的一個問題是有可能出現欠擬合現象,因為它求的是最小均方誤差的無偏估計。顯而易見,如果模型欠擬合將不能取得最好的預測效果。所以有些方法允許在估計中引入一些偏差,從而降低預測的均方誤差。
——《機器學習實戰》P141P_{141}P141?
處理欠擬合的方法:
*增加特征,增大模型復雜度
*增大調試參數C
處理過擬合的方法:
*減少特征,降低模型復雜度
*減小調試參數C
*增加訓練數量
——《機器學習之路》P49P_{49}P49?
一般而言,欠擬合就是模型能力不足,沒有有效的表示出數據集內在的表達式。與欠擬合相對的就是模型的過擬合問題,在實際中,當特征維度增加到一定程度時,雖然模型在訓練集的成績越來越好,但在測試集的最終成績反而越來越差。例舉示意圖如下:
總之模型越簡單,模型適應力越強,越容易發生欠擬合;反之,模型越復雜,模型適應性越差,越容易發生過擬合。針對以上問題,我們可以對線性模型進行相應的優化處理。
2. 模型優化
2.1 局部加權線性回歸(LWLR)
在局部加權線性回歸(LocallyWeightedLinearRegression, LWLR )算法中,給待預測點附近的每個點賦予一定的權重,在這個子集上基于最小二乘法來進行普通的回歸,LWLR試圖求得:
arg?min?ω∑i=1mωi(yi?f(xi))2\begin{aligned} \argmin_{ω}\sum_{i=1}^{m}ω_i(y_i-f(x_i))^2 \end{aligned}ωargmin?i=1∑m?ωi?(yi??f(xi?))2?
此處的ωiω_iωi? 是非負的權重(weights)值。直觀看來,如果對于某個特定的 i ,它的ωiω_iωi? 很大,那么在選擇ωiω_iωi?的時候,我們將會盡可能地使 (yi?f(xi))2(y_i-f(x_i))^2(yi??f(xi?))2 更小。如果ωiω_iωi? 很小,那么在擬合的過程中(yi?f(xi))2(y_i-f(x_i))^2(yi??f(xi?))2誤差項就能夠大大地忽略。
參考上一篇博文—線性回歸(一),LWLR 回歸系數推導過程和(一)類似,最終求得的回歸系數ω的形式如下:
ω^=(XTWX)?1XTWy\hat\omega=(X^TWX)^{-1}X^TWy ω^=(XTWX)?1XTWy
W是一個權重矩陣,LWLR使用 “核”(與支持向量機中的核類似)來對附近的點賦予更高的權重。核的類型可以自由選擇,最常用的核就是高斯核,高斯核對應的權重如下:
W(i,i)=exp(∣x(i)?x∣?2k2)W(i,i)=exp\left({\frac{|x^{(i)}-x|}{-2k^2}}\right) W(i,i)=exp(?2k2∣x(i)?x∣?)
代碼實現如下:
def lwlr(testPoint,xArr,yArr,k=1.0):xMat = mat(xArr); yMat = mat(yArr).Tm = shape(xMat)[0]# 創建對角矩陣weights = mat(eye((m)))# 創建權重矩陣,權重大小以指數級衰減for j in range(m):diffMat = testPoint - xMat[j,:] # xMat[j,:]為某一行的值weights[j,j] = exp(diffMat*diffMat.T/(-2.0*k**2))xTx = xMat.T * (weights * xMat)if linalg.det(xTx) == 0.0:print("矩陣為奇異矩陣,不能求逆")return# 計算回歸系數ws = xTx.I * (xMat.T * (weights * yMat))return testPoint * ws2.2 嶺回歸
如果特征比樣本點還多(n > m ) , 也就是說輸入數據的矩陣X不是滿秩矩陣,非滿秩矩陣在求逆時會出現問題。同時為了防止過擬合,在標準線型回歸函數中增加λ擾動。
嶺回歸的目標函數在一般的線性回歸的基礎上加入了二范數正則項,在保證最佳擬合誤差的同時,使得參數盡可能的“簡單”,使得模型的泛化能力強。嶺回歸試圖求得:
arg?min?ω∑i=1m(yi?f(xi))2+λ∣∣ω∣∣2\begin{aligned} \argmin_{ω}\sum_{i=1}^{m}(y_i-f(x_i))^2 + λ||ω||^2 \end{aligned}ωargmin?i=1∑m?(yi??f(xi?))2+λ∣∣ω∣∣2?
回歸系數的計算公式為:
ω^=(XTX+λI)?1XTy\hat\omega=(X^TX+\lambda I)^{-1}X^Ty ω^=(XTX+λI)?1XTy
代碼實現如下:
使用sklearn.linear_model中嶺回歸代碼如下:
from sklearn.linear_model import Ridge# sklearn的嶺回歸 model = Ridge() # 0.001 ~ 100 的等比數列的20個數 alpha_can = np.logspace(-3, 2, 20) # 超參數自動搜索模塊GridSearchCV,系統地遍歷多種參數組合,通過交叉驗證確定最佳效果參數 5折交叉驗證 lasso_model = GridSearchCV(model, param_grid={'alpha': alpha_can}, cv=5) lasso_model.fit(x_train, y_train)2.3 Lasso回歸
區別于嶺回歸的二范數正則項,Lasso回歸采用一范數來約束,使參數非零個數最少。Lasso回歸試圖求得:
arg?min?ω∑i=1m(yi?f(xi))2+λ∣ω∣\begin{aligned} \argmin_{ω}\sum_{i=1}^{m}(y_i-f(x_i))^2 + λ|ω| \end{aligned}ωargmin?i=1∑m?(yi??f(xi?))2+λ∣ω∣?
與嶺回歸相比其唯一的不同點在于,這個約束條件使用絕對值取代了平方和。雖然約束形式只是稍作變化,結果卻大相徑庭:在λ\lambdaλ足夠小的時候,一些系數會因此被迫縮減到0,這個特性可以幫助我們更好地理解數據。這兩個約束條件在公式上看起來相差無幾,但細微的變化卻極大地增加了計算復雜度(為了在這個新的約束條件下解出回歸系數,需要使用二次規劃算法)。
Lasso回歸使用sklearn.linear_model的核心代碼如下:
from sklearn.linear_model import Lasso# sklearn的Lasso回歸 model = Lasso() # 0.001 ~ 100 的等比數列的20個數 alpha_can = np.logspace(-3, 2, 20) # 超參數自動搜索模塊GridSearchCV,系統地遍歷多種參數組合,通過交叉驗證確定最佳效果參數 5折交叉驗證 lasso_model = GridSearchCV(model, param_grid={'alpha': alpha_can}, cv=5) lasso_model.fit(x_train, y_train)2.4 前向逐步回歸
前向逐步回歸算法可以得到與Lasso差不多的效果,但更加簡單。它屬于一種貪心算法,即每一步都盡可能減少誤差。一開始,所有的權重都設為1,然后每一步所做的決策是對某個權重增加或減少一個很小的值。即步長每個特征。
代碼實現如下:
def regularize(xMat):'''數據標準化:param xMat: 數據集:return: 標準化后的數據'''inMat = xMat.copy()# 求均值inMeans = mean(inMat,0)# 求方差inVar = var(inMat,0)# 數據減均值除以方差實現標準化inMat = (inMat - inMeans)/inVarreturn inMatdef stageWise(xArr,yArr,eps=0.01,numIt=100):''':param xArr: 輸入數據:param yArr: 預測變量:param eps: 每次迭代步長:param numIt: 迭代次數:return: 回歸系數'''# 數據標準化xMat = mat(xArr); yMat=mat(yArr).TyMean = mean(yMat,0)yMat = yMat - yMeanxMat = regularize(xMat)m,n=shape(xMat)# 初始化回歸系數矩陣returnMat = zeros((numIt,n)) #testing code removews = zeros((n,1)); wsTest = ws.copy(); wsMax = ws.copy()for i in range(numIt):print(ws.T)lowestError = inf;# 遍歷每個特征的回歸系數for j in range(n):for sign in [-1, 1]:wsTest = ws.copy()# 回歸系數步進wsTest[j] += eps * signyTest = xMat * wsTestrssE = rssError(yMat.A, yTest.A)# 若誤差更小,選擇最佳回歸系數if rssE < lowestError:lowestError = rssEwsMax = wsTestws = wsMax.copy()returnMat[i, :] = ws.Treturn returnMat2.5 時間序列分析ARIMA
時間序列
時間序列(或稱動態數列)是指將同一統計指標的數值按其發生的時間先后順序排列而成的數列。時間序列分析的主要目的是根據已有的歷史數據對未來進行預測。
時間序列分析
時間序列分析是根據系統觀察得到的時間序列數據,通過曲線擬合和參數估計來建立數學模型的理論和方法。時間序列分析常用于國民宏觀經濟控制、市場潛力預測、氣象預測、農作物害蟲災害預報等各個方面。
使用statsmodels.tsa.arima_model代碼如下:
from statsmodels.tsa.arima_model import ARIMAp = 2; q = 2 model = ARIMA(endog=x, order=(p, d, q)) # 自回歸函數p,差分d,移動平均數q arima = model.fit(disp=-1) # disp<0:不輸出過程 prediction = arima.fittedvalues y = prediction.cumsum() + x[0]3. 實戰:廣告花費與銷售額
問題描述:
已知某公司分別在電視(TV)、廣播(Radio)、報紙(Newspaper)上所投入的廣告花費,及對應所產生的銷售額(Sales),預測在不同廣告投入下所能產生的銷售額。
相應的數據集如下:
| 1 | 230.1 | 37.8 | 69.2 | 22.1 |
| 2 | 44.5 | 39.3 | 45.1 | 10.4 |
| 3 | 17.2 | 45.9 | 69.3 | 9.3 |
| 4 | 151.5 | 41.3 | 58.5 | 18.5 |
| 5 | 180.8 | 10.8 | 58.4 | 12.9 |
| 6 | 8.7 | 48.9 | 75 | 7.2 |
| 7 | 57.5 | 32.8 | 23.5 | 11.8 |
| 8 | 120.2 | 19.6 | 11.6 | 13.2 |
| 9 | 8.6 | 2.1 | 1 | 4.8 |
| 10 | 199.8 | 2.6 | 21.2 | 10.6 |
| …… | …… | …… | …… | …… |
| 200 | 232.1 | 8.6 | 8.7 | 13.4 |
繪制該數據的示意圖如下:
各數據分別顯示:
后續將綜合線性回歸(一)和(二)的一些關鍵算法實現做具體展開。
3.1 線性回歸
實現代碼如下:
#!/usr/bin/python # -*- coding:utf-8 -*-import numpy as np import matplotlib.pyplot as plt import pandas as pd from sklearn.model_selection import train_test_split from sklearn.linear_model import LinearRegression import sklearn.metrics as metrics import matplotlib as mplif __name__ == "__main__":# pandas讀入數據(TV、Radio、Newspaper、Sales)data = pd.read_csv('Advertising.csv')x = data[['TV', 'Radio', 'Newspaper']]y = data['Sales']print("數據維度:", data.shape)print("x數據集:\n", x)print("y數據集:\n", y)# 拆分數據為訓練集(80%)和測試集(20%)x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=1)print("訓練數據維度:", x_train.shape, "測試數據維度:", x_test.shape)# sklearn線性回歸linreg = LinearRegression()# 用訓練集來訓練出線型回歸模型model = linreg.fit(x_train, y_train)print(model)print("回歸系數:", linreg.coef_, " 截距:", linreg.intercept_)# 返回測試集從小到大的索引值,沿第一軸排序(向下)order = y_test.argsort(axis=0)y_test = y_test.values[order]x_test = x_test.values[order, :]# 用測試集進行預測y_hat = linreg.predict(x_test)# Mean Squared Error(均方誤差)mse = np.average((y_hat - np.array(y_test)) ** 2)# Root Mean Squared Error(均方根誤差)rmse = np.sqrt(mse)# 用sklearn計算 Mean Squared Error(均方誤差)mse = metrics.mean_squared_error(y_test, y_hat)# Root Mean Squared Error(均方根誤差)rmse = np.sqrt(mse)print("======== 均方誤差,均方根誤差 ========")print("MSE = ", mse)print("RMSE = ", rmse)# 對模型進行評價print("======== 模型評價 R^2 ========")print("Training R^2 = ", linreg.score(x_train, y_train))print("Test R^2 = ", linreg.score(x_test, y_test))# 線型回歸預測圖mpl.rcParams['font.sans-serif'] = ['simHei']mpl.rcParams['axes.unicode_minus'] = Falseplt.figure(facecolor='w')t = np.arange(len(x_test))plt.plot(t, y_test, 'r-', linewidth=2, label='真實數據')plt.plot(t, y_hat, 'g-', linewidth=2, label='預測數據')plt.legend(loc='upper left')plt.title('線性回歸預測銷量', fontsize=18)plt.grid(b=True, ls=':')plt.show()輸出結果如下:
數據維度: (200, 5) x數據集:TV Radio Newspaper 0 230.1 37.8 69.2 1 44.5 39.3 45.1 2 17.2 45.9 69.3 3 151.5 41.3 58.5 4 180.8 10.8 58.4 5 8.7 48.9 75.0 .. ... ... ... 199 232.1 8.6 8.7 [200 rows x 3 columns]y數據集: 0 22.1 1 10.4 2 9.3 3 18.5 4 12.9 5 7.2... 199 13.4 Name: Sales, Length: 200, dtype: float64訓練數據維度: (160, 3) 測試數據維度: (40, 3) LinearRegression(copy_X=True, fit_intercept=True, n_jobs=1, normalize=False) 回歸系數: [ 0.0468431 0.17854434 0.00258619] 截距: 2.90794702082 ======== 均方誤差,均方根誤差 ======== MSE = 1.99188555183 RMSE = 1.41134175586 ======== 模型評價 R^2 ======== Training R^2 = 0.895937263233 Test R^2 = 0.892760591462繪制的線性回歸預測銷量如下:
擬合的線型回歸函數為:
y=2.9+0.046?TV+0.179?Radio+0.0026?Newspapery = 2.9 + 0.046 * TV + 0.179 * Radio + 0.0026 * Newspaper y=2.9+0.046?TV+0.179?Radio+0.0026?Newspaper
從擬合出的回歸系數可知,Newspaper對銷售額的影響較其他兩種小一到兩個數量級,不妨嘗試忽略Newspaper,只選取TV、Radio兩個重要特征來進行線型回歸,得到結果如下:
回歸系數: [ 0.04686997 0.1800065 ] 截距: 2.94751503603 ======== 均方誤差,均方根誤差 ======== MSE = 1.95522188501 RMSE = 1.39829248908 ======== 模型評價 R^2 ======== Training R^2 = 0.895852846878 Test R^2 = 0.894734495003從結果可知,只考慮重要特征(TV、Radio),得到的結果可能會優于考慮全部特征,即特征不見得越多越好。在機器學習實踐中,在深入研究應用業務的基礎上,對特征的分析和恰當選取是非常重要的。
3.2 嶺回歸(Ridge)
主要實現代碼如下:
if __name__ == "__main__":# pandas讀入數據(TV、Radio、Newspaper、Sales)# 拆分數據為訓練集(80%)和測試集(20%)# sklearn的嶺回歸model = Ridge()# 0.001 ~ 100 的等比數列的20個數alpha_can = np.logspace(-3, 2, 20)np.set_printoptions(suppress=True)print('alpha_can = ', alpha_can)# 超參數自動搜索模塊GridSearchCV,系統地遍歷多種參數組合,通過交叉驗證確定最佳效果參數 5折交叉驗證lasso_model = GridSearchCV(model, param_grid={'alpha': alpha_can}, cv=5)lasso_model.fit(x_train, y_train)print('超參數:\n', lasso_model.best_params_)# 結果輸出輸出結果如下:
超參數:{'alpha': 16.237767391887211} ======== 均方誤差,均方根誤差 ======== MSE = 1.99368993021 RMSE = 1.41198085334 ======== 模型評價 R^2 ======== Training R^2 = 0.895937204701 Test R^2 = 0.892663447093.3 Lasso
主要實現代碼如下:
if __name__ == "__main__":# pandas讀入數據(TV、Radio、Newspaper、Sales)# 拆分數據為訓練集(80%)和測試集(20%)# sklearn的Lasso回歸model = Lasso()# 同嶺回歸(Ridge)# 結果輸出輸出結果如下:
超參數:{'alpha': 0.78475997035146072} ======== 均方誤差,均方根誤差 ======== MSE = 2.03270682226 RMSE = 1.42573027683 ======== 模型評價 R^2 ======== Training R^2 = 0.895833980993 Test R^2 = 0.8905628502854. 參考學習的書目及論文
=文檔信息=
本學習筆記由博主整理編輯,僅供非商用學習交流使用
由于水平有限,錯誤和紕漏之處在所難免,歡迎大家交流指正
如本文涉及侵權,請隨時留言博主,必妥善處置
版權聲明:非商用自由轉載-保持署名-注明出處
署名(BY) :zhudj
文章出處:https://zhudj.blog.csdn.net/
總結
以上是生活随笔為你收集整理的机器学习实战之路—— 1 线性回归 (二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 现代制造工程笔记04-精密超精密加工和特
- 下一篇: 如何快速在Github找到你想要的东西