机器学习之多项式回归和学习曲线

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第9天,点击查看活动详情

我们之间都是用线性回归去模拟线性的数据,那么如果我们如何来预测一些非线性的呢?这就是需要用用到多项式回归的技术。

多项式回归

比如一个一元二次的方程如 a X 2 + b X + c aX^{2}+bX+c ,这个图像一看就是一个非线性的。这个例子我们知道他是一个二次方程,但是在其他项目我们往往时不清楚次数,所以第一步是需要先估计出一个次数。

然后我们就可以调用Scikit-Learn的PolynomialFeatures,将我们猜测的这个特征的n次,作为我们新的特征,而我们的线性回归就是对这个新的特征进行训练和预测。

from sklearn.preprocessing import PolynomialFeatures
m = 100
# x的范围,不要太小,不然我们模拟的数据会因为x的左右取值范围太窄而混在一起
# 可以设置 np.random.seed(),方便后面重现
X =  10* np.random.rand(m,1) -5
# 这里的a为 0.5 b 为 1 c为 2 ,同时别忘了加上噪音
y = 0.5 * X**2 + X + 2 + np.random.randn(m,1)
# 设置新的特征值
poly_features = PolynomialFeatures(degree=2,include_bias=False)
X_poly = poly_features.fit_transform(X)
# 调用线性回归
lin_reg = LinearRegression()
lin_reg.fit(X_poly, y)
# lin_reg.intercept_, lin_reg.coef_ 输出
# (array([1.78134581]), array([[0.96020136, 0.52324255]]))
复制代码

图1 二元方程式预测

结果还是蛮不错,而且我们发现coef返回多个数的列表,分别表示b和a(循序是反着的)。

简单看一下PolynomialFeatures(degree=2,include_bias=False)的参数含义:

  • degree这个是用来设置我们的新参数是多少次方程,degree=2,就是二次方程
  • include_bias bias 我们上一篇了解过,这里不添加偏置项,默认是True

使用PolynomialFeatures需要注意一些问题:如果我们的特征有两个如a和b,而degree=2是,他生成函数不仅有 a 2 b 2 a^{2}、 b^{2} 也会生成 a b ab ,所以我们不要设置过多的特征值和degreee。

如果degree设置过高,他会有这种错误:RuntimeWarning: overflow encountered in multiply 我的机器他算不过来,再向我求饶了。

因为存在噪音的原因,我们其实并不能用二次方程式完美的预测出来,那我们是不是可以用高阶的方程去模拟呢?Ok,想到我们就动手试试看,来个100阶的:

图2 高阶多项式回归

扫描二维码关注公众号,回复: 14336229 查看本文章

似乎好像效果很诡异,怎么线都上上下下的,歪歪扭扭的呢!!

其实这就是过拟合了,我们用了高阶多项式他希望尽可能的把每个点都包含在内,这样就出现了这个诡异的画面。那么我们怎么知道我们的模型是不是过拟合了。

学习曲线

这个时候我们我们就需要配合学习曲线来看了,我们的学习曲线绘制的就是我们的模型在训练集和验证集上关于训练集大小(或者迭代次数)的性能曲线。

def plot_learning_curve(model, X, y):
    X_train,X_val ,y_train,y_val = train_test_split(X,y,test_size=0.2)
    train_errors, val_errors = [],[]
    for m in range(1,len(X_train)):
        model.fit(X_train[:m],y_train[:m])
        y_train_pred = model.predict(X_train[:m])
        y_val_pred = model.predict(X_val)
        train_errors.append(mean_squared_error(y_train[:m],y_train_pred ))
        val_errors.append(mean_squared_error(y_val,y_val_pred))
    plt.plot(np.sqrt(train_errors),'r-+',linewidth=2, label="训练集")
    plt.plot(np.sqrt(val_errors),'b-',linewidth=3, label="验证集")
    
# 这个只有单纯的线性回归
lin_reg = LinearRegression()
plot_learning_curve(lin_reg,X,y)
复制代码

图3 学习曲线

我们看到训练集和验证集的误差好像是不一样起点,只是因为我们的模型是从训练集中训练出来的,所以当训练数还比较少时,这个模型自然预测的不错,但是随着训练集数量的增加,后面就渐渐的到达一个稳定的误差。而且他不会因为训练集数据增加而变动。

而我们的验证因为一开始训练的少,所以预测自然误差大,但是随着训练的进行,预测的成功率也是一步步增加,误差也最终稳定在一个范围内。

由于我们是直接使用线性回归,随意最后的误差会在很大。因此我们也可以看看如果是设置degree为2的多项式回归的学习曲线是怎么样的:

图3 二阶多项式学习曲线

通过上面的图,我们可以得出一些好的学习曲线的特点:

  1. 误差很小
  2. 验证集和训练集的两条线应该是有一段时间相距比较远,后面才慢慢靠近。

猜你喜欢

转载自juejin.im/post/7104669179927592973