【火爐煉AI】機器學習005-多項式迴歸器的建立和測試

煉丹老頑童發表於2018-08-05

【火爐煉AI】機器學習005-多項式迴歸器的建立和測試

(本文所使用的Python庫和版本號: Python 3.5, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )

前面講到了簡單線性迴歸器和嶺迴歸器,這兩類迴歸器都是將資料集擬合成直線,但現實生活中,有很多情況,資料集的分佈並不是簡單的線性關係,還有可能是曲線關係,聚類關係,隨機分佈關係等,對於這些不同的資料集分佈關係,需要使用不同的迴歸器來擬合。


1. 分析資料集

由於缺少資料集,我自己用程式碼生成了一些資料,資料的生成過程和(【火爐煉AI】機器學習003-簡單線性迴歸器的建立,測試,模型儲存和載入)類似,如下程式碼所示。

# 構建服從多項式迴歸特性的資料集
np.random.seed(37) # 使得每次執行得到的隨機數都一樣
x=np.arange(2,102) 
x_shift=np.random.normal(size=x.shape)
x=x+x_shift # 構建的x含有100個數,通過在整數點引入偏差得到

error=np.random.normal(size=x.shape)*800 # 構建噪音,*800是擴大噪音的影響
y=1.19*x*x+0.82*x+5.95+error
plt.scatter(x,y) # 可以檢視生成的資料集的分佈情況

dataset=[(i,j) for i,j in zip(x,y)]
from sklearn.model_selection import train_test_split
train_set,test_set=train_test_split(dataset,test_size=0.2,random_state=37)
X_train=np.array([i for (i,j) in train_set]).reshape(-1,1) # 後面的fit需要先reshape
y_train=np.array([j for (i,j) in train_set]).reshape(-1,1)
X_test= np.array([i for (i,j) in test_set]).reshape(-1,1)
y_test= np.array([j for (i,j) in test_set]).reshape(-1,1)
複製程式碼

生成的資料集分佈

########################小**********結###############################

1,資料集的構建可以採用在標準資料中引入誤差的方式。

2,在迴歸或分類模型中,經常要將資料集對映到二維平面上,通過散點圖的方式來檢視資料集的空間分佈,有了直觀的初步印象後,才能選擇更合適的迴歸或分類模型。

#################################################################


2. 簡單線性迴歸器模型擬合資料集

圖中顯示的資料集好像服從線性關係,也好像服從多項式關係,對於這樣的情況,可以先用簡單線性迴歸器擬合得到迴歸模型,然後用測試集看看該模型的優劣。如下程式碼:

# 如果採用簡單線性迴歸器進行擬合得到簡單的擬合直線
from sklearn import linear_model
linear_regressor=linear_model.LinearRegression() # 建立線性迴歸器物件
linear_regressor.fit(X_train,y_train) # 使用訓練資料集訓練該回歸器物件

# 檢視擬合結果
y_predict=linear_regressor.predict(X_train) # 使用訓練後的迴歸器物件來擬合訓練資料
plt.figure()
plt.scatter(X_train,y_train,label='train_set')
plt.scatter(X_test,y_test,color='r',label='test_set')
plt.plot(X_train,y_predict,'-b',linewidth=3,label='fitted_line')
plt.legend()

# 用測試集看看該線性迴歸器模型的測試結果
y_predict_test=linear_regressor.predict(X_test)
import sklearn.metrics as metrics
print('簡單線性迴歸器模型的評測結果----->>>')
print('均方誤差MSE:{}'.format(
    round(metrics.mean_squared_error(y_predict_test,y_test),2)))
print('解釋方差分:{}'.format(
    round(metrics.explained_variance_score(y_predict_test,y_test),2)))
print('簡單線性迴歸器得到的直線方程為:y={:.3f}x+{:.3f}'
      .format(linear_regressor.coef_[0][0],linear_regressor.intercept_[0]))
複製程式碼

---------------------------輸---------出--------------------------------

簡單線性迴歸器模型的評測結果:
均方誤差MSE:1906916.26
解釋方差分:0.85
簡單線性迴歸器得到的直線方程為:y=117.061x+-1924.904

---------------------------------完-------------------------------------

簡單線性迴歸得到的擬合直線

########################小**********結###############################

1,使用簡單線性迴歸器得到的模型在測試集上的MSE非常大,看來還有非常大的優化空間。

#################################################################


3. 採用多項式迴歸器

由於簡單線性迴歸器模型在該資料集上的表現非常差,故而我們需要改進模型,所以嘗試使用多項式迴歸器。

# 使用多項式迴歸器來對資料集進行擬合,得到多項式方程
from sklearn.preprocessing import PolynomialFeatures
polynomial=PolynomialFeatures(degree=2) # 構建多項式迴歸器物件
# degree是多項式的次數,此處初步的設定為2

X_train_transformed=polynomial.fit_transform(X_train)
# print(X_train_transformed) #transformed之後的資料是degree+1維
from sklearn import linear_model
poly_regressor=linear_model.LinearRegression() # 也是構建線性迴歸器
poly_regressor.fit(X_train_transformed,y_train) # 對多項式迴歸器進行訓練

# 檢視擬合結果
y_predict_polynomial=poly_regressor.predict(X_train_transformed) 
plt.figure()
plt.scatter(X_train,y_train,label='train_set')
plt.scatter(X_test,y_test,color='r',label='test_set')

# print(y_predict_polynomial.shape) #(80, 1)
plt.plot(X_train,y_predict_polynomial,'-b',linewidth=3,label='fitted_poly') 
# 上面的plot會產生很多條線。。。。。
plt.legend()

# 用測試集看看該線性迴歸器模型的測試結果
X_test_transformed=polynomial.fit_transform(X_test)
y_predict_test=poly_regressor.predict(X_test_transformed)
import sklearn.metrics as metrics
print('多項式迴歸器模型的評測結果----->>>')
print('均方誤差MSE:{}'.format(
    round(metrics.mean_squared_error(y_predict_test,y_test),2)))
print('解釋方差分:{}'.format(
    round(metrics.explained_variance_score(y_predict_test,y_test),2)))
print('得到的多項式方程為:y={:.3f}x^2+({:.3f}x)+{:.3f}'
      .format(poly_regressor.coef_[0][-1],
              poly_regressor.coef_[0][-2],
              poly_regressor.intercept_[0]))
複製程式碼

------------------------------輸---------出-----------------------------

多項式迴歸器模型的評測結果:
均方誤差MSE:525885.05
解釋方差分:0.97
得到的多項式方程為:y=1.374x^2+(-22.187x)+487.664

---------------------------------完-------------------------------------

多項式迴歸得到的多條擬合直線

########################小**********結###############################

1,採用多項式迴歸器,首先需要將X特徵向量經過fit_transform()函式轉變到對應的維度,然後才能使用LinearRegression()物件的fit()進行訓練。

2,雖然使用了多項式迴歸器進行擬合,但是得到的MSE仍然比較大,只是比線性迴歸器得到的MSE小一些而已。所以MSE這個指標是不是不靠譜?

3,從解釋方差分上來看,多項式迴歸器對test set有了更大改進,數值為0.97

4,圖中線條比較多,是因為19行plt.plot(X_train,y_predict_polynomial)繪製了多次所導致,我暫時沒有明白為什麼會plot多個線條。

#################################################################


4. 對新資料進行預測

對於訓練好的模型,不管是簡單線性迴歸器還是稍複雜的多項式迴歸器,都要用來進行新資料的預測,下面我分別用這兩個迴歸器預測一個新資料。

# 使用多項式迴歸器預測新的資料值
data_X=[[66]] # 需要計算的資料點 X值
print('用直線迴歸器得到的數值:{}'.format(linear_regressor.predict(data_X)))
print('用擬合直線計算的數值:{}'.format(
    linear_regressor.coef_[0][0]*data_X[0][0]+linear_regressor.intercept_[0]))

data_X_transormed=polynomial.fit_transform(data_X)
data_X_predict=poly_regressor.predict(data_X_transormed)
# print(poly_regressor.coef_, '\n',poly_regressor.intercept_)
print('用多項式迴歸器得到的數值:{}'.format(data_X_predict))
print('用多項式曲線計算的數值:{}'.format(
    poly_regressor.coef_[0][-1]*np.power(data_X[0][0],2)+
    poly_regressor.coef_[0][-2]*data_X[0][0]+
    poly_regressor.intercept_[0]))
# 兩者資料相等,代表predict的確是按照這個曲線方程來計算的。
複製程式碼

------------------------------輸---------出-----------------------------

用直線迴歸器得到的數值:[[5801.09012059]] 用擬合直線計算的數值:5801.090120592645 用多項式迴歸器得到的數值:[[5010.58753529]] 用多項式曲線計算的數值:5010.587535291616

---------------------------------完-------------------------------------

########################小**********結###############################

1,由於模型不同,對新資料進行預測,得到的結果也不同,但是由於多項式迴歸器模型對於test set的解釋方差分要大一些,故而我們認為本例中多項式迴歸器模型更好一些,故而對新資料預測的結果更可靠一些。

2,如果某些資料集並不是服從簡單的二項式,可以增加PolynomialFeatures(degree=2) 中degree的數值大小來提高x的最高次,得到的模型可能會更準確一些,但是要防止模型對train set的過擬合。

#################################################################


注:本部分程式碼已經全部上傳到(我的github)上,歡迎下載。

參考資料:

1, Python機器學習經典例項,Prateek Joshi著,陶俊傑,陳小莉譯

相關文章