理論+實踐,一文帶你讀懂線性回歸的評價指標

  • 2019 年 11 月 24 日
  • 筆記

關於作者:餅乾同學,某人工智能公司交付開發工程師/建模科學家。專註於AI工程化及場景落地,希望和大家分享成長中的專業知識與思考感悟。

0x00 前言:

本篇內容是線性回歸系列的第三篇。

在《模型之母:簡單線性回歸&最小二乘法》、《模型之母:簡單線性回歸&最小二乘法》中我們學習了簡單線性回歸、最小二乘法,並完成了代碼的實現。在結尾,我們拋出了一個問題:在之前的kNN算法(分類問題)中,使用分類準確度來評價算法的好壞,那麼回歸問題中如何評價好壞呢?

本篇內容就是關於回歸模型的評價,首先介紹線性回歸模型的三個常用評價方法,然後通過波士頓房產預測的實際例子,對評價方法進行代碼實現。最後我們會隆重引出最好的衡量線性回歸法的指標:R Square

0x01 線性回歸算法的衡量標準

簡單線性回歸的目標是:

已知訓練數據樣本、 ,找到和的值,使 儘可能小

實際上是找到訓練數據集中 最小。

衡量標準是看在測試數據集中y的真實值與預測值之間的差距。

因此我們可以使用下面公式作為衡量標準:

但是這裡有一個問題,這個衡量標準是和m相關的。在具體衡量時,測試數據集不同將會導致誤差的累積量不同。因此很快的

首先我們從「使損失函數盡量小」這個思路出發:

對於訓練數據集合來說,使 儘可能小

在得到a和b之後將 代入a、b中。可以使用 來作為衡量回歸算法好壞的標準。

1.1 均方誤差MSE

測試集中的數據量m不同,因為有累加操作,所以隨着數據的增加 ,誤差會逐漸積累;因此衡量標準和 m 相關。為了抵消掉數據量的形象,可以除去數據量,抵消誤差。通過這種處理方式得到的結果叫做 均方誤差MSE(Mean Squared Error)

1.2 均方根誤差RMSE

但是使用均方誤差MSE收到量綱的影響。例如在衡量房產時,y的單位是(萬元),那麼衡量標準得到的結果是(萬元平方)。為了解決量綱的問題,可以將其開方(為了解決方差的量綱問題,將其開方得到平方差)得到均方根誤差RMSE(Root Mean Squarde Error)

1.3 平均絕對誤差MAE

對於線性回歸算法還有另外一種非常樸素評測標準。要求真實值 與 預測結果 之間的距離最小,可以直接相減做絕對值,加m次再除以m,即可求出平均距離,被稱作平均絕對誤差MAE(Mean Absolute Error)

在之前確定損失函數時,我們提過,絕對值函數不是處處可導的,因此沒有使用絕對值。但是在評價模型時不影響。因此模型的評價方法可以和損失函數不同。

0x02 評價標準的代碼實現

2.1 數據探索

import numpy as npimport matplotlib.pyplot as pltfrom sklearn import datasets  # 查看數據集描述boston = datasets.load_boston()print(boston.DESCR)

(輸出略)

因為是測試簡單回歸算法,因此我們選擇其中的一個特徵進行建模。選擇:

  • RM average number of rooms per dwelling 每個住宅的平均房間數

下面我們進行簡單的數據探索:

# 查看數據集的特徵列表boston.feature_names輸出:array(['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD',       'TAX', 'PTRATIO', 'B', 'LSTAT'], dtype='<U7')       # 取出數據中的第六例的所有行(房間數量)x = boston.data[:,5]x.shape輸出:(506,)  # 取出樣本標籤y = boston.targety.shape輸出:(506,)  plt.scatter(x,y)plt.show()

在圖中我們可以看到 50W 美元的檔分佈着一些點。這些點可能是超出了限定範圍(比如在問卷調查中,價格的最高檔位是「50萬及以上」,那麼就全都划到50W上了,因此在本例中,可以將這部分數據去除)

np.max(y)# 這裡有一個騷操作,用比較運算符返回一個布爾值的向量,將其作為索引,直接在矩陣里對每個元素進行過濾。x = x[y < 50.0]y = y[y < 50.0]plt.scatter(x,y)plt.show()

2.2 簡單線性回歸預測

from myAlgorithm.model_selection import train_test_split  x_train, x_test, y_train, y_test = train_test_split(x, y, seed=666)print(x_train.shape)    # (392,)print(y_train.shape)    #(392,)print(x_test.shape)     #(98,)print(y_test.shape)     #(98,)  from myAlgorithm.SimpleLinearRegression import SimpleLinearRegression  reg = SimpleLinearRegression()reg.fit(x_train,y_train)print(reg.a_)   # 7.8608543562689555print(reg.b_)   # -27.459342806705543  plt.scatter(x_train,y_train)plt.plot(x_train, reg.predict(x_train),color='r')plt.show()
y_predict = reg.predict(x_test)print(y_predict)

(輸出略)

2.3 MSE 均方誤差

mse_test = np.sum((y_predict - y_test) ** 2) / len(y_test)mse_test

24.156602134387438

2.4 RMSE 均方根誤差

from math import sqrt  rmse_test = sqrt(mse_test)rmse_test

4.914936635846635

RMSE消除了量綱的差異,輸出的結果是4.9,與y的量綱相同。解釋為在RMSE指標下,我們預測的房產數據平均誤差在4.9萬美元左右。

2.5 MAE 平均絕對誤差

mae_test = np.sum(np.absolute(y_predict - y_test)) / len(y_test)mae_test

3.5430974409463873

在MAE指標下,我們預測的房產數據平均誤差在3.54萬美元左右。我們看到MAE指標得到的誤差要比RMSE指標得到的誤差小。說明不同的評價指標的結果不同

從數學角度來分析,RMSE和MAE的量綱相同,但RMSE的結果較大,這是因為RMSE是將錯誤值平方,平方操作會放大樣本中預測結果和真實結果較大的差距。MAE沒有放大。而我們就是要解決目標函數最大差距,因為選RMSE更好一點

0x03 封裝及調用

3.1 在工程文件中封裝

在工程文件的metrics.py中添加以上評價指標:

mport numpy as npfrom math import sqrt  def accuracy_score(y_true, y_predict):    """計算y_true和y_predict之間的準確率"""    assert y_true.shape[0] != y_predict.shape[0],         "the size of y_true must be equal to the size of y_predict"    return sum(y_true == y_predict) / len(y_true)  def mean_squared_error(y_true, y_predict):    """計算y_true和y_predict之間的MSE"""    assert len(y_true) == len(y_predict),         "the size of y_true must be equal to the size of y_predict"    return np.sum((y_true - y_predict) ** 2) / len(y_true)  def root_mean_squared_error(y_true, y_predict):    """計算y_true和y_predict之間的RMSE"""    return sqrt(mean_squared_error(y_true, y_predict))  def mean_absolute_error(y_true, y_predict):    """計算y_true和y_predict之間的MAE"""    assert len(y_true) == len(y_predict),         "the size of y_true must be equal to the size of y_predict"      return np.sum(np.absolute(y_predict - y_true)) / len(y_predict)

3.2 調用

我們可以在jupyter notebook進行調用:

from myAlgorithm.metrics import mean_squared_errorfrom myAlgorithm.metrics import root_mean_squared_errorfrom myAlgorithm.metrics import mean_absolute_error  mean_squared_error(y_test, y_predict)# 輸出:24.156602134387438  root_mean_squared_error(y_test, y_predict)# 輸出:4.914936635846635  mean_absolute_error(y_test, y_predict)# 輸出:3.5430974409463873

3.3 sklearn中的MSE和MAE

sklearn中不存在RMSE,我們可以手動對MSE開方:

from sklearn.metrics import mean_squared_errorfrom sklearn.metrics import mean_absolute_error  mean_squared_error(y_test, y_predict)# 輸出:24.156602134387438  mean_absolute_error(y_test, y_predict)# 輸出:3.5430974409463873

0x04 更好用的 R Square

4.2 R Square介紹以及為什麼好

分類準確率,就是在01之間取值。但RMSE和MAE沒有這樣的性質,得到的誤差。因此RMSE和MAE就有這樣的局限性,比如我們在預測波士頓方差,RMSE值是4.9(萬美元) 我們再去預測身高,可能得到的誤差是10(厘米),我們不能說後者比前者更準確,因為二者的量綱根本就不是一類東西。

其實這種局限性,可以被解決。用一個新的指標R Squared。

R方這個指標為什麼好呢?

  • 對於分子來說,預測值和真實值之差的平方和,即使用我們的模型預測產生的錯誤。
  • 對於分母來說,是均值和真實值之差的平方和,即認為「預測值=樣本均值」這個模型(Baseline Model)所產生的錯誤。
  • 我們使用Baseline模型產生的錯誤較多,我們使用自己的模型錯誤較少。因此用1減去較少的錯誤除以較多的錯誤,實際上是衡量了我們的模型擬合住數據的地方,即沒有產生錯誤的相應指標

我們根據上述分析,可以得到如下結論:

  • R^2 <= 1
  • R2越大也好,越大說明減數的分子小,錯誤率低;當我們預測模型不犯任何錯誤時,R2最大值1
  • 當我們的模型等於基準模型時,R^2 = 0
  • 如果R^2 < 0,說明我們學習到的模型還不如基準模型。此時,很有可能我們的數據不存在任何線性關係。

4.2 R Square實現

下面我們從具體實現的層面再來分析一下R方:

如果分子分母同時除以m,我們會發現,分子就是之前介紹過的均方誤差,分母實際上是y這組數據對應的方差:

下面我們具體編程實踐一下:

1 - mean_squared_error(y_test, y_predict) / np.var(y_test)

輸出:0.61293168039373225

下面我們在工程文件metrics.py中添加自己實現的r2_score方法:

def score(self, x_test, y_test):    """根據測試數據x_test、y_test計算簡單線性回歸準確度(R方)"""    y_predict = self.predict(x_test)    return r2_score(y_test, y_predict)

然後我們再來調用它:

from myAlgorithm.metrics import r2_scorer2_score(y_test, y_predict)

其實這跟掉sklearn中的方法相同

from sklearn.metrics import r2_scorer2_score(y_test, y_predict)

0xFF 總結

線性回歸的評價指標與分類的評價指標有很大的不同,本篇介紹了均方誤差MSE(預測值與真實值之差的平方和,再除以樣本量)、均方根誤差RMSE(為了消除量綱,將MSE開方)、平均絕對誤差MAE(預測值與真實值之差的絕對值,再除以樣本量)、以及非常重要的、效果非常好的R方(因此用1減去較少的錯誤除以較多的錯誤,實際上是衡量了我們的模型擬合住數據的地方,即沒有產生錯誤的相應指標)。

在實際應用過程中,我們需要這些評價指標,來判別模型的好壞。

在下一篇,我們將會拋棄簡單線性回歸中每個樣本只能有一個特徵的限制,考慮更一般的、多個特徵的多元線性回歸。