4 机器学习 欠拟合和过拟合 多项式回归 正则化 岭回归 模型的保存与加载
机器学习1 案例 预测房屋价格1.1 数据介绍台湾新北市新店区的房地产估值的市场历史数据集。字段介绍X1 - 交易日期,例如2013.250表示2013年3月,2013.500表示2013年6月X2 - 房屋年龄 (单位:年)X3 - 到最近的捷运站的距离 (单位:米)X4 - 步行生活圈中便利店的数量 (整数)X5 - 地理坐标纬度 (单位:度)X6 - 地理坐标经度 (单位:度)标签Y表示单位
机器学习
1 案例 预测房屋价格
1.1 数据介绍
台湾新北市新店区的房地产估值的市场历史数据集。
字段介绍
X1 - 交易日期,例如2013.250表示2013年3月,2013.500表示2013年6月
X2 - 房屋年龄 (单位:年)
X3 - 到最近的捷运站的距离 (单位:米)
X4 - 步行生活圈中便利店的数量 (整数)
X5 - 地理坐标纬度 (单位:度)
X6 - 地理坐标经度 (单位:度)
标签Y表示单位面积房价 (10000新台币/ Ping,其中Ping是本地单位,1 Ping = 3.3平方米)
1.2 构建模型
导入数据
import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error as MSE
from sklearn.metrics import r2_score
df = pd.read_excel('./datasets/house.xlsx')
df = df.drop(labels='No', axis=1)
df.head(3)
'''
X1 transaction date X2 house age X3 distance to the nearest MRT station X4 number of convenience stores X5 latitude X6 longitude Y house price of unit area
0 2012.916667 32.0 84.87882 10 24.98298 121.54024 37.9
1 2012.916667 19.5 306.59470 9 24.98034 121.53951 42.2
2 2013.583333 13.3 561.98450 5 24.98746 121.54391 47.3
'''
feature = df.loc[:,df.columns != 'Y house price of unit area']
target = df['Y house price of unit area']
feature.shape # (414, 6)
x_train, x_test, y_train, y_test = train_test_split(feature, target, test_size=0.2, random_state=2020)
lr = LinearRegression()
lr.fit(x_train,y_train)
1.3 评估模型
y_test_pred = lr.predict(x_test)
# 均方误差MSE
MSE(y_test, y_test_pred) # 55.33406050090903
y_test.max() # 63.2
y_test.min() # 13.8
# R方
r2_score(y_test, y_test_pred) # 0.6108181277767377
lr.score(x_test, y_test) # 0.6108181277767377
用训练集评估模型
y_train_pred = lr.predict(x_train)
# 均方误差MSE
MSE(y_train, y_train_pred) # 83.00347064630712
y_train.max() # 117.5
y_train.min() # 7.6
# R方
r2_score(y_train, y_train_pred) # 0.5750984249253508
lr.score(x_train, y_train) # 0.5750984249253508
发现模型在训练集和测试集中的表现都不好。
此时出现的问题称为欠拟合。
2 欠拟合和过拟合
-
欠拟合
欠拟合(Underfitted)表现为模型在训练集和训练集的误差均较大。
产生欠拟合的原因是模型学习到的特征过少,模型过于简单,导致模型的回归函数较为粗糙,不能对训练集做出准确拟合,因此误差较大。
可以通过增加特征维度来解决欠拟合问题。 -
过拟合
欠拟合(Overfitted)表现为模型在训练集上表现很好,但在测试集上存在较大的误差,即模型太过于依赖的训练集数据,泛化能力较差。
产生过拟合的原因是模型学习到的特征过多,模型过于复杂,导致模型的回归函数虽然能够完美地对训练数据集进行拟合,但是对新数据的预测存在较大误差。
可以通过正则化来解决过拟合问题。 -
泛化能力
泛化能力(Generalization Ability)是指模型对未知数据进行预测或分类的表现。
3 解决欠拟合问题 - 多项式回归
3.1 介绍
欠拟合问题是由于模型过于简单导致的,即线性回归模型中特征与标签的关系过于简单,只能是线性关系。
需要通过增加特征维度来增加模型的复杂程度,回归问题中可以通过增加高次项特征来实现,这样线性回归模型就转化为多项式回归(Polynomial Regression)模型,多项式回归模型中每一项都可以理解为一个特征维度。
3.2 PolynomialFeatures
sklearn.preprocessing.PolynomialFeatures(degree=2, interaction_only=False, include_bias=True)
参数说明
假设存在
a
a
a和
b
b
b两个特征,2次多项式为
[
1
,
a
,
b
,
a
2
,
b
2
]
[1, a, b, a^2, b^2]
[1,a,b,a2,b2]。
- degree:用于指定多项式的次数,默认为2;
- interaction_only:是否允许出现特征与自己结合的项,默认为False,如果指定interaction_only=True,上面例子中的2次多项式不会存在 a 2 a^2 a2和 b 2 b^2 b2;
- include_bias:是否允许出现0次幂的项,默认为True,如果指定include_bias=False,上面例子中的2次多项式不会存在 1 1 1。
3.3 案例
使用多项式回归处理上面的案例。
3.3.1 准备数据
import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error as MSE
from sklearn.metrics import r2_score
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']
3.3.2 增加高次项特征
向数据集中增加高次项特征,这里使用二次项。
from sklearn.preprocessing import PolynomialFeatures
p2 = PolynomialFeatures(degree=2) # PolynomialFeatures(degree=2, include_bias=True, interaction_only=False, order='C')
d2_feature = p2.fit_transform(feature)
3.3.3 构建模型
x_train, x_test, y_train, y_test = train_test_split(d2_feature, target, test_size=0.2, random_state=2020)
lr = LinearRegression()
lr.fit(x_train,y_train)
3.3.4 评估模型
y_pred = lr.predict(x_test)
MSE(y_test, y_pred) # 30.830183307250028
lr.score(x_test, y_test) # 0.7831616123616155
4 解决过拟合问题 - 正则化
4.1 过拟合产生原因分析
上面的案例中,如果增加的特征维度设置过大,会导致模型处理测试集时产生的误差非常大。
from sklearn.preprocessing import PolynomialFeatures
p5 = PolynomialFeatures(degree=5) # 维度设置为5
d5_feature = p5.fit_transform(feature)
x_train, x_test, y_train, y_test = train_test_split(d5_feature, target, test_size=0.2, random_state=2020)
lr = LinearRegression()
lr.fit(x_train, y_train)
# 测试集
y_test_pred = lr.predict(x_test)
MSE(y_test, y_pred) # 996.1982154441408
lr.score(x_test, y_test) # -6.00657575248168
# 训练集
y_train_pred = lr.predict(x_train)
MSE(y_train, y_train_pred) # 29.21333530526558
lr.score(x_train, y_train) # 0.8504545401808031
可以看出,模型在训练集上的表现非常好,但在测试集上的表现却很差。换句话说,模型过于依赖训练集,在训练集上可以做出非常好的拟合,但是处理新的数据会产生较大的误差,此时模型发生了过拟合现象。
4.2 正则化
发生过拟合的原因是模型过于复杂,包含了许多不必要的特征。
解决方法包括:
- 添加数据,使得数据量远大于特征数量;
- 通过特征选择或者特征提取减少特征数量;
- 正则化。
这里主要介绍正则化。
与正常拟合的曲线相比,过拟合的曲线包含了许多幅度较大的凹凸,因此直观的处理方法是降低曲线的凹凸幅度。曲线的凹凸一般是由模型中的高次项特征产生的,正则化就是通过不断的尝试来降低模型高次项特征的权重,使其不断趋近于0。
正则化的本质是对参数空间添加约束,正则化框架:
L
(
w
)
+
α
P
(
w
)
=
∣
∣
y
−
X
w
∣
∣
2
2
+
α
∣
∣
w
∣
∣
2
2
L(\boldsymbol{w}) + α P(\boldsymbol{w})= {||\boldsymbol{y-Xw}||}_2^2 + α||\boldsymbol{w}||^2_2
L(w)+αP(w)=∣∣y−Xw∣∣22+α∣∣w∣∣22
其中,
L
(
w
)
L(w)
L(w)是损失函数,
P
(
w
)
P(w)
P(w)是惩罚项,
α
α
α是超参数。
正则化分类
- L1正则化,也称为Lasso回归, P ( w ) = ∣ ∣ w ∣ ∣ 1 P(\boldsymbol{w})=||\boldsymbol{w}||_1 P(w)=∣∣w∣∣1。
- L2正则化,也称为Ridge回归,即岭回归, P ( w ) = ∣ ∣ w ∣ ∣ 2 2 = w T w P(\boldsymbol{w})=||\boldsymbol{w}||^2_2=\boldsymbol {w}^T\boldsymbol {w} P(w)=∣∣w∣∣22=wTw。
4.3 岭回归
4.3.1 介绍
岭回归模型(Ridge Regression)是具备L2正则化的线性回归模型,通过引入一个特征参数的惩罚项来减小参数值。
arg min
w
[
∣
∣
y
−
X
w
∣
∣
2
2
+
α
∣
∣
w
∣
∣
2
2
]
\argmin_{\boldsymbol w} [{||\boldsymbol{y-Xw}||}_2^2 + α||\boldsymbol{w}||^2_2]
wargmin[∣∣y−Xw∣∣22+α∣∣w∣∣22]
其中
α
α
α表示正则化的力度,
α
α
α越大,高次项的权重越接近于0,过拟合曲线中的凹凸幅度越小。
w
^
=
arg min
w
[
∣
∣
y
−
X
w
∣
∣
2
2
+
α
∣
∣
w
∣
∣
2
2
]
\hat{\boldsymbol w} = \argmin_{\boldsymbol w} [{||\boldsymbol{y-Xw}||}_2^2 + α||\boldsymbol{w}||^2_2]
w^=wargmin[∣∣y−Xw∣∣22+α∣∣w∣∣22]
通过令上式对
w
\boldsymbol w
w的偏导为0,计算出
w
^
=
(
X
T
X
+
α
I
)
−
1
X
T
y
\hat{\boldsymbol w} = (\boldsymbol{X}^T\boldsymbol{X} + α\boldsymbol{I})^{-1}\boldsymbol{X}^T\boldsymbol{y}
w^=(XTX+αI)−1XTy
矩阵
X
T
X
+
α
I
\boldsymbol{X}^T\boldsymbol{X} + α\boldsymbol{I}
XTX+αI一定是正定的(可逆的)。
使用最小二乘法直接对损失函数进行估计(上一节),得到
w
^
=
(
X
T
X
)
−
1
X
T
y
\hat{\boldsymbol w} = (\boldsymbol{X}^T\boldsymbol{X})^{-1}\boldsymbol{X}^T\boldsymbol{y}
w^=(XTX)−1XTy
通过对比可以发现,带超参数
α
α
α的惩罚项的作用是对所有的参数造成衰减,因此岭回归也称为权值衰减。
4.3.2 代码实现
x_train = [[6], [8], [10], [14], [18]]
y_train = [[7], [9], [13], [17.5], [18]]
pf = PolynomialFeatures(degree=5)
d5_train = pf.fit_transform(x_train)
lr = LinearRegression()
lr.fit(d5_train, y_train)
pf.powers_
'''
array([[0], [1], [2], [3], [4], [5]], dtype=int64)
'''
lr.coef_
'''
array([[ 8.58514662e-11, -2.63443321e-01, -1.29176988e+00,
2.66898824e-01, -1.79389838e-02, 3.97068908e-04]])
'''
使用岭回归模型,通过控制正则化力度参数alpha降低高次项特征的权重。
from sklearn.linear_model import Ridge
x_train = [[6], [8], [10], [14], [18]]
y_train = [[7], [9], [13], [17.5], [18]]
pf = PolynomialFeatures(degree=5)
d5_train = pf.fit_transform(x_train)
ridge = Ridge(alpha=0.5)
ridge.fit(d5_train, y_train)
ridge.coef_
'''
array([[ 0.00000000e+00, -8.97118441e-02, -4.38385511e-01,
1.06492140e-01, -7.35242572e-03, 1.60866438e-04]])
'''
5 模型的保存与加载
使用pickle实现模型的保存与加载。
import pickle
with open('./ridge.pkl','wb') as fp:
pickle.dump(ridge,fp)
import pickle
ridge = None
with open('./ridge.pkl','rb') as fp:
ridge = pickle.load(fp)
print(ridge) # Ridge(alpha=0.5, copy_X=True, fit_intercept=True, max_iter=None, normalize=False, random_state=None, solver='auto', tol=0.001)
更多推荐
所有评论(0)