前言
這一篇文章,我會詳細介紹如何利用Python來實作線性回歸以及線性回歸的實戰模擬,以及回歸模型的評估指標的詳細介紹,感興趣的朋友可以看一看,
目錄
- 前言
- 1 線性回歸的Scikit-learn實作
- 1.1 匯入模塊后開始下載資料
- 1.2 拆分資料集(訓練集和測驗集)
- 1.3 線性回歸建模
- 1.4 訓練資料
- 1.5 模型評估
- 1.6 將資料集標準化之后再訓練
- 1.7 繪制擬合影像
- 2 多重共線性
- 2.1 理解與代碼實作
- 2.2 與變換前的模型擬合效果進行比對
- 結束語
1 線性回歸的Scikit-learn實作
接下來以一個加利福尼亞的房價預測為案例進行講解實作,
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_val_score
from sklearn.datasets import fetch_california_housing #加利福尼亞房屋價值資料集
import pandas as pd
1.1 匯入模塊后開始下載資料
housevalue = fetch_california_housing()
housevalue

housevalue.feature_names
# 特征解釋
# MedInc:該街區住戶的收入中位數
# HouseAge:該街區房屋使用年代的中位數
# AveRooms:該街區平均的房間數目
# AveBedrms:該街區平均的臥室數目
# Population:街區人口
# AveOccup:平均入住率
# Latitude:街區的緯度
# Longitude:街區的經度

將資料轉成DataFrame:
X = pd.DataFrame(housevalue.data,columns=housevalue.feature_names)
X

y = housevalue.target
y

1.2 拆分資料集(訓練集和測驗集)
Xtrain,Xtest,Ytrain,Ytest = train_test_split(X,y,test_size=0.3,random_state=420)
1.3 線性回歸建模
lr = LinearRegression()
1.4 訓練資料
lr.fit(Xtrain,Ytrain)
1.5 模型評估
接下來進行模型評估,這里的評估指標有很多,我們先從MSE均方誤差開始介紹,
MSE均方誤差
- MSE趨于0效果越好
from sklearn.metrics import mean_squared_error
#對訓練集做預測
y_pred =lr.predict(Xtrain)#得到預測結果
# 評估訓練集集合情況 引數1:真實標簽 引數2:預測標簽
mean_squared_error(Ytrain,y_pred)
0.52185226625331
y_test_pred = lr.predict(Xtest)
mean_squared_error(Ytest,y_test_pred)
0.5309012639324568
注意,這個MSE值是越小越趨于0越好,在這里MSE為0.53其實不是很好,當然還要結合其他指標評估,
交叉驗證
lr2 = LinearRegression()
# 交叉驗證使用-MSE指標
cross_val_score(lr2,Xtrain,Ytrain,cv=10,scoring='neg_mean_squared_error')
array([-0.52730876, -0.50816696, -0.48736401, -0.49269076, -0.56611205,
-0.53795641, -0.48253409, -0.5130032 , -0.53188562, -0.60443733])
注意這里的指標前面是有neg_的,不要忘了,不能會報錯,同時結果是負數也不影響你的判斷,
當然,如果你想知道里面指標都有哪些,可以用到下列方法:
import sklearn
sorted(sklearn.metrics.SCORERS.keys())
接下來看下交叉驗證的平均值:
cross_val_score(lr2,Xtrain,Ytrain,cv=10,scoring='neg_mean_squared_error').mean()
-0.525145918217335
MAE絕對均值誤差
當然啦,除了MSE,還可以用MAE作為評估指標,MAE與MSE差不多,兩個選一個用即可,
from sklearn.metrics import mean_absolute_error
mean_absolute_error(Ytrain,y_pred)
# 交叉驗證使用-MAE指標
cross_val_score(lr2,Xtrain,Ytrain,cv=10,scoring='neg_mean_absolute_error')
cross_val_score(lr2,Xtrain,Ytrain,cv=10,scoring='neg_mean_absolute_error').mean()
-0.5313931576388832
R方
- 方差是來衡量資料集包含了多少資訊量(資料都是0和資料從1到1000都有,很明顯是后者資訊量大)
- R方越趨于1擬合效果就越好,趨于0擬合效果越差
- R方是回歸模型最常用的評估指標,
from sklearn.metrics import r2_score
r2_score(Ytrain,y_pred) #訓練集R2
0.6067440341875014
r2_score(Ytest,y_test_pred) #測驗集R2
0.6043668160178819
或者可以直接這樣:
lr.score(Xtrain,Ytrain)
0.6067440341875014
lr.score(Xtest,Ytest)
0.6043668160178819
細心的朋友應該可以看到上面的資料是跟下面的資料是一樣的,因為這里的lr.score()默認使用的指標就是R方,
同樣這里也可以用交叉驗證:
cross_val_score(lr,Xtrain,Ytrain,cv=10,scoring='r2')
cross_val_score(lr,Xtrain,Ytrain,cv=10,scoring='r2').mean()
0.603923823554634
查看模型系數
lr.coef_ #訓練結果

lr.intercept_ # 截距
-36.25689322920392
list(zip(X.columns,lr.coef_))

這里也就是我們求的系數,也就是
w
w
w,
1.6 將資料集標準化之后再訓練
from sklearn.preprocessing import StandardScaler
std = StandardScaler()
#對訓練集進行標準化
X_train_std = std.fit_transform(Xtrain)
X_train_std

我們再看一下之前的資料:
Xtrain

區別還是很大的,
接下來用標準化的資料來訓練,
lr3 = LinearRegression()
lr3.fit(X_train_std,Ytrain)
lr3.score(X_train_std,Ytrain)
0.6067440341875014
稍微起了一點點作用(因為各資料之間的差異性不是很大),
1.7 繪制擬合影像
- 繪制預測值的散點和真實值的直線進行對比
- 如果兩者趨勢越接近(預測值的散點越靠近真實值)擬合效果優秀
# 因為資料是無序的,所以畫出的點是亂的
plt.scatter(range(len(Ytest)),Ytest,s=2)
plt.show()

那怎么辦呢?
我們可以給它排個序,
plt.scatter(range(len(Ytest)),sorted(Ytest),s=2)
plt.show()

那為了讓預測值和真實值能一一對應,應該用如下方法:
y_test_pred[np.argsort(Ytest)]
將排序好的資料再進行繪圖
plt.scatter(range(len(Ytest)),sorted(Ytest),s=2,label='True')
plt.scatter(range(len(Ytest)),y_test_pred[np.argsort(Ytest)],s=2,c='r',label='Predict',alpha=0.3) # 這里的alpha是用來調整點透明度的
plt.legend()
plt.show()

總體看起來還可以,但是可以發現后面的資料明顯有些預測得不好,
2 多重共線性
2.1 理解與代碼實作
上文我們也說了,在線性回歸當中不能存在多重共線性,為什么呢?
這里先回到我們上文:
這里可解的前提是矩陣的逆是存在的,而為什么不能存在多重共線性正是因為這樣的話逆會不存在,
我們回想一下逆矩陣的計算公式: A ? 1 = 1 ∣ A ∣ A ? A^{-1}=\frac{1}{|A|}A^* A?1=∣A∣1?A?其中這個 A ? A^* A?是伴隨矩陣,而任何矩陣都可以有伴隨矩陣,所以這個并不影響逆矩陣的存在,所以關鍵在于 ∣ A ∣ |A| ∣A∣, ∣ A ∣ |A| ∣A∣是矩陣 A A A的行列式,并且它還在分母上,這就意味著它要是等于0,那么就不存在逆矩陣了,
我們看一下下面這張圖:

這是三個矩陣進行了一些初等行變換,轉換成了梯形矩陣(轉換往往是為了機器方便后續計算),而矩陣
A
A
A最終轉換出現了零行,而矩陣
B
B
B第三行也接近零行了,只有第三行較為正常,
熟悉行列式計算的朋友們應該能想起來 A A A的值等于0,而矩陣 B B B是接近為0,這會導致什么結果?這樣會導致 A A A的 1 ∣ A ∣ \frac{1}{|A|} ∣A∣1?不存在,而 B B B的 1 ∣ A ∣ \frac{1}{|A|} ∣A∣1?接近于無窮大(分母越小越趨于無窮大),這些都是我們不希望看到的,
矩陣A中第一行和第三行的關系,被稱為“精確相關關系”,即完全相關,一行可使另一行為0,矩陣B則屬于非常接近于”精確相關關系“,但又不是完全相關,這種關系被稱為”高度相關關系“,在這種情況下,最小二乘法可以使用,不過得到的逆會很大,直接影響我們對w引數向量的求解,
所以到這里,朋友們應該知道為什么線性回歸不能存在多重共線性了吧,
那值得一提的是,多重共線性如果存在,則線性回歸就無法使用最小二乘法來進行求解,或者求解就會出現偏差,幸運的是,不能存在多重共線性,不代表不能存在相關性——機器學習不要求特征之間必須獨立,必須不相關,只要不是高度相關或者精確相關就好,多重共線性是一種統計現象,是指線性模型中的特征(解釋變數)之間由于存在精確相關關系或高度相關關系,多重共線性的存在會使模型無法建立,或者估計失真, 多重共線性使用指標方差膨脹因子(variance inflation factor,VIF)來進行衡量,通常當我們提到“共線性”,都特指多重共線性,相關性是衡量兩個或多個變數一起波動的程度的指標,它可以是正的,負的或者0, 當我們說變數之間具有相關性,通常是指線性相關性,
劃重點: 在現實中特征之間完全獨立的情況其實非常少,因為大部分資料統計手段或者收集者并不考慮統計學或者機器學習建模時的需求,現實資料多多少少都會存在一些相關性,極端情況下,甚至還可能出現收集的特征數量比樣本數量多的情況,通常來說,這些相關性在機器學習中通常無傷大雅(在統計學中他們可能是比較嚴重的問題),即便有一些偏差,只要最小二乘法能夠求解,我們都有可能會無視掉它,畢竟,想要消除特征的相關性,無論使用怎樣的手段,都無法避免進行特征選擇,這意味著可用的資訊變得更加少,對于機器學習來說,很有可能盡量排除相關性后,模型的整體效果會受到巨大的打擊,這種情況下,我們選擇不處理相關性,只要結果好,一切萬事大吉,然而多重共線性就不是這樣一回事了,它的存在會造成模型極大地偏移,無法模擬資料的全貌,因此這是必須解決的問題,
那接下來我們來看看多重共線性在我們代碼中是如何解決的吧?
X.columns = ['住戶的收入中位數','房屋使用年代的中位數','該街區平均的房間數目',
'該街區平均的臥室數目','街區人口','平均入住率','街區的緯度','街區的經度']
# 先把列名都變成中文的,方便觀察,
我們可以通過多項式把這些列構建出來,
首先把包導進來:
from sklearn.preprocessing import PolynomialFeatures
進行實體化(這就是多項式轉化的物件)
poly = PolynomialFeatures(degree=2).fit(X,y)
# 這里的degree設定過大電腦會很卡的,2 3 4就差不多了
poly.get_feature_names(X.columns)#通過多項式構造列
[‘1’,
‘住戶的收入中位數’,
‘房屋使用年代的中位數’,
‘該街區平均的房間數目’,
‘該街區平均的臥室數目’,
‘街區人口’,
‘平均入住率’,
‘街區的緯度’,
‘街區的經度’,
‘住戶的收入中位數^2’,
‘住戶的收入中位數 房屋使用年代的中位數’,
‘住戶的收入中位數 該街區平均的房間數目’,
‘住戶的收入中位數 該街區平均的臥室數目’,
‘住戶的收入中位數 街區人口’,
‘住戶的收入中位數 平均入住率’,
‘住戶的收入中位數 街區的緯度’,
‘住戶的收入中位數 街區的經度’,
‘房屋使用年代的中位數^2’,
‘房屋使用年代的中位數 該街區平均的房間數目’,
‘房屋使用年代的中位數 該街區平均的臥室數目’,
‘房屋使用年代的中位數 街區人口’,
‘房屋使用年代的中位數 平均入住率’,
‘房屋使用年代的中位數 街區的緯度’,
‘房屋使用年代的中位數 街區的經度’,
‘該街區平均的房間數目^2’,
‘該街區平均的房間數目 該街區平均的臥室數目’,
‘該街區平均的房間數目 街區人口’,
‘該街區平均的房間數目 平均入住率’,
‘該街區平均的房間數目 街區的緯度’,
‘該街區平均的房間數目 街區的經度’,
‘該街區平均的臥室數目^2’,
‘該街區平均的臥室數目 街區人口’,
‘該街區平均的臥室數目 平均入住率’,
‘該街區平均的臥室數目 街區的緯度’,
‘該街區平均的臥室數目 街區的經度’,
‘街區人口^2’,
‘街區人口 平均入住率’,
‘街區人口 街區的緯度’,
‘街區人口 街區的經度’,
‘平均入住率^2’,
‘平均入住率 街區的緯度’,
‘平均入住率 街區的經度’,
‘街區的緯度^2’,
‘街區的緯度 街區的經度’,
‘街區的經度^2’]
X_ = poly.transform(X) #多項式變化后
X_

reg = LinearRegression().fit(X_,y)#使用轉化后的資料進行建模訓練
reg.coef_

[*zip(poly.get_feature_names(X.columns),reg.coef_)]
[(‘1’, 5.919547622013033e-08),
(‘住戶的收入中位數’, -11.24302557462409),
(‘房屋使用年代的中位數’, -0.8488985630544302),
(‘該街區平均的房間數目’, 6.441059285824681),
(‘該街區平均的臥室數目’, -31.59133038837795),
(‘街區人口’, 0.0004060907004548096),
(‘平均入住率’, 1.0038623267368598),
(‘街區的緯度’, 8.705681906512265),
(‘街區的經度’, 5.880632740950536),
(‘住戶的收入中位數^2’, -0.031308123295653814),
(‘住戶的收入中位數 房屋使用年代的中位數’, 0.0018599473971959836),
(‘住戶的收入中位數 該街區平均的房間數目’, 0.04330204720647667),
(‘住戶的收入中位數 該街區平均的臥室數目’, -0.18614230286022418),
(‘住戶的收入中位數 街區人口’, 5.728313132329231e-05),
(‘住戶的收入中位數 平均入住率’, -0.002590194649331616),
(‘住戶的收入中位數 街區的緯度’, -0.15250571828258908),
(‘住戶的收入中位數 街區的經度’, -0.14424294425079082),
(‘房屋使用年代的中位數^2’, 0.00021172532576618083),
(‘房屋使用年代的中位數 該街區平均的房間數目’, -0.0012621899769862225),
(‘房屋使用年代的中位數 該街區平均的臥室數目’, 0.010611505200531843),
(‘房屋使用年代的中位數 街區人口’, 2.818853379960247e-06),
(‘房屋使用年代的中位數 平均入住率’, -0.0018171694411520457),
(‘房屋使用年代的中位數 街區的緯度’, -0.010069037338454228),
(‘房屋使用年代的中位數 街區的經度’, -0.00999950188065276),
(‘該街區平均的房間數目^2’, 0.007269477252714056),
(‘該街區平均的房間數目 該街區平均的臥室數目’, -0.0689064336889457),
(‘該街區平均的房間數目 街區人口’, -6.823655839335575e-05),
(‘該街區平均的房間數目 平均入住率’, 0.02688788388649532),
(‘該街區平均的房間數目 街區的緯度’, 0.08750899386040001),
(‘該街區平均的房間數目 街區的經度’, 0.08228903893629276),
(‘該街區平均的臥室數目^2’, 0.1601809459853239),
(‘該街區平均的臥室數目 街區人口’, 0.0005142639649729885),
(‘該街區平均的臥室數目 平均入住率’, -0.08719113908251339),
(‘該街區平均的臥室數目 街區的緯度’, -0.4370430295730081),
(‘該街區平均的臥室數目 街區的經度’, -0.4041506064429531),
(‘街區人口^2’, 2.737790919310526e-09),
(‘街區人口 平均入住率’, 1.9142676560849866e-05),
(‘街區人口 街區的緯度’, 2.2952983608247036e-05),
(‘街區人口 街區的經度’, 1.4656775581091295e-05),
(‘平均入住率^2’, 8.715609635939173e-05),
(‘平均入住率 街區的緯度’, 0.02133445921833345),
(‘平均入住率 街區的經度’, 0.016241293829958238),
(‘街區的緯度^2’, 0.061886735759100135),
(‘街區的緯度 街區的經度’, 0.10810717326205625),
(‘街區的經度^2’, 0.039907735048536896)]
同樣,這里每個列對應的值就是對應的系數,可以理解為影響結果的重要性大小,
我們也可以把這個化成dataframe格式:
coeff = pd.DataFrame([poly.get_feature_names(X.columns),reg.coef_.tolist()]).T
coeff
大家可以自行去試一試,這里截圖太長就不放了,
2.2 與變換前的模型擬合效果進行比對
poly = PolynomialFeatures(degree=4).fit(X,y)
X_ = poly.transform(X)
變換前:
lr = LinearRegression().fit(X,y)
lr.score(X,y)
0.6062326851998051
變換后的:
lr1 = LinearRegression().fit(X_,y)
lr1.score(X_,y)
0.745313897131279
通過結果不難發現,變換后的結果確實要提升不少,不過切忌degree調太高,電腦會卡死的哈哈,
另外,我這里沒有劃分訓練集和測驗集,大家也可以自己去試一試,
結束語
那么關于線性回歸的介紹就到這里啦,下一篇講啥好呢,,,
emmm,明天再看吧,
推薦關注的專欄
👨?👩?👦?👦 機器學習:分享機器學習實戰專案和常用模型講解
👨?👩?👦?👦 資料分析:分享資料分析實戰專案和常用技能整理
機器學習系列往期回顧
💜 如何搞懂機器學習中的線性回歸模型?機器學習系列之線性回歸基礎篇
🖤 你真的了解分類模型評估指標都有哪些嗎?【附Python代碼實作】
💙 一文帶你用Python玩轉決策樹 ??畫出決策樹&各種引數詳細說明??決策樹的優缺點又有哪些?
🧡 開始學習機器學習時你必須要了解的模型有哪些?機器學習系列之決策樹進階篇
💚 開始學習機器學習時你必須要了解的模型有哪些?機器學習系列之決策樹基礎篇
?? 以??簡單易懂??的語言帶你搞懂有監督學習演算法【附Python代碼詳解】機器學習系列之KNN篇
💜 開始學習機器學習之前你必須要了解的知識有哪些?機器學習系列入門篇
往期內容回顧
🖤 我和關注我的前1000個粉絲“合影”啦!收集前1000個粉絲進行了一系列資料分析,識訓滿滿
💚 MySQL必須掌握的技能有哪些?超細長文帶你掌握MySQL【建議收藏】
💜 Hive必須了解的技能有哪些?萬字博客帶你掌握Hive??【建議收藏】
CSDN@報告,今天也有好好學習
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/300173.html
標籤:AI
