4-機器學習-多項式回歸+過擬合&欠擬合的處理、模型保存與加載


總結

  • 欠擬合:(對訓練集的數據和測試集的數據擬合的都不是很好)
    • 原因:模型學習到樣本的特征太少
    • 解決:增加樣本的特征數量(多項式回歸)
    • 多項式回歸:from sklearn.preprocessing import PolynomialFeatures
      • 在原有特征的基礎上增加高次方特征
  • 過擬合:(對訓練集的數據高度擬合,對測試集的數據擬合的很離譜)
    • 原因:原始特征過多,存在一些嘈雜特征。
    • 解決:
      • 1.進行特征選擇,消除關聯性大的特征
      • 2.正則化之嶺回歸:from sklearn.linear_model import Ridge
        • 將對模型影響較大的特征(高次方)的權重系數變小,將模型彎曲程度大的地方捋直一定,降低關聯性大的特征對預測模型的影響

模型的保存和加載

  • 方式一 (推薦):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)

欠擬合&&過擬合問題引入

問題

  訓練好的模型在訓練集上表現的預測效果很好,但是在測試集上卻有很大的問題和誤差,why?

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

欠擬合&&過擬合

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

    image.png

欠擬合和過擬合問題的解決

  • 欠擬合:
    • 原因:模型學習到樣本的特征太少
    • 解決:增加樣本的特征數量(多項式回歸)
  • 過擬合:
    • 原因:原始特征過多,存在一些嘈雜特征。
    • 解決:
      • 進行特征選擇,消除關聯性大的特征(很難做)
      • 正則化之嶺回歸(掌握)
  • 模型的復雜度--》回歸出直線or曲線:
    • 我們的回歸模型最終回歸出的一定是直線嗎(y=wx+b)?有沒有可能是曲線(非線性)呢(y=wx**2+b)?
      • 我們都知道回歸模型算法就是在尋找特征值和目標值之間存在的某種關系,那么這種關系越復雜則表示訓練出的模型的復雜度越高,反之越低。
      • 模型的復雜度是由特征和目標之間的關系導致的!特征和目標之間的關系不僅僅是線性關系!

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

  • 為了解決欠擬合的情 經常要提高線性的次數(高次多項式)建立模型擬合曲線,次數過高會導致過擬合,次數不夠會欠擬合。
    • y = w*x + b 一次多項式函數
    • y = w1x^2 + w2x + b 二次多項式函數
    • y = w1x^3 + w2x^2 + w3*x + b 三次多項式函數
    • 。。。
      • 高次多項式函數的表示為曲線
  • 相對於線性回歸模型y=wx+b只能解決線性(回歸出的為直線)問題,多項式回歸能夠解決非線性回歸(回歸出的為曲線)問題。
  • 拿最簡單的線性模型來說,其數學表達式可以表示為:y=wx+b,它表示的是一條直線,而多項式回歸則可以表示成:y=w1x∧2+w2x+b,它表示的是二次曲線,

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

    ,即把x∧2看成一個特征,把x看成另一個特征,這樣就可以表示成y=w1z+w2x+b,其中z=x∧2,這樣多項式回歸實際上就變成線性回歸了。
  • 其中的y=w1x∧2+w2x+b就是所謂的二次多項式:aX∧2+bX+c(a≠0).
  • 當然還可以將y=wx+b轉為更高次的多項式。是否需要轉成更高次的多項式取決於我們想要擬合樣本的程度了,更高次的多項式可以更好的擬合我們的樣本數據,但是也不是一定的,很可能會造成過擬合。

示例

  • 下面模擬 根據蛋糕的直徑大小 預測蛋糕價格
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]]#價格

# 訓練模型
linear = LinearRegression()
linear.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')
 

給原始特征增加高次項特征,可以是模型直線變彎曲,從而更加擬合數據

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

  • 根據二次多項式公式可知,需要給原始特征添加更高次的特征數據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,上面的二次項中沒有a^2和b^2。
        • include_bias:默認為True。如果為False的話,那么就不會有上面的1那一項

工具類的基本使用(在原本數據的特征上增加多次方特征)

from sklearn.preprocessing import PolynomialFeatures

# 參數degree控制增加特征的次數
# 參數interaction_only默認為False是有二次項,如果變成True就會去掉二次項
# 參數include_bias默認為True,如果是False就是不要增加出來的1那一項
p = PolynomialFeatures(degree=2,interaction_only=True, include_bias=True)
p.fit_transform([[3,5]]) # 需要傳入二維的特征 array([[ 1.,  3.,  5., 15.]])
p = PolynomialFeatures(degree=2,interaction_only=False, include_bias=True)
p.fit_transform([[3,5]]) # 需要傳入二維的特征 array([[ 1.,  3.,  5.,  9., 15., 25.]])
p = PolynomialFeatures(degree=2,interaction_only=False, include_bias=False)
p.fit_transform([[3,5]]) # 需要傳入二維的特征 array([[ 3.,  5.,  9., 15., 25.]])

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

from sklearn.linear_model import LinearRegression
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures

# 樣本的訓練數據,特征和目標值
x_train = [[6], [8], [10], [14], [18]] #大小
y_train = [[7], [9], [13], [17.5], [18]]#價格

# 在原有特征上增加2次方特征
p = PolynomialFeatures(degree=2)
d_2_train = p.fit_transform(x_train)

array([[  1.,   6.,  36.],
       [  1.,   8.,  64.],
       [  1.,  10., 100.],
       [  1.,  14., 196.],
       [  1.,  18., 324.]])
# 訓練模型
linear = LinearRegression().fit(d_2_train,y_train)

y_pred = linear.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次方特征后,模型看起來更加擬合

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

# 在原有特征上增加3次方特征
p = PolynomialFeatures(degree=3)
d_3_train = p.fit_transform(x_train)

array([[1.000e+00, 6.000e+00, 3.600e+01, 2.160e+02],
       [1.000e+00, 8.000e+00, 6.400e+01, 5.120e+02],
       [1.000e+00, 1.000e+01, 1.000e+02, 1.000e+03],
       [1.000e+00, 1.400e+01, 1.960e+02, 2.744e+03],
       [1.000e+00, 1.800e+01, 3.240e+02, 5.832e+03]])

linear = LinearRegression().fit(d_3_train,y_train)

y_pred = linear.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次方特征后,模型看起來有點過擬合

對上篇文章的實戰使用多次項回歸

 

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,r2_score
from sklearn.preprocessing import PolynomialFeatures

# 1.導入數據
df = pd.read_excel('./house.xlsx')
df.head(1)

# 2.提取樣本數據
feature = df.loc[:,df.columns != 'Y house price of unit area']
target = df[ 'Y house price of unit area']

# 3.給原始特征增加高次特征
p = PolynomialFeatures(degree=2)
d_2_feature = p.fit_transform(feature)

d_2_feature.shape  # (414, 28)
target.shape  # (414,)

# 4.切分樣本數據
x_train,x_test,y_train,y_test = train_test_split(d_2_feature,target,test_size=0.2, random_state=2020)


# 5. 訓練模型
linear = LinearRegression()
linear.fit(x_train,y_train)

# 6. 評估模型
# 均方誤差MSE
y_pred = linear.predict(x_test)
MSE(y_test, y_pred)  # 30.83018292349415
y_test.max(),y_test.min()  # (63.2, 13.8)

# R^2
linear.score(x_test,y_test)  # 0.7831616150606915

# 7.繪制擬合圖
import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(range(len(y_test)),sorted(y_test), c='black', label='y_true')
plt.plot(range(len(y_pred)),sorted(y_pred),c='red', label='y_predict')
plt.legend()
plt.show()

 過擬合處理:L2正則化Ridge嶺回歸模型

  • 將過擬合的曲線的凹凸幅度減少就可以將過擬合曲線趨近於擬合曲線了。那么過擬合曲線的凹凸肯定是由y=wx**2+x**3+x**4中的高次項導致的
  • 那么L2正則化就是通過高次項的特征的權重w調小到趨近於0,則高次項的特征就幾乎沒有了,那么凹凸幅度就會減少,就越趨近於擬合曲線了
  • LinnerRegression是沒有辦法進行正則化的,所以該算法模型容易出現過擬合,並且無法解決。
  • L2正則化:
    • 使用帶有正則化算法的回歸模型(Ridge嶺回歸)處理過擬合的問題。

Ridge嶺回歸模型:具備L2正則化的線性回歸模型

  • API:from sklearn.linear_model import Ridge
  • Ridge(alpha=1.0):
    • alpha:正則化的力度,力度越大,則表示高次項的權重w越接近於0,導致過擬合曲線的凹凸幅度越小。
      • 取值:0-1小數或者1-10整數
    • coef_:回歸系數

使用嶺回歸可以通過控制正則化力度參數alpha降低高次項特征的權重

from sklearn.linear_model import Ridge
from sklearn.linear_model import LinearRegression
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures

# 樣本的訓練數據,特征和目標值
x_train = [[6], [8], [10], [14], [18]] #大小
y_train = [[7], [9], [13], [17.5], [18]]#價格

# 在原有特征上增加3次方特征
p = PolynomialFeatures(degree=3)
d_3_train = p.fit_transform(x_train)
linear = LinearRegression().fit(d_3_train,y_train)
# 原本線性回歸權重系數
linear.coef_

array([[ 0.        , -1.42626096,  0.31320489, -0.01103344]])

# 使用L2正則化力度調整權重系數
# 參數alpha正則化力度
ridge = Ridge(alpha=0.5)
ridge.fit(d_3_train,y_train)
ridge.coef_
# 調整后權重系數,明顯將高權重的變低了
array([[ 0.        , -0.14579637,  0.19991159, -0.00792083]])

嶺回歸的優點:

  • 獲取的回歸系數更符合實際更可靠
  • 在病態數據(異常值多的數據)偏多的研究中有更大的存在意義

模型的保存和加載

方式一 (推薦使用方式一,更加便捷)

  • 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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM