【Python機器學習及實踐】進階篇:模型實用技巧(模型正則化)

Python機器學習及實踐——進階篇:模型實用技巧(模型正則化)

任何機器學習模型在訓練集上的性能表現,都不能作爲其對未知測試數據預測能力的評估。

1. 欠擬合與過擬合

所謂擬合,是指機器學習模型在訓練的過程中,通過更新參數,使得模型不斷契合可觀測數據(訓練集)的過程。

使用線性迴歸模型在披薩訓練樣本上進行擬合:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@File  : Fitting.py
@Author: Xinzhe.Pang
@Date  : 2019/7/23 23:50
@Desc  : 
"""
# 輸入訓練樣本的特徵以及目標值,分別存儲在變量X_train與y_train之中
X_train = [[6], [8], [10], [14], [18]]
y_train = [[7], [9], [13], [17.5], [18]]

# 導入LinearRegression
from sklearn.linear_model import LinearRegression

lr = LinearRegression()
lr.fit(X_train, y_train)

import numpy as np

# 在x軸上從0至25均勻採樣100個數據點
xx = np.linspace(0, 26, 100)
xx = xx.reshape(xx.shape[0], 1)

# 以上述100個數據點作爲基準,預測迴歸直線
yy = lr.predict(xx)

# 對迴歸預測到的直線作圖
import matplotlib.pylab as plt

plt.scatter(X_train, y_train)
plt1, = plt.plot(xx, yy, label="Degree = 1")

plt.axis([0, 25, 0, 25])
plt.xlabel('Diameter of Pizza')
plt.ylabel('Price of Pizza')
plt.legend(handles=[plt1])
plt.show()

# 輸出線性迴歸模型在訓練樣本上的R-squared值
print('The R-squared value of Linear Regressor performing on the training data is', lr.score(X_train, y_train))

The R-squared value of Linear Regressor performing on the training data is 0.910001596424

使用2次多項式迴歸模型在披薩訓練樣本上進行擬合:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@File  : Fitting2.py
@Author: Xinzhe.Pang
@Date  : 2019/7/24 20:29
@Desc  : 
"""
import numpy as np
# 導入多項式特徵產生器
from sklearn.preprocessing import PolynomialFeatures
# 導入LinearRegression
from sklearn.linear_model import LinearRegression
# 分別對訓練數據點、線性迴歸直線、2次多項式迴歸曲線進行作圖
import matplotlib.pyplot as plt

# 輸入訓練樣本的特徵以及目標值,分別存儲在變量X_train與y_train之中
X_train = [[6], [8], [10], [14], [18]]
y_train = [[7], [9], [13], [17.5], [18]]

lr = LinearRegression()
lr.fit(X_train, y_train)

# 在x軸上從0至25均勻採樣100個數據點
xx = np.linspace(0, 26, 100)
xx = xx.reshape(xx.shape[0], 1)
# 以上述100個數據點作爲基準,預測迴歸直線
yy = lr.predict(xx)

# 使用PolynominalFeatures(degree = 2)映射出2次多項式特徵,存儲在變量X_train_poly2中
poly2 = PolynomialFeatures(degree=2)
X_train_poly2 = poly2.fit_transform(X_train)

# 以線性迴歸器爲基礎,初始化迴歸模型。儘管特徵的維度有提升,但是模型基礎仍然是線性模型
lr_poly2 = LinearRegression()

# 對2次多項式迴歸模型進行訓練
lr_poly2.fit(X_train_poly2, y_train)

# 從新映射繪圖用x軸採樣數據
xx_poly2 = poly2.transform(xx)
# 使用2次多項式迴歸模型對應x軸採樣數據進行迴歸預測
yy_poly2 = lr_poly2.predict(xx_poly2)

plt.scatter(X_train, y_train)
plt1, = plt.plot(xx, yy, label='Degree = 1')
plt2, = plt.plot(xx, yy_poly2, label='Degree=2')
plt.axis([0, 25, 0, 25])
plt.xlabel('Diameter of Pizza')
plt.ylabel('Price of Pizza')
plt.legend(handles=[plt1, plt2])
plt.show()

# 輸出2次多項式迴歸模型在訓練樣本上的R-squared值
print('The R-squared value of Polynominal Regressor (Degree = 2) performing on the training data is',
      lr_poly2.score(X_train_poly2, y_train))

 

The R-squared value of Polynominal Regressor (Degree = 2) performing on the training data is 0.98164216396

升高了特徵維度之後,2次多項式迴歸模型在訓練樣本上的性能表現更加突出,R-squared值從0.910上升到0.982.

使用4次多項式迴歸模型在披薩訓練樣本上進行擬合:

# 導入多項式特徵生成器
from sklearn.preprocessing import PolynomialFeatures

# 初始化4次多項式特徵生存器
poly4 = PolynomialFeatures(degree=4)
X_train_n_poly4 = poly4.fit_transform(X_train)

# 使用默認配置初始化4次多項式迴歸器
lr_poly4 = LinearRegression()
lr_poly4.fit(X_train_n_poly4, y_train)

# 從新映射繪圖用x軸採樣數據
xx_poly4 = poly4.transform(xx)
# 使用4次多項式迴歸模型對x軸採樣數據進行迴歸預測
yy_poly4 = lr_poly4.predict(xx_poly4)

# 分別對訓練數據點、線性迴歸直線、2次多項式以及4次多項式迴歸曲線進行作圖
plt.scatter(X_train, y_train)
plt1, = plt.plot(xx, yy, label="Degree=1")
plt2, = plt.plot(xx, yy_poly2, label="Degree=2")

plt4, = plt.plot(xx, yy_poly4, label="Degree=4")
plt.axis([0, 25, 0, 25])
plt.xlabel('Diameter of Pizza')
plt.ylabel('Price of Pizza')

plt.legend(handles=[plt1, plt2, plt4])
plt.show()
print('The R-squared value of Polynominal Regressor(Degree=4) performing on the training data is',
      lr_poly4.score(X_train_n_poly4, y_train))

 

The R-squared value of Polynominal Regressor(Degree=4) performing on the training data is 1.0

評估3種迴歸模型在測試數據集上的性能表現:

# 準備測試數據
X_test = [[6], [8], [11], [16]]
y_test = [[8], [12], [15], [18]]

# 使用測試數據對線性迴歸模型的性能進行評估
print(lr.score(X_test, y_test))
# 使用測試數據對2次多項式迴歸模型的性能進行評估
X_test_poly2 = poly2.transform(X_test)
print(lr_poly2.score(X_test_poly2, y_test))
# 使用測試數據對4次多項式迴歸模型的性能進行評估
X_test_poly4 = poly4.transform(X_test)
print(lr_poly4.score(X_test_poly4, y_test))

0.809726797708
0.867544365635
0.809588079578

當模型複雜度較低(Degree=1)時,模型不僅沒有對訓練集上的數據有良好的擬合狀態,而且在測試集上也是表現平平,這種情況叫做欠擬合(Underfitting);當模型複雜度較高(Degree=4)時,模型幾乎完全擬合了所有的訓練數據,但是幾乎喪失了對未知數據的預測能力,這種情況叫做過擬合(Over fitting)。這兩種情況都是缺乏模型泛化力的表現。

爲了更好的模型泛化力,要求在增加模型複雜度、提高在可觀測數據上的性能表現的同時,又需要兼顧模型的泛化力,防止發生過擬合的情況。通常採用兩種模型正則化的方法。分別是L1範數正則化和L2範數正則化。

2. L1範數正則化

正則化(Regularization)的目的在於提高模型在未知測試數據上的泛化力,避免參數過擬合。

正則化的常見方法都是在原模型優化目標的基礎上,增加對參數的懲罰(Penalty)項。在原優化目標的基礎上,增加了參數向量的L1範數。這樣在新目標優化的過程中同時需要考量L1懲罰項的影響。爲了使目標最小化,這種正則化方法的結果會讓參數向量中許多元素趨向於0,使得大部分特徵失去對優化目標的貢獻。這種讓有效特徵變得稀疏的L1正則化模型,通常被稱爲Lasso

Lasso模型在4次多項式特徵上的擬合表現

# 從sklearn.linear_mode中導入Lasso
from sklearn.linear_model import Lasso

# 使用默認參數初始化Lasso
lasso_poly4 = Lasso()
# 使用Lasso對4次多項式特徵進行擬合
lasso_poly4.fit(X_train_n_poly4, y_train)
# 對Lasso模型在測試樣本上的迴歸性能進行評估
print(lasso_poly4.score(X_test_poly4, y_test))

# 輸出Lasso模型的參數列表
print(lasso_poly4.coef_)

# 4次多項式迴歸模型過擬合之後的性能
print(lr_poly4.score(X_test_poly4, y_test))
# 4次多項式迴歸模型的參數列表
print(lr_poly4.coef_)

0.83889268736
[  0.00000000e+00   0.00000000e+00   1.17900534e-01   5.42646770e-05
  -2.23027128e-04]
0.809588079578
[[  0.00000000e+00  -2.51739583e+01   3.68906250e+00  -2.12760417e-01
    4.29687500e-03]]

通過對代碼一系列輸出的觀察,驗證了我們所介紹的Lasso模型的特點:

  1. 相比於普通4次多項式迴歸模型在測試集上的表現,默認配置的Lasso模型性能提高了大約3%;
  2. 相較之下,Lasso模型擬合後的參數列表中,4次與3次特徵的參數均爲0.0,使得特徵更加稀疏。

3. L2範數正則化

L2範數正則化則在原優化目標的基礎上,增加了參數向量的L2範數的懲罰項。爲了使新優化目標最小化,這種正則化方法的結果會讓參數向量中的大部分元素都變得很小,壓制了參數之間的差異性。這種正則化模型通常被稱爲Ridge

Ridge模型在4次多項式特徵上的擬合表現:

# 4次多項式迴歸模型的參數列表
print(lr_poly4.coef_)
# 輸出上述這些參數的平方和,驗證參數之間的巨大差異
print(np.sum(lr_poly4.coef_ ** 2))

# 從sklearn.linear_model導入Ridge
from sklearn.linear_model import Ridge

# 使用默認參數初始化Riedge
ridge_poly4 = Ridge()

# 使用Ridge模型對4次多項式特徵進行擬合
ridge_poly4.fit(X_train_n_poly4, y_train)

# 輸出Ridge模型在測試樣本上的迴歸性能
print(ridge_poly4.score(X_test_poly4, y_test))

# 輸出Ridge模型的參數列表,觀察參數差異
print(ridge_poly4.coef_)

# 計算Ridge模型擬合後參數的平方和
print(np.sum(ridge_poly4.coef_ ** 2))

[[  0.00000000e+00  -2.51739583e+01   3.68906250e+00  -2.12760417e-01
    4.29687500e-03]]
647.382645692

0.837420175937
[[ 0.         -0.00492536  0.12439632 -0.00046471 -0.00021205]]
0.0154989652035

通過對上述輸出的觀察,可以驗證Ridge模型的特點:

  1. 相比於普通4次多項式迴歸模型在測試集上的表現,默認配置的Ridge模型性能提高了近3%;
  2. 與普通4次多項式迴歸模型不同的是,Ridge模型擬合後的參數之間差異非常小。

需要注意的是在懲罰項中都有一個因子λ進行調節。儘管λ不屬於需要擬合的參數,卻在模型優化中扮演非常重要的角色。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章