多項式回歸及過擬合欠擬合處理

回顧

  • 什么是回歸問題
    • 如果需要處理的標簽數據為連續性數據,則該問題為回歸問題
  • 什么是線性回歸
    • 就是在找尋特征數據和標簽數據之間的線性關系,可以使用權重系數來表示。
    • 權重系數的個數一定是和特征維度保持一致。
  • 線性回歸的矩陣表達
    • y = wx + b
    • Y = XWt
  • 損失函數
    • 誤差平方和/殘差平方和
  • 最小二乘法的作用
    • 可以使得損失值進行最小化,在損失值最小化的情況下求解出最優的權重系數W
    • 損失函數對W進行求導,且將一階導數等于0.
  • 回歸模型的評價指標
    • 模型是否能夠預測到真實值或者接近真實的值
      • MSE:均方誤差
    • 模型是否擬合到了足夠的信息
      • R2

實戰

  • 房地產估價數據集數據集(house.xlsx)
    • 數據集信息:
      • 房地產估值的市場歷史數據集來自臺灣新北市新店區。“房地產估價” 是一個回歸問題。
    • 屬性信息:
      • 輸入如下:
        • X1 =交易日期(例如,2013.250 = 2013年3月,2013.500 = 2013年6月,等等)
        • X2 =房屋年齡(單位:年)
        • X3 =到最近的捷運站的距離(單位:米) )
        • X4 =步行生活圈中的便利店的數量(整數)
        • X5 =地理坐標,緯度。(單位:度)
        • X6 =地理坐標,經度。(單位:度)
      • 輸出結果如下:
        • Y =單位面積的房價(10000新臺幣/ Ping,其中Ping是本地單位,1 Ping = 3.3米平方)
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
import pandas as pd
from sklearn.metrics import mean_squared_error as MSE
#讀取數據
df = pd.read_excel('./datasets/house.xlsx')
#刪除多余的列
df = df.drop(labels='No',axis=1)
#特征 標簽
feature =  df.loc[:,df.columns != 'Y house price of unit area']
target = df['Y house price of unit area']
#數據集的切分
x_train,x_test,y_train,y_test = train_test_split(feature,target,test_size=0.2,random_state=2020)

linner = LinearRegression()
linner.fit(x_train,y_train)

y_pred = linner.predict(x_test)
MSE(y_test,y_pred) #55.334060500911804
y_test.max(),y_test.min() #(63.2, 13.8)
linner.score(x_test,y_test) #0.6108181277767183

linner.score(x_train,y_train) #0.5750984249253495
#在測試集和訓練集表現都不好,因此為欠擬合

#出現問題:訓練好的模型沒有很好的擬合到原始的樣本數據中標簽和特征值之間的線性關系。
  • 使用多項式回歸處理上述案例出現的欠擬合問題

二次項

feature =  df.loc[:,df.columns != 'Y house price of unit area']
target = df['Y house price of unit area']
#給原始特征增加高次項特征
from sklearn.preprocessing import PolynomialFeatures
p = PolynomialFeatures(degree=2)
d_2_feature = p.fit_transform(feature)
#數據集的切分
x_train,x_test,y_train,y_test = train_test_split(d_2_feature,target,test_size=0.2,random_state=2020)

linner = LinearRegression().fit(x_train,y_train)
y_pred = linner.predict(x_test)
MSE(y_test,y_pred) #30.83018292349415
linner.score(x_test,y_test) #0.7831616150606915

? 三次項

feature =  df.loc[:,df.columns != 'Y house price of unit area']
target = df['Y house price of unit area']
#給原始特征增加高次項特征
from sklearn.preprocessing import PolynomialFeatures
p = PolynomialFeatures(degree=3)
d_3_feature = p.fit_transform(feature)
#數據集的切分
x_train,x_test,y_train,y_test = train_test_split(d_3_feature,target,test_size=0.2,random_state=2020)

linner = LinearRegression().fit(x_train,y_train)
y_pred = linner.predict(x_test)
MSE(y_test,y_pred) #34.37178091836353
linner.score(x_test,y_test) #0.7582524411119846

欠擬合&&過擬合

  • 案例1:
    • 現在有一組天鵝的特征數據然后對模型進行訓練,然后模型學習到的內容是有翅膀,嘴巴長的就是天鵝。然后使用模型進行預測,該模型可能會將所有符合這兩個特征的動物都預測為天鵝,則肯定會有誤差的,因為鸚鵡,禿鷲都符合有翅膀和嘴巴長的特征。
      • 原因:模型學習到的天鵝的特征太少了,導致區分標準太粗糙,不能準確的識別出天鵝。
  • 案例2:
    • 更新了樣本的特征數據了,增加了一些特征,然后訓練模型。模型這次學習到的內容是,有翅膀、嘴巴長、白色、體型像2、脖子長且有彎度的就是天鵝。然后開始使用模型進行預測,現在一組測試數據為鸚鵡,因為鸚鵡的體型小,脖子短不符合天鵝的特征,則預測結果為不是天鵝。然后又有一組特征為黑天鵝,結果因為顏色不是白色,預測成了黑天鵝。
      • 原因:現在模型學習到的特征已經基本可以區分天鵝和其他動物了。但是學習到的特征中有一項是羽毛是白色,那么就會導致將黑天鵝無法識別出來。也就是機器學習到的特征太依賴或者太符合訓練數據了。

1.欠擬合&&過擬合

  • 欠擬合:案例1中的場景就可以表示欠擬合
    • 一個假設在訓練數據上不能獲得很好的擬合,在訓練數據以外的數據集上也不能很好的擬合數據,此時認為這個假設出現了欠擬合的現象。(模型過于簡單)
  • 過擬合:案例2中的場景就可以表示過擬合
    • 一個假設在訓練數據上能夠獲得比其他假設更好的擬合,但是在訓練數據以外的數據集上卻不能很好的擬合數據,此時認為這個假設出現了過擬合現象。(模型過于復雜)
欠擬合 過擬合.png

2.欠擬合和過擬合的解決

  • 欠擬合:

    • 原因:模型學習到樣本的特征太少
    • 解決:增加樣本的特征數量(多項式回歸)
  • 過擬合:

    • 原因:原始特征過多,存在一些嘈雜特征。
    • 解決:
      • 進行特征選擇,消除關聯性大的特征(很難做)
      • 正則化之嶺回歸(掌握)
  • 模型的復雜度 --》回歸出直線or曲線 :

    回歸模型算法就是在尋找特征值和目標值之間存在的某種關系,那么這種關系越復雜則表示訓練出的模型的復雜度越高,反之越低。

    模型的復雜度由特征和目標之間的關系導致的 , 特征和目標之間的關系不僅僅是線性關系

1.欠擬合的處理:多項式回歸

為了解決欠擬合的情 經常要提高線性的次數(高次多項式)建立模型擬合曲線,次數過高會導致過擬合,次數不夠會欠擬合。

  • y = w*x + b 一次多項式函數
  • y = w1x^2 + w2x + b 二次多項式函數
  • y = w1x^3 + w2x^2 + w3*x + b 三次多項式函數

高次多項式函數的表示為曲線

線性回歸模型y=wx+b只能解決線性(回歸出的為直線)問題,多項式回歸能夠解決非線性回歸(回歸出的為曲線)問題。

多項式回歸可以看成特殊的線性模型

  • 建立二次多項式線性回歸模型進行預測

    • 根據二次多項式公式可知,需要給原始特征添加更高次的特征數據x^2.

      • y=w1x∧2+w2x+b
    • 如何給樣本添加高次的特征數據呢?

      • 使用sklearn.preprocessing.PolynomialFeatures來進行更高次特征的構造

        • 它是使用多項式的方法來進行的,如果有a,b兩個特征,那么它的2次多項式為(1,a,b,a^2,ab, b^2)

        • PolynomialFeatures有三個參

          • degree:控制多項式的度

          • interaction_only: 默認為False,如果指定為True,上面的二次項中沒有a2和b2。

          • include_bias:默認為True。如果為False的話,那么就不會有上面的1那一項

            #工具類的基本使用
            from sklearn.preprocessing import PolynomialFeatures
            p = PolynomialFeatures(degree=2)
            p.fit_transform([[3,5]])
            #array([[ 1.,  3.,  5.,  9., 15., 25.]])
            
示例
  • 下面模擬 根據蛋糕的直徑大小 預測蛋糕價格
from sklearn.linear_model import LinearRegression
import numpy as np
import matplotlib.pyplot as plt
# 樣本的訓練數據,特征和目標值
x_train = [[6], [8], [10], [14], [18]] #大小
y_train = [[7], [9], [13], [17.5], [18]]#價格
linner = LinearRegression()
linner.fit(x_train,y_train)
#畫圖
y_pred = linner.predict(x_train)
plt.scatter(x_train,y_train)
plt.plot(x_train,y_pred)
plt.xlabel('size_x')
plt.ylabel('price_y')
蛋糕1.png
  • 建立二次多項式線性回歸模型進行預測
#二次特征的構造
p = PolynomialFeatures(degree=2)
d_2_train = p.fit_transform(x_train)
linner = LinearRegression().fit(d_2_train,y_train)
#畫圖
y_pred = linner.predict(d_2_train)
plt.scatter(x_train,y_train)
plt.plot(x_train,y_pred)
plt.xlabel('size_x')
plt.ylabel('price_y')
蛋糕2.png
  • 建立3次多項式線性回歸模型進行預測
# 3次特征的構造
p = PolynomialFeatures(degree=3)
d_3_train = p.fit_transform(x_train)
linner = LinearRegression().fit(d_3_train,y_train)
#畫圖
y_pred = linner.predict(d_3_train)
plt.scatter(x_train,y_train)
plt.plot(x_train,y_pred)
plt.xlabel('size_x')
plt.ylabel('price_y')
蛋糕3.png
2.過擬合處理:正則化
- 將過擬合的曲線的凹凸幅度減少就可以將過擬合曲線趨近于擬合曲線了。那么過擬合曲線的凹凸肯定是由y=wx**2+x**3+x**4中的高次項導致的,那么正則化就可以通過不斷的嘗試發現高次項的特征然后這些特征的權重w調小到0,則高次項的特征沒有了,那么凹凸幅度就減少了,就越趨近于擬合曲線了!
- 可以使得高次項的w權重減小,趨近于0.
- LinnerRegression是沒有辦法進行正則化的,所以該算法模型容易出現過擬合,并且無法解決。
  • L2正則化:
    • 使用帶有正則化算法的回歸模型(Ridge嶺回歸)處理過擬合的問題。
3.Ridge嶺回歸:具備L2正則化的線性回歸模型
  • API:from sklearn.linear_model import Ridge

  • Ridge(alpha=1.0):

    • alpha:正則化的力度,力度越大,則表示高次項的權重w越接近于0,導致過擬合曲線的凹凸幅度越小。
      • 取值:0-1小數或者1-10整數
    • coef_:回歸系數
  • 使用嶺回歸可以通過控制正則化力度參數alpha降低高次項特征的權重

x_train = [[6], [8], [10], [14], [18]] #大小
y_train = [[7], [9], [13], [17.5], [18]]#價格
p = PolynomialFeatures(degree=3)
d_3_train = p.fit_transform(x_train)
linner = LinearRegression().fit(d_3_train,y_train)
linner.coef_
#array([[ 0.        , -1.42626096,  0.31320489, -0.01103344]])
from sklearn.linear_model import Ridge
p = PolynomialFeatures(degree=3)
d_3_train = p.fit_transform(x_train)
ridge=Ridge(alpha=0.1)
ridge.fit(d_3_train,y_train)
ridge.coef_
#array([[ 0.        , -0.54302902,  0.23512062, -0.00888958]])
  • 嶺回歸的優點:
    • 獲取的回歸系數更符合實際更可靠
    • 在病態數據(異常值多的數據)偏多的研究中有更大的存在意義
模型的保存和加載
  • from sklearn.externals import joblib

    • joblib.dump(model,'xxx.m'):保存
    • joblib.load('xxx.m'):加載
  • import pickle

    • with open('./123.pkl','wb') as fp:
      • pickle.dump(linner,fp)
    • with open('./123.pkl','rb') as fp:
      • linner = pickle.load(fp)
import pickle
with open('./ridge.pkl','wb') as fp:
    pickle.dump(ridge,fp)
ridge=None
with open('./ridge.pkl','rb') as fp:
    ridge=pickle.load(fp)
print(ridge)   
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。