来源:原始 Jupyter Notebook。内容已转换为网页阅读格式;下载原文件。
前面在计算多项式回归时,随着维度的增多,程序写起来也越来越麻烦。这一节我们使用 scikit-learn 来简化这个操作。
scikit-learn 简称 sklearn,它是 Python 语言里的一个通用机器学习库,里面包含了大量常用的机器学习方法,如分类,回归,无监督学习,降维,预处理等等。在前面求解线性回归问题时,我们使用了最原始的方法,手工推导出了用最小二乘法的解析解:
这一节,我们使用 sklearn 自带的 LinearRegression 模块来求解线性回归。首先看一元的场景:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
plt.xlim(30, 60)
plt.ylim(100, 600)
X = np.array([39.93, 42.05, 43.18, 44.68, 49.87, 53.57]).reshape(-1, 1)
Y = np.array([199, 290, 298, 310, 399, 420]).reshape(-1, 1)
plt.scatter(X, Y)
model = LinearRegression()
model.fit(X, Y)
x = np.linspace(30, 60, 100).reshape(-1, 1)
y = model.predict(x)
plt.plot(x, y)
plt.show()
运行结果

使用 sklearn 里的机器学习算法,都是同一个套路,先使用 fit 方法训练出模型,然后再使用模型的 predict 方法进行预测(注意输入的数据要使用 reshape(-1, 1) 转换为列向量):
再来看看二元的场景:
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from matplotlib import cm
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(1,1,1,projection='3d')
X = np.array([6000, 6000, 8000, 8000, 10000]).reshape(-1, 1)
Y = np.array([60, 80, 70, 100, 90]).reshape(-1, 1)
Z = np.array([340000, 350000, 400000, 450000, 500000]).reshape(-1, 1)
ax.scatter(X, Y, Z, c='red', marker='o')
model = LinearRegression()
XY = np.hstack([X, Y])
model.fit(XY, Z)
x = np.linspace(6000, 10000, 10).reshape(-1, 1)
y = np.linspace(60, 90, 10).reshape(-1, 1)
xy = np.hstack([x, y])
z = model.predict(xy)
x, y = np.meshgrid(x, y)
ax.plot_surface(x, y, z, linewidth=0, antialiased=False)
plt.show()
运行结果

画出来的图形和前面的有一定的差异,这是因为数据量比较少,而且 sklearn 的线性回归使用的算法也不是我们前面介绍的正规解法,而是使用了梯度下降法(待验证)。不过 numpy 里提供了一个最小二乘方法 lstsq,我们可以验证下前面的求解结果对不对:
import numpy as np
from numpy.linalg import lstsq
np.set_printoptions(suppress=True)
X = np.matrix([
[1, 1, 1, 1, 1],
[6000, 6000, 8000, 8000, 10000],
[60, 80, 70, 100, 90]]).T
Y = np.matrix([340000, 350000, 400000, 450000, 500000]).T
print(lstsq(X, Y, rcond=None)[0])
运行结果
[[62105.26315789]
[ 32.10526316]
[ 1273.68421053]]
同样,sklearn 也可以求解多项式回归,但是多项式回归其本质依然是线性回归,只是在做线性回归之前将入参从一维扩展到多维。我们使用 sklearn 预处理模块中的 PolynomialFeatures.fit_transform() 来完成这个转换。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
plt.xlim(30, 60)
plt.ylim(100, 600)
def draw_polynomial(X, Y, degree):
polynomial = PolynomialFeatures(degree = degree)
X_t = polynomial.fit_transform(X)
model = LinearRegression()
model.fit(X_t, Y)
x = np.linspace(30, 60, 100).reshape(-1, 1)
x_t = polynomial.fit_transform(x.reshape(x.shape[0], 1))
y = model.predict(x_t)
plt.plot(x, y)
X = np.array([39.93, 42.05, 43.18, 44.68, 49.87, 53.57]).reshape(-1, 1)
Y = np.array([199, 290, 298, 310, 399, 420]).reshape(-1, 1)
plt.scatter(X, Y)
# 二次回归
draw_polynomial(X, Y, 2)
# 三次回归
draw_polynomial(X, Y, 3)
plt.show()
运行结果

也可以画出十次回归的曲线图:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
plt.xlim(30, 60)
plt.ylim(100, 600)
def draw_polynomial(X, Y, degree):
polynomial = PolynomialFeatures(degree = degree)
X_t = polynomial.fit_transform(X)
model = LinearRegression()
model.fit(X_t, Y)
x = np.linspace(30, 60, 100).reshape(-1, 1)
x_t = polynomial.fit_transform(x.reshape(x.shape[0], 1))
y = model.predict(x_t)
plt.plot(x, y)
X = np.array([39.93, 42.05, 43.18, 44.68, 49.87, 53.57]).reshape(-1, 1)
Y = np.array([199, 290, 298, 310, 399, 420]).reshape(-1, 1)
plt.scatter(X, Y)
# 十次回归
draw_polynomial(X, Y, 10)
plt.show()
运行结果
