如何评估?
简单线性回归 的 目标是找到 a 和 b 使得 $ \sum^m_{i=1} (y_{train}^{(i)} - ax_{train}^{(i)} - b )^2 $ 尽可能小。
这个式子也可以表示为 $ \sum^m_{i=1} ( y_{train}^{(i)} - \hat{y}_{train}^{(i)} )^2 $
训练完成后得到 $ \hat{y}{train}^{(i)} = ax{test}^{(i)} + b $
MSE
所以衡量回归问题的标准可以是(m 是测试数据集的个数):
$ \frac{1}{m} \sum^m_{i=1} ( y_{test}^{(i)} - \hat{y}_{test}^{(i)} )^2 $
这个标准也叫 均方误差MSE(Mean Squared Error);
RMSE
MSE 的问题是,得到的数值是 量纲的平方,所以需要开根号,得到的公式称为 均方根误差 RMSE(Root Mean Squared Error )
$ \sqrt{ \frac{1}{m} \sum^m_{i=1} ( y_{test}^{(i)} - \hat{y}{test}^{(i)} )^2 } = \sqrt{ MSE{test} } $
MSE 和 RMSE 区别不大,主要看对量纲的敏感性。
线性回归还有另一个评测方法:平均绝对误差 MAE (Mean Absolute Error)
$ \frac{1}{m} \sum^m_{i=1} | y_{test}^{(i)} - \hat{y}_{test}^{(i)} | $
绝对值不是处处可导,所以没有用在损失函数中;但绝对值完全可以用来评价。
评价一个算法的标准 和 训练模型使用的最优化函数的标准 是可以完全不一致的。
RMSE & MAE
RMSE 得到的值一般比 MAE 大;
RMSE 有平方操作,会放大样本中预测结果和真实结果 较大误差 的趋势。MAE 没有这个趋势。
所以一般来讲,让 RMSE 尽量小(比 MAE )意义更大,因为这意味着 样本的错误中,最大的错误值 相应的比较小。
R Square
分类问题的评估 比较简单,主要看 分类的准确度,在 0--1 之间进行取值。
但 RMSE 和 MAE 没有这种性质,R Square (也可读作 R方)这个方法解决了这个问题。
R 方比较重要,使用比较广泛。
公式:
$ R^2 = 1 - \frac{ SS_{residual} }{ SS_{total} } = 1 - \frac{ \sum_i ( \hat{y}^{(i)} - y^{(i)} )^2 }{ \sum_i \overline{y}^{(i)} - y^{(i)} )^2 } $
$ = 1 - \frac{ (\sum_i ( \hat{y}^{(i)} - y^{(i)} )^2 )/m }{ (\sum_i \overline{y}^{(i)} - y^{(i)} )^2)/m } = 1 - \frac{MSE( \hat{y}, y )}{ Var(y) } $
residual:Residual Sum of Squares
total:Total Sum of Squares
分子 $ \sum_i ( \hat{y}^{(i)} - y^{(i)} )^2 $ 代表使用我们的模型来预测,产生的错误;
分母 $ \sum_i \overline{y}^{(i)} - y^{(i)} )^2 $ ,也可以看做一个模型,代表使用 $ y = \overline{y} $ 预测产生的错误。这是个很朴素的预测结果,在统计学领域称为 基准模型(Baseline Model);这个模型预测的错误率是比较高的。
使用 1 来减去这个分数,相当于 我们的模型没有产生错误的比率。
R 方特性
- R^2<= 1
- R^2 越大越好。当我们的预测模型不犯任何错误时,R^2 取得最大值1;
- 当我们的模型等于基准模型时,R^2为0,是最差的情况;
- 如果R^2< 0,说明我们学习到的模型还不如基准模型。此时,很有可能我们的数据不存在任何线性关系。
示例:预测boston 房价数据并评估
读取、查看数据特征
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
boston = datasets.load_boston()
boston.keys()
# dict_keys(['data', 'target', 'feature_names', 'DESCR', 'filename'])
boston.DESCR
# 有 13 个特征
boston.feature_names
# array(['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT'], dtype='<U7')
boston.data
'''
array([[6.3200e-03, 1.8000e+01, 2.3100e+00, ..., 1.5300e+01, 3.9690e+02,
4.9800e+00],
...,
[6.0760e-02, 0.0000e+00, 1.1930e+01, ..., 2.1000e+01, 3.9690e+02, 5.6400e+00],
[4.7410e-02, 0.0000e+00, 1.1930e+01, ..., 2.1000e+01, 3.9690e+02, 7.8800e+00]])
'''
x = boston.data[:,5] # 取第五列数据,使用房间数量这个特征
x.shape # (506,)
y = boston.target
y # array([24. , 21.6, 34.7, 33.4, 36.2, 28.7, 22.9, 27.1, 16.5, 18.9, 15. , 20.6, 21.2, 19.1, 20.6, 15.2, 7. , 8.1,...20.6, 23.9, 22. , 11.9])
先做一个简单线性回归
## 看看数据分布
plt.scatter(x, y)
# 最上方分布的点,贴近最大值,可能是异常点,采集的时候计量的限制值。
去除异常值
# 确认有最大值
np.max(y) # 50.0
# 删除最大值的点
x = x[y < 50.0]
y = y[y < 50.0]
plt.scatter(x, y)
# 这里就没有上述的边缘点了
训练数据
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split( x, y, test_size=0.2, random_state=42)
x_train.shape, x_test.shape # ((392,), (98,))
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
x_train = x_train.reshape(-1, 1)
y_train = y_train.reshape(-1, 1)
lr.fit(x_train, y_train)
# LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None, normalize=False)
# 斜率,权重列表
lr.coef_ # array([[8.24882251]])
# 截距 bias值
lr.intercept_ # array([-29.6721626])
plt.scatter(x_train, y_train)
plt.plot(x_train, lr.predict(x_train), color='r')
预测并评估
# 预测
y_predict = lr.predict(x_test.reshape(-1,1))
y_test = y_test.reshape(-1,1)
## 计算 MSE
mse_test = np.sum((y_predict - y_test)**2) / len(y_test)
mse_test # 31.763084786207326
## RMSE
rmse_test = np.sqrt(mse_test)
rmse_test # 5.6358748022119265
# MAE
mae_test = np.sum( np.abs(y_predict - y_test)) / len(y_test)
mae_test # 3.9395943900511363
# R Square
rsquare = 1 - mean_squared_error(y_test, y_predict)/ np.var(y_test)
rsquare # 0.37823504497807936
使用 sklearn.metrics 中的方法进行评估
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
# mse
mean_squared_error(y_test, y_predict) # 31.763084786207326
# mae
mean_absolute_error(y_test, y_predict) # 3.9395943900511363
# R Square
r2_score(y_test, y_predict) # 0.37823504497807936