线性回归法有一个很大的局限性,它要求假设我们的数据背后是存在线性关系的,但是在我们的实际应用场景中,有线性关系这么强的数据集相对来说还是比较少的,更多的数据之前它们具有的是非线性关系。我们使用一种非常简单的手段,就可以改进我们的线性回归法,使得它可以对非线性的数据进行处理,相应的进行预测,也就是所谓的多项式回归,通过多项式回归这种方法,将引出在机器学习中或许是最为重要的概念,也就是模型泛化相关的问题。
什么是多项式回归
什么是多项式回归?在线性回归中,我们想要寻找一条直线,让这条直线尽可能地拟合数据
而对于有一些数据,虽然我们也可以使用线性回归的方式来拟合,但是其实它是具有更加强的非线性关系。换句话说,如果我们用一根二次曲线来拟合这些数据的话,效果会更好
多项式回归在机器学习上并没有新的地方,完全是使用线性回归的思路,它的关键在于我们为原来的数据样本提供新的特征,而我们得到这些新的特征的方式,是原有的特征的多项式组合,采用这样的方式我们就可以解决一些非线性问题。与此同时,这个思路值得我们去注意一下,我们上一章讲的PCA算法是对我们的数据集进行降维处理,而这一章讲的多项式回归算法显然是在做一件相反的事情,它让我们的数据集升维,在升高维度添加一些新的特征之后,使得我们的算法可以更好的拟合高维度的数据。
scikit-learn中的多项式回归
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import PolynomialFeatures
x = np.random.uniform(-3, 3, size=100)
X = x.reshape(-1, 1)
y = 0.5 * x**2 + x + 2 + np.random.normal(0, 1, 100)
poly_reg = Pipeline([
("poly",PolynomialFeatures(degree=2)),
("std_sclar",StandardScaler()),
("lin_reg",LinearRegression())
])
poly_reg.fit(X,y)
y_predict = poly_reg.predict(X)
plt.scatter(x, y)
plt.plot(np.sort(x), y_predict[np.argsort(x)], color='r')
plt.show()
经过PolynomialFeatures之后,我们的样本特征将呈指数级的增长,十分的强大,与此同时也会牵扯到机器学习中一个非常重要的问题,过拟合和欠拟合。
过拟合与欠拟合
曲线在面对新的数据的时候的预测能力就是泛化能力
随着模型复杂度的增加,训练数据集的模型准确率将会越来越高。但是对于测试数据集来说,却存在欠拟-正合适-过拟这样的曲面变化
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
np.random.seed(666)
x = np.random.uniform(-3.0, 3.0, size=100)
X = x.reshape(-1, 1)
y = 0.5 * x**2 + x + 2 + np.random.normal(0, 1, size=100)
lin_reg = LinearRegression()
lin_reg.fit(X, y)
lin_reg.score(X, y)
y_predict = lin_reg.predict(X)
plt.scatter(x, y)
plt.plot(np.sort(x), y_predict[np.argsort(x)], color='r')
plt.show()
对于这样的数据,简单的线性回归模型显然是欠拟合,曲线不能很好的拟合数据
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import PolynomialFeatures
np.random.seed(666)
x = np.random.uniform(-3.0, 3.0, size=100)
X = x.reshape(-1, 1)
y = 0.5 * x**2 + x + 2 + np.random.normal(0, 1, size=100)
def PolynomialRegression(degree):
return Pipeline([
("poly", PolynomialFeatures(degree=degree)),
("std_scaler", StandardScaler()),
("lin_reg", LinearRegression())
])
poly100_reg = PolynomialRegression(degree=100)
poly100_reg.fit(X, y)
X_plot = np.linspace(-3, 3, 100).reshape(100, 1)
y_plot = poly100_reg.predict(X_plot)
plt.scatter(x, y)
plt.plot(X_plot[:,0], y_plot, color='r')
plt.axis([-3, 3, 0, 10])
plt.show()
当我们过度的使用多项式回归(代码示例degree=100),就会出现过拟合问题,曲线过度的拟合数据