回歸預測分析(RANSAC、多項式回歸、殘差圖、隨機森林)
在本篇文章中,主要是介紹利用波士頓房價數據來掌握回歸預測分析的一些方法。通過本篇文章你可以學習到:
1、可視化數據集的重要特征
2、估計回歸模型的系數
3、使用RANSAC擬合高魯棒性回歸模型
4、如何來評價回歸模型
5、多項式回歸
6、決策樹回歸
7、隨機森林回歸
數據集下載地址:https://archive.ics.uci.edu/ml/machine-learning-databases/housing/housing.data
數據特征說明:https://archive.ics.uci.edu/ml/machine-learning-databases/housing/housing.names
掌握數據的基本情況
-
import pandas as pd
-
import matplotlib.pyplot as plt
-
import seaborn as sns
-
#設置seaborn的風格
-
sns.set(style= "whitegrid",context="notebook")
-
-
if __name__ == "__main__":
-
#讀取數據集
-
data = pd.read_csv( "data/train.csv")
-
#獲取csv的前5行數據
-
print(data.head( 5))
一、數據特征的可視化
探索性數據分析(Exploratory Data Analysis,EDA):是機器學習模型訓練之前的一個重要步驟,通過借助python第三方庫pandas、seaborn來繪圖,可以幫助我們分析和發現數據中的異常情況、數據的分布情況,以及特征將的相互關系。
由於屏幕大小關系,我們選擇四個自變量和因變量進行分析,indus(房屋所在鎮無零售業務區域所占比例),nox(一氧化氮濃度,每千萬分之一),rm(每處寓所的平均房間數),lstat(弱勢群體人口所占比例),medv(房屋平均價格,單位1000美元)。
1、繪制散點圖
-
#選擇需要繪制散點圖的列名
-
cols = [ "lstat","indus","nox","rm","medv"]
-
#通過seaborn繪制散點圖
-
sns.pairplot(data[cols],size= 1.5)
-
plt.show()
通過繪制特征的散點圖,我們可以發現變量之間的關系。對角線是變量的直方圖,可以看出特征的分布情況。通過medv(房價)的直方圖可以發現,房價服從正態分布,但是在大於40的部分包含了幾個異常值。通過rm(房間數)和medv(房價)的散點圖,第四行第五列,呈線性分布。而其他的三個變量與mdv(房價)呈一個非線性分布。
注意:訓練一個線性回歸模型並不需要自變量或者因變量呈正態分布,正態假設僅適用於某些統計檢驗和假設檢驗。
2、系數矩陣
除了通過變量之間的散點圖來尋找變量之間的關系,還可以通過變量之間的相關系數來發現變量的關系。相關系數矩陣,常用的有皮爾遜相關系數(Pearson product-moment correlation coefficient,Pearson's r)的方陣,通過它可以來衡量兩個特征之間的線性關系。皮爾遜相關系數的取值在[-1,1]范圍內,如果r=1,表示兩個變量呈正相關,r=0表示兩個變量沒有關系,r=-1表示兩個變量呈負相關。其實,相關系數矩陣就是標准化的協方差矩陣。
-
#獲取相關系數矩陣
-
cm = np.corrcoef(data[cols].values.T)
-
#設置字的比例
-
sns.set(font_scale= 1.5)
-
#繪制相關系數圖
-
hm = sns.heatmap(cm,cbar= True,annot=True,square=True,fmt=".2f",
-
annot_kws={ "size":15},yticklabels=cols,xticklabels=cols)
-
plt.show()
通過相關系數矩陣可以發現,lstat與medv的相關性最大(-0.74),其次就是rm與medv的相關性最大。通過之前的散點圖,也可以說明這一點。
二、常用的線性回歸算法
分析rm與medv的線性關系
1、線性回歸
-
#獲取特征和目標變量的值
-
X = data[ "rm"]
-
Y = data[ "medv"]
-
from sklearn.linear_model import LinearRegression
-
#創建一個線性模型對象
-
linear = LinearRegression()
-
X = np.array(X).reshape( 333,1)
-
Y = np.array(Y).reshape( 333,1)
-
#訓練模型
-
linear.fit(X,Y)
-
#繪制點
-
plt.scatter(X, Y, c= "blue")
-
#繪制直線
-
pred_Y = linear.predict(X)
-
plt.plot(X,pred_Y,c= "red")
-
plt.show()
通過rm與medv數據之間的關系,來擬合一條直線。通過rm與medv的點集可以發現,在周圍存在着很多的異常值,異常值對於線性回歸模型具有很嚴重的影響。下面通過RANSAC算法,清除異常值。
2、RANSAC擬合高魯棒性回歸
RANSAC(Random Sample Consenus),它是根據一組包含異常數據的樣本數據集,計算出數據的數學模型參數,得到有效樣本數據的算法。使用數據的一個子集(內點,Ran)來進行回歸模型的擬合。
RANSAC算法的工作流程如下:
1、從數據集中隨機抽取樣本構建內點集合擬合模型。
2、使用剩余的數據對上一步得到的模型進行測試,並將落在預定公差范圍內的樣本點增加到內點集合中。
3、使用全部的內點集合數據再次進行模型的擬合。
4、使用內點集合來估計模型的誤差。
5、如果模型性能達到了用戶設定的特定閾值或者迭代的次數達到了預定的次數,則算法終止,否則重復從第一步開始。
-
from sklearn.linear_model import RANSACRegressor
-
'''
-
max_trials設置最大迭代次數為100
-
min_samples隨機抽取內點的最小樣本數為50
-
residual_metric計算擬合曲線與樣本點的距離的絕對值
-
residual_threshold設置預定公差,小於這個值才被加入到內點集合
-
'''
-
ransac = RANSACRegressor(LinearRegression(),max_trials= 100,min_samples=50,
-
residual_metric= lambda x:np.sum(np.abs(x),axis=1),
-
residual_threshold= 5.0,random_state=0)
-
ransac.fit(X,Y)
-
inlier_mask = ransac.inlier_mask_
-
outlier_mask = np.logical_not(inlier_mask)
-
line_X = np.arange( 3,10,1)
-
line_y_ransac = ransac.predict(line_X[:,np.newaxis])
-
plt.scatter(X[inlier_mask],Y[inlier_mask],c= "blue",marker="o",label="內點")
-
plt.scatter(X[outlier_mask],Y[outlier_mask],c= "lightgreen",marker="s",label="異常值")
-
plt.plot(line_X,line_y_ransac,color= "red")
-
plt.xlabel( "房間數")
-
plt.ylabel( "房價")
-
plt.legend(loc= "upper left")
-
plt.show()
三、線性回歸模型性能的評估
1、殘差圖
通過繪制殘差圖能夠直觀的發現真實值與預測值之間的差異或垂直距離,通過真實值與預測值之間的差異來對回歸模型進行評估。殘差圖可以作為圖形分析方法,可以對回歸模型進行評估、獲取模型的異常值,同時還可以檢查模型是否是線性的,以及誤差是否隨機分布。
-
#獲取特征和目標變量的值
-
X = data[ "rm"]
-
Y = data[ "medv"]
-
from sklearn.linear_model import LinearRegression
-
from sklearn.model_selection import train_test_split
-
# #創建一個線性模型對象
-
linear = LinearRegression()
-
X = np.array(X).reshape( 333,1)
-
Y = np.array(Y).reshape( 333,1)
-
# #訓練模型
-
linear.fit(X,Y)
-
#將數據集分為訓練集和測試集
-
train_x,test_x,train_y,test_y = train_test_split(X,Y,test_size= 0.2)
-
train_y_pred = linear.predict(train_x)
-
test_y_pred = linear.predict(test_x)
-
plt.scatter(train_y_pred,train_y_pred-train_y,c= "blue",marker="o",label="訓練數據")
-
plt.scatter(test_y_pred,test_y_pred-test_y,c= "lightgreen",marker="s",label="測試數據")
-
plt.legend(loc= "upper left")
-
plt.hlines(y= 0,xmin=-10,xmax=50,lw=2,color="red")
-
plt.xlim([ -10,50])
-
plt.xlabel( "預測值")
-
plt.ylabel( "殘差")
-
plt.show()
最好的模型預測結果的殘差為0,在實際應用中,這種情況是不可能發生的。但是,對於一個好的模型,我們期望誤差是隨機分布的,同時殘差也是在y=0水平線附近波動。通過殘差圖也可以發現異常值,偏離y=0比較遠的點。
2、均方誤差(MSE)
均方誤差(Mean Squared Error,MSE):真實值與預測值差的平方和的平均值,計算公式如下
-
from sklearn.metrics import mean_squared_error
-
print( "train MSE:%.3f"%mean_squared_error(train_y,train_y_pred))
-
#train MSE:46.037
-
print( "test MSE:%.3f"%mean_squared_error(test_y,test_y_pred))
-
#test MSE:35.919
除了均方誤差之外,還可以通過絕對值誤差來衡量模型的性能。
3、決定系數R^2
在某些情況下決定系數(coefficient of determination)R^2非常重要,可以將其看成一個MSE標准化版本,R^2是模型捕獲響應方差的分數。對於訓練集來說,R^2的取值范圍為[0,1],對於測試集來說,R^2取值可能為負。如果R^2越接近與1表明其模型的性能越好。R^2計算公式如下:
-
from sklearn.metrics import r2_score
-
print( "train r2:%.3f"%r2_score(train_y,train_y_pred))
-
#train r2:0.473
-
print( "test r2:%.3f"%r2_score(test_y,test_y_pred))
-
#test r2:0.485
四、非線性回歸
1、多項式回歸
對於不滿足線性回歸,可以通過加入多項式來使用多項式回歸。
前面通過散點圖繪制了四個特征與房價之前關系,發現lstat與房價之間呈現一個非線性關系,我們分別使用線性回歸於多項式回歸來擬合lstat與房價之間的線性關系,對比R^2的變化。
-
from sklearn.linear_model import LinearRegression
-
from sklearn.preprocessing import PolynomialFeatures
-
from sklearn.metrics import r2_score
-
-
#線性回歸
-
X = np.array(data[ "lstat"]).reshape(333,1)
-
Y = np.array(data[ "medv"]).reshape(333,1)
-
linear = LinearRegression()
-
linear.fit(X,Y)
-
linear_y = linear.predict(X)
-
print( "linear R^2:%.3f"%r2_score(Y,linear_y))
-
#linear R^2:0.546
-
-
#多項式回歸
-
qua_linear = LinearRegression()
-
#設置x的最大次數為2
-
quadratic = PolynomialFeatures(degree= 2)
-
X_quad = quadratic.fit_transform(X)
-
qua_linear.fit(X_quad,Y)
-
qua_linear_y = qua_linear.predict(X_quad)
-
print( "polynomial R^2:%.3f"%r2_score(Y,qua_linear_y))
-
#polynomial R^2:0.641
-
-
#繪點
-
plt.scatter(X,Y,label= "數據",marker="o",color="blue")
-
X_linear = np.arange(np.min(X),np.max(X), 1)[:,np.newaxis]
-
#線性回歸
-
plt.plot(X_linear,linear.predict(X_linear),label= "線性回歸",
-
color= "green",lw=2,linestyle="-")
-
#多項式擬合
-
plt.plot(X_linear,qua_linear.predict(quadratic.fit_transform(X_linear))
-
,label= "多項式回歸",color="red",lw=2,linestyle="-")
-
plt.xlabel( "lstat(弱勢群體人口所占比例%)")
-
plt.ylabel( "medv(房價)")
-
plt.legend(loc= "upper right")
-
plt.show()
2、特征轉換
對於這種非線性回歸除了使用多項式回歸還可以使用log回歸。對於lstat與medv之間的關系,可以先將lstat進行log對數轉換,medv進行平方根轉換之后再使用線性回歸。
-
#特征轉換
-
X_log = np.log(X)
-
Y_sqrt = np.sqrt(Y)
-
linear = LinearRegression()
-
linear.fit(X_log,Y_sqrt)
-
print( "R^2:%.3f"%r2_score(Y_sqrt,linear.predict(X_log)))
-
#R^2:0.692
-
-
plt.scatter(X_log,Y_sqrt,label= "數據",marker="o",color="blue")
-
lin_X = np.arange(np.min(X_log),np.max(X_log), 1)[:,np.newaxis]
-
plt.plot(lin_X,linear.predict(lin_X),label= "線性擬合",linestyle="-",color="red")
-
plt.show()
通過上圖可以發現,將特征轉換之后由原來的非線性關系變成了線性關系,而且R^2比多項回歸的結果還要好。
3、隨機森林
隨機森林是一種集成算法,它是通過組合多顆決策樹。能夠降低模型的方差,與單顆決策樹相比,隨機森林通常具有更好的泛化性能。它對數據集中的異常值不敏感,不需要過多的參數調優。
-
from sklearn.ensemble import RandomForestRegressor
-
from sklearn.model_selection import train_test_split
-
-
#將數據集分為測試集和訓練集
-
train_x,test_x,train_y,test_y = train_test_split(X,Y,test_size= 0.3)
-
'''
-
n_estimators:估計器(樹)的個數
-
criterion:優化目標
-
'''
-
forest = RandomForestRegressor(n_estimators= 100,criterion="mse",n_jobs=1)
-
forest.fit(train_x,train_y)
-
print( "train r2:%.3f"%r2_score(train_y,forest.predict(train_x)))
-
#train r2:0.929
-
print( "test r2:%.3f"%r2_score(test_y,forest.predict(test_x)))
-
#test r2:0.227