多项式回归

释放双眼,带上耳机,听听看~!

多项式回归

日萌社

人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新)


第二章知识补充: 多项式回归

我们在前面讲的都是一般线性回归,即使用的假设函数是一元一次方程,也就是二维平面上的一条直线。

但是很多时候可能会遇到直线方程无法很好的拟合数据的情况,这个时候可以尝试使用多项式回归。

多项式回归中,加入了特征的更高次方(例如平方项或立方项),也相当于增加了模型的自由度,用来捕获数据中非线性的变化。添加高阶项的时候,也增加了模型的复杂度。随着模型复杂度的升高,模型的容量以及拟合数据的能力增加,可以进一步降低训练误差,但导致过拟合的风险也随之增加(后面会专门讨论出现过拟合的情况)。

1 多项式回归的一般形式

在多项式回归中,最重要的参数是最高次方的次数。设最高次方的次数为n,且只有一个特征时,其多项式回归的方程为:

 多项式回归

其中?是大小为m⋅(n+1)的矩阵,θ是大小为(n+1)⋅1的矩阵。

在这里虽然只有一个特征x以及x的不同次方,但是也可以将x的高次方当做一个新特征。与多元回归分析唯一不同的是,这些特征之间是高度相关的,而不是通常要求的那样是相互对立的。

在这里有个问题在刚开始学习线性回归的时候困扰了自己很久:如果假设中出现了高阶项,那么这个模型还是线性模型吗?此时看待问题的角度不同,得到的结果也不同。如果把上面的假设看成是特征xx的方程,那么该方程就是非线性方程;如果看成是参数?θ的方程,那么xx的高阶项都可以看做是对应?θ的参数,那么该方程就是线性方程。很明显,在线性回归中采用了后一种解释方式。因此多项式回归仍然是参数的线性模型。

2 多项式回归的实现


1
2
3
4
5
1import numpy as np
2import matplotlib.pyplot as plt
3from sklearn.linear_model import LinearRegression
4from sklearn.metrics import mean_squared_error
5

多项式回归


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1# 构造数据,数据可视化展示
2data = np.array([[ -2.95507616,  10.94533252],
3                 [ -0.44226119,   2.96705822],
4                 [ -2.13294087,   6.57336839],
5                 [  1.84990823,   5.44244467],
6                 [  0.35139795,   2.83533936],
7                 [ -1.77443098,   5.6800407 ],
8                 [ -1.8657203 ,   6.34470814],
9                 [  1.61526823,   4.77833358],
10                 [ -2.38043687,   8.51887713],
11                 [ -1.40513866,   4.18262786]])
12
13X = data[:, 0].reshape(-1, 1)  # 将array转换成矩阵
14y = data[:, 1].reshape(-1, 1)
15
16plt.plot(X, y, "b.")
17plt.xlabel('X')
18plt.ylabel('y')
19plt.show()
20

多项式回归

2.1 直线方程的拟合

下面先用直线方程拟合上面的数据点:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1lin_reg = LinearRegression()
2lin_reg.fit(X, y)
3print(lin_reg.intercept_, lin_reg.coef_)  # [ 4.97857827] [[-0.92810463]]
4
5X_plot = np.linspace(-3, 3, 1000).reshape(-1, 1)
6
7# 可以使用两种方法用于模型预测
8# y_plot = np.dot(X_plot, lin_reg.coef_.T) + lin_reg.intercept_
9y_plot = lin_reg.predict(X_plot)
10
11plt.plot(X_plot, y_plot,"red")
12plt.plot(X, y, 'b.')
13plt.xlabel('X')
14plt.ylabel('y')
15
16# 使用mse衡量其误差值:
17y_pre = lin_reg.predict(X)
18mean_squared_error(y, y_pre)
19# 3.3363076332788495
20

多项式回归

2.2 使用多项式方程

多项式回归

sklearn 的 PolynomialFeatures 的用法

官方文档链接

多项式回归


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1X = np.arange(6).reshape(3, 2)
2X
3
4# 输出结果
5array([[0, 1],
6       [2, 3],
7       [4, 5]])
8
9from sklearn.preprocessing import PolynomialFeatures
10# 设置多项式阶数为2,其他值默认
11# degree 多项式阶数
12poly = PolynomialFeatures(degree=2)
13res = poly.fit_transform(X)
14res
15
16# 输出结果
17array([[ 1.,  0.,  1.,  0.,  0.,  1.],
18       [ 1.,  2.,  3.,  4.,  6.,  9.],
19       [ 1.,  4.,  5., 16., 20., 25.]])
20
21

使用函数"PolynomialFeatures"获取二次方项:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1poly_features = PolynomialFeatures(degree=2, include_bias=False)
2X_poly = poly_features.fit_transform(X)
3print(X_poly)
4
5# 输出结果
6[[-2.95507616  8.73247511]
7 [-0.44226119  0.19559496]
8 [-2.13294087  4.54943675]
9 [ 1.84990823  3.42216046]
10 [ 0.35139795  0.12348052]
11 [-1.77443098  3.1486053 ]
12 [-1.8657203   3.48091224]
13 [ 1.61526823  2.60909145]
14 [-2.38043687  5.66647969]
15 [-1.40513866  1.97441465]]
16
17

利用上面的数据做线性回归分析:


1
2
3
4
5
6
7
8
9
10
11
12
1lin_reg = LinearRegression()
2lin_reg.fit(X_poly, y)
3print(lin_reg.intercept_, lin_reg.coef_)  
4# [ 2.60996757] [[-0.12759678  0.9144504 ]]
5
6X_plot = np.linspace(-3, 3, 1000).reshape(-1, 1)
7X_plot_poly = poly_features.fit_transform(X_plot)
8y_plot = lin_reg.predict(X_plot_poly)
9plt.plot(X_plot, y_plot, 'red')
10plt.plot(X, y, 'b.')
11plt.show()
12

多项式回归


1
2
3
4
5
6
1# 使用mse衡量其误差值:
2y_pre = lin_reg.predict(X_poly)
3mean_squared_error(y, y_pre)
4# 0.07128562789085331
5
6

利用多项式回归,代价函数MSE的值下降到了0.07。

多项式回归

3 持续降低训练误差与过拟合

在上面实现多项式回归的过程中,通过引入高阶项x2,训练误差从3.34下降到了0.07,减小了将近50倍。那么训练误差是否还有进一步下降的空间呢?

多项式回归

下面是测试不同degree的过程:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1# 定义模型训练函数
2def try_degree(degree, X, y):
3    poly_features_d = PolynomialFeatures(degree=degree, include_bias=False)
4    X_poly_d = poly_features_d.fit_transform(X)
5    lin_reg_d = LinearRegression()
6    lin_reg_d.fit(X_poly_d, y)
7    return {'X_poly': X_poly_d, 'intercept': lin_reg_d.intercept_, 'coef': lin_reg_d.coef_}
8
9degree2loss_paras = []
10for i in range(2, 20):
11    paras = try_degree(i, X, y)
12
13    # 自己实现预测值的求解
14    h = np.dot(paras['X_poly'], paras['coef'].T) + paras['intercept']
15    _loss = mean_squared_error(h, y)
16    degree2loss_paras.append({'d': i, 'loss': _loss, 'coef': paras['coef'], 'intercept': paras['intercept']})
17
18

查看最小模型参数:


1
2
3
4
5
6
7
8
9
10
11
1min_index = np.argmin(np.array([i['loss'] for i in degree2loss_paras]))
2min_loss_para = degree2loss_paras[min_index]
3print(min_loss_para)
4
5# 输出结果
6{'d': 12,
7 'loss': 3.8764202841976227e-23,
8 'coef': array([[ 1.17159189,  8.60674192, -4.91798703, -4.18378115,  3.79426131, -8.56026107, -6.94465715,  5.03891035,  4.08870088, -0.30369348, -0.6635493 , -0.11314395]]),
9 'intercept': array([1.63695924])}
10
11

对最小模型可视化展示:


1
2
3
4
5
6
7
8
9
10
11
12
1X_plot = np.linspace(-3, 1.9, 1000).reshape(-1, 1)
2poly_features_d = PolynomialFeatures(degree=min_loss_para['d'], include_bias=False)
3
4X_plot_poly = poly_features_d.fit_transform(X_plot)
5y_plot = np.dot(X_plot_poly, min_loss_para['coef'].T) + min_loss_para['intercept']
6
7
8plt.plot(X_plot, y_plot, 'red', label="degree12")
9plt.plot(X, y, 'b.', label="X")
10plt.legend(loc='best')
11plt.show()
12

多项式回归

此时函数图像穿过了每一个样本点,所有的训练样本都落在了拟合的曲线上,训练误差接近与0。 可以说是近乎完美的模型了。但是,这样的曲线与我们最开始数据的来源(一个二次方程加上一些随机误差)差异非常大。

如果从相同来源再取一些样本点,使用该模型预测会出现非常大的误差。类似这种训练误差非常小,但是新数据点的测试误差非常大的情况,就叫做模型的过拟合。过拟合出现时,表示模型过于复杂,过多考虑了当前样本的特殊情况以及噪音(模型学习到了当前训练样本非全局的特性),使得模型的泛化能力下降。

防止模型过拟合是机器学习领域里最重要的问题之一。鉴于该问题的普遍性和重要性,在满足要求的情况下,能选择简单模型时应该尽量选择简单的模型。

 

 

给TA打赏
共{{data.count}}人
人已打赏
安全运维

WordPress网站专用docker容器环境带Waf

2020-7-18 20:04:44

安全运维

运维安全-Gitlab管理员权限安全思考

2021-9-19 9:16:14

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索