機器學習實戰:線性迴歸模型

公衆號:尤而小屋
作者:Peter
編輯:Peter

大家好,我是Peter~

今天帶來的是機器學習的一篇實戰文章:利用機器學習庫scikit-learn實戰線性迴歸模型。

機器學習實戰—線性迴歸

在理想的狀態下,任何非線性的東西都是可以通過線性的東西來擬合的(參考泰勒公式)。而且線性模型本質上是均值預測,而大部分事物的變化都只是圍繞着均值來波動(參考大數定理),所以線性模型能夠模擬絕大部分的現象。

文章目錄

基本形式

基本表達

假設x是由d個屬性來描述:x={x_1,x_2,......,x_d};其中x_i表示第i個屬性上的取值。線性模型是通過各個屬性之間的組合來得到一個進行預測的函數,可表示爲:

f(x) = w_1x_1+ w_2x_2 + ... + w_dx_d + b

如果用向量表示爲:

f(x) = w^Tx+b

其中w=(w_1,w_2,...,w_d)稱之爲權重,b稱之爲偏置


不同形式

不同尺度下的線性函數f(x):

  • f(x)取離散的值:線性多分類模型
  • f(x)取實數域上實值函數:線性迴歸模型
  • f(x)爲對數:對數線性模式
  • f(x)進行sigmoid非線性變換:對數機率迴歸

本文中重點講解的是線性迴歸問題,參考資料:《周志華-機器學習》和李航《統計學習方法》,還有datawhale的《南瓜書》公式部分。

線性迴歸

給定數據集D = {(x_1,y_1),(x_2,y_2),...,(x_m,y_m)},y_i \in R

線性迴歸linear regression試圖學得一個線性模型,儘可能使得預測值f(x)和實際值y_i之間的差別最小

衡量方法

使用均方誤差來衡量:找到合適的w和b,滿足 \min _{(w,b)} \sum ^m _{i=1} (f(x_i) - y_i)^2

均方誤差對應的就是常用的歐幾里得距離(歐式距離)。基於均方誤差最小化來進行模型求解的方法稱之爲:最小二乘法

在線性迴歸模型中,最小二乘法就是試圖找到一條直線,使得所有樣本到直線上的歐氏距離之和最小

參數求解

求解w和b使E(w,b)=\sum ^m _{i=1}(y_i-wx_i-b)^2達到最小,這個過程稱之爲最小二乘法的參數估計

E(w,b)對w和b單獨求導的過程,具體推導過程參考:https://datawhalechina.github.io/pumpkin-book/#/chapter3/chapter3

令上面的兩個求導出來的結果等於0,我們可以得到w和b的兩個結果:

sklearn實戰線性迴歸

我們通過網上的一個公開的數據集,來實現如何利用機器學習庫sklearn進行線性迴歸學習線性迴歸問題。

  • 數據來源

  • 數據探索

  • 數據處理

  • 運行sklearn的線性模型

  • 模型評估

  • 模型優化

  • 可視化展示結果

數據來源

1、數據的介紹看這裏: http://archive.ics.uci.edu/ml/datasets/Combined+Cycle+Power+Plant

2、數據的下載地址請移步 http://archive.ics.uci.edu/ml/machine-learning-databases/00294/

數據中有4個字段屬性用來描述發電廠的輸出電力,最後一個是真實的輸出電力值。

我們現在需要做的是利用線性迴歸模型找到4個因素對輸出電力的影響,來預測後期的發電力。

數據探索

import pandas as pd
import numpy  as np
from sklearn import datasets, linear_model
from sklearn.linear_model import LinearRegression  # 導入線性迴歸模型

import matplotlib.pyplot as plt
%matplotlib inline 

1、讀取數據

2、數據信息查看

3、數據統計信息查看

數據處理

1、選擇需要的樣本數據X,也就是前4個字段的信息

2、選擇我們的樣本輸出標籤數據y,也就是最後一個屬性字段的數據

數據集劃分

數據集的劃分:一部分變成訓練集,另一部分劃分成測試集

from sklearn.model_selection import train_test_split  # 從模型選擇模塊中導入訓練、測試集模塊

X_train,X_test,y_train,y_test = train_test_split(X, y, random_state=1)

X_train   # 7176條數據訓練數據

測試集的數據是2392條:

樣本的輸出值的行記錄是和對應的X相同的;同時我們也發現:本次案例有75%的數據作爲了訓練集,25%作爲了測試集

擬合實例化對象

line.fit(X_train,y_train)
LinearRegression()

查看我們模擬出來的係數:

print(line.intercept_)  # 相當於是d;類似於截距
print(line.coef_)   # 相當於是每個w的取值
[460.05727267]
[[-1.96865472 -0.2392946   0.0568509  -0.15861467]]

到這裏,我們就已經模擬出來了線性迴歸的表達式:也就是PE和前面4個變量之間的關係式子:

PE = -1.96865472*AT -0.2392946*V + 0.0568509*AP -0.15861467*PH + 460.05727267

模型評價

通過訓練集的數據我們得到了線性迴歸的表達式,現在我們通過該表達式來模擬我們之前產生的測試集數據。

一個模型的評估,對於線性迴歸通常就是用上面我們介紹的均方差(Mean Squared Error, MSE)或者均方根差(Root Mean Squared Error, RMSE)在測試集上的表現來評價模型的好壞。下面通過代碼來進行測試:

y_pred = line.predict(X_test)  # 對測試集數據進行預測

y_pred
array([[457.26722361],
       [466.70748375],
       [440.33763981],
       ...,
       [457.39596168],
       [429.37990249],
       [438.16837983]])
len(y_pred)
2392

預測到結果之後,我們將預測值和實際值進行比較:

from sklearn import metrics  # 對比模塊
# 輸出MSE

print("MSE:",metrics.mean_squared_error(y_test,y_pred)) 
MSE: 20.837191547220346
# 輸出RMSE:MSE開根號的結果

print("RMSE: ",np.sqrt(metrics.mean_squared_error(y_test,y_pred)))
RMSE:  4.564777272465804

使用交叉驗證優化模型

交叉驗證法:將全部的數據樣本D劃分成k個大小相似的互斥子集。每個子集儘量保持數據分佈的一致性。然後用用k-1個子集作爲訓練集,剩下的那個作爲測試集。

這樣就可以獲取k組訓練集/測試集,從而進行k次的訓練和測試,最終返回k次訓練的均值。

我們可以使用sklearn中自帶的交叉驗證方法來優化我們得到的模型,下面的例子中,採用的10折交叉驗證:

line
LinearRegression()
from sklearn.model_selection import cross_val_predict  # 導入交叉驗證模塊

y_predicted = cross_val_predict(line,X,y,cv=10) 
y_predicted  # 通過交叉驗證得到的預測值
array([[467.24487977],
       [444.06421837],
       [483.53893768],
       ...,
       [432.47556666],
       [443.07355843],
       [449.74395838]])
len(y_predicted)
9568

通過交叉驗證得到的預測值predicted和真實值求MSE和RMSE:

# 輸出MSE

print("MSE:",metrics.mean_squared_error(y,y_predicted)) 
MSE: 20.79367250985753
print("RMSE: ",np.sqrt(metrics.mean_squared_error(y,y_predicted)))
RMSE:  4.560007950635342

我們發現:通過使用交叉驗證後的均方誤差優於未使用情況下的誤差

繪圖

最後,我們畫出真實的樣本值和預測值之間的圖形,當點距離中間y=x的值越近,說明預測損失越低。

下面是使用matplotlib繪圖的代碼和效果:

fig, ax = plt.subplots()

ax.scatter(y, y_predicted)

ax.plot([y.min(), y.max()], [y.min(), y.max()], 'k--', lw=3)

ax.set_xlabel('Measured')  # 真實值
ax.set_ylabel('Predicted') # 預測值

plt.show()

我把數據用Plotly_express重新繪製了一遍,看看效果:

data = pd.concat([pd.DataFrame(y),pd.DataFrame(y_predicted)],axis=1)
data.columns = ["Measured", "Predicted"]
data
import plotly_express as px

fig = px.scatter(data,
                 x="Measured",  # 真實值
                 y="Predicted",  # 預測值
                 trendline="ols",  # 趨勢線
                 trendline_color_override="red" # 顏色
                )

fig.show()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章