多项式回归
提示:适合初学者使用
提示:写完文章后,记得点点关注,持续更新机器学习系列
如果您的数据点显然不适合线性回归(穿过数据点之间的直线),那么多项式回归可能是理想的选择。
它的出现就是为了弥补线性回归。
像线性回归一样,多项式回归使用变量 x 和 y 之间的关系来找到绘制数据点线的最佳方法。
概念
研究一个因变量(目标变量)与一个或多个自变量间多项式的回归分析方法,称为多项式回归
(Polynomial Regression)。如果自变量只有一个时,称为一元多项式回归;如果自变量有多个时,称
为多元多项式回归。在一元回归分析中,如果因变量 y与自变量x的关系为非线性的,但是又找不到适当
的** 函数曲线 ** 来拟合,则可以采用一元多项式回归。
一般来说我们用到的一元多项式模型更多,如下:
多项式回归的最大优点就是可以通过增加x的高次项对实测点进行逼近,直至满意为止,但是缺点就是如
果数据太多需要耗更多时间。事实上,多项式回归可以处理相当一类非线性问题,它在回归分析中占有
重要的地位,因为任一函数都可以分段用多项式来逼近。因此,在通常的实际问题中,不论依变量与其
他自变量的关系如何,我们总可以用多项式回归来进行分析,所以线性回归可以堪称多项式回归的特殊
情况。
一、案例(numpy实现)
1.1 搭建模型
在下面的例子中,我们记录了 18 辆经过特定收费站的汽车。我们已经记录了汽车的速度和通过时间
(小时)。x 轴表示一天中的小时,y 轴表示速度:
import matplotlib.pyplot as plt
x = [1,2,3,5,6,7,8,9,10,12,13,14,15,16,18,19,21,22]
y = [100,90,80,60,60,55,60,65,70,70,75,76,78,79,90,99,99,100]
plt.scatter(x, y)
plt.show()
明显这不是线性了。
导入 numpy 和 matplotlib,然后画出多项式回归线:
import numpy
import matplotlib.pyplot as plt
x = [1,2,3,5,6,7,8,9,10,12,13,14,15,16,18,19,21,22]
y = [100,90,80,60,60,55,60,65,70,70,75,76,78,79,90,99,99,100]
mymodel = numpy.poly1d(numpy.polyfit(x, y, 3)) # 三阶
myline = numpy.linspace(1, 22, 100) # 产生1到22的100个点
plt.scatter(x, y) # 原始点
plt.plot(myline, mymodel(myline)) # 多项式回归
plt.show() #显示
3阶拟合绘制如图:
如果是10阶:
1.2 评估回归
重要的是要知道 x 轴和 y 轴的值之间的关系有多好,如果没有关系,则多项式回归不能用于预测任何东
西:
import numpy
from sklearn.metrics import r2_score
x = [1,2,3,5,6,7,8,9,10,12,13,14,15,16,18,19,21,22]
y = [100,90,80,60,60,55,60,65,70,70,75,76,78,79,90,99,99,100]
mymodel = numpy.poly1d(numpy.polyfit(x, y, 3))
print(r2_score(y, mymodel(x)))
结果R^2值 0.94 表明存在很好的关系,我们可以在将来的预测中使用多项式回归。
1.3 预测未来值
预测下午 17 点过车的速度:
speed = mymodel(17)
print(speed)
该例预测速度为 88.87。
二、案例(sklearn实现)
为了解决欠拟合的情 经常要提高线性的次数建立模型拟合曲线, 次数过高会导致过拟合,次数不够会欠
拟合。再建立高次函数时候,要利用多项式特征生成器 生成训练数据。
在做线性回归预测时候,为了提高模型的泛化能力,经常采用多次线性函数建立模型:
先了解一些基本概念:
泛化:
对未训练过的数据样本进行预测。
泛化能力:
对未训练过的数据样本进行预测的效果。
欠拟合:
由于对训练样本的拟合程度不够,导致模型的泛化能力不足。最常见的导致原因是:数据不足、数据
缺失值之类的。
过拟合:
训练样本拟合非常好,并且学习到了不希望学习到的特征,导致模型的泛化能力不足。间接的说:训
练准确率大于测试准确率,可以用这个标准来判断模型是否过拟合和欠拟合。
这个类可以进行特征的构造,构造的方式就是特征与特征相乘(自己与自己,自己与其他人),这种方
式叫做使用多项式的方式。语法:
sklearn.preprocessing.PolynomialFeatures(degree=2,
interaction_only=False,include_bias=True)
这个方式省略了很多步骤,并且也无法得知PolynomialFeatures是如何运作的。在建立超过一次函数的
线性回归模型之前,要对默认特征生成多项式特征再输入给模型。
poly2 = PolynomialFeatures(degree=2) # 2次多项式特征生成器
x_train_poly2 = poly2.fit_transform(x_train)
首先我们来定义一些数据并绘制图形:
# 自定义数据
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
#x从-3 - 3均匀取值
x = np.random.uniform(-3, 3 ,size=100)
X = x.reshape(-1, 1)
#y是二次方程
y = 0.5 * x**2 + x +2 + np.random.normal(0, 1, size = 100)
plt.scatter(x, y )
如下:
接着使用线性模型进行拟合如下:
# 线性拟合
from sklearn.linear_model import LinearRegression
#实例化线性模型
lr = LinearRegression()
lr.fit(X, y)
y_predict = lr.predict(X)
plt.scatter(x, y )
plt.plot(x, y_predict)
如下:
# 为总特征添加二次这个特征然后去拟合
from sklearn.preprocessing import PolynomialFeatures
poly = PolynomialFeatures(degree=2)
#degree=2 生成2次特征,可以调整
poly.fit(X)
X2 = poly.transform(X)
print('X2的大小',X2.shape)
X2[0:5, :] # 前五个
输出结果:(100, 3)。 第一列常数项,第二列一次项系数,第三列二次项系数,第三列三次项系数。接
下来查看一下前五列。如下:
X2的大小 (100, 3)
array([[ 1. , -0.60809991, 0.3697855 ],
[ 1. , -0.34602578, 0.11973384],
[ 1. , -1.68750674, 2.84767899],
[ 1. , 0.14662252, 0.02149816],
[ 1. , -2.1034439 , 4.42447624]])
二次拟合如下:
#为X添加了二次的特征,来拟合下y
lr.fit(X2, y)
y_predict2 = lr.predict(X2)
plt.scatter(x, y)
plt.plot(np.sort(x), y_predict2[np.argsort(x)] )
如下:
如果为3次:
小总结:对于我们拿到的特征只有低次关系,而预测值为高次关系,我们可以使用PolynomialFeatures
生成高次的特征去更好拟合预测值。实际上,次数越高,拟合效果越好