sklearn实现多项式回归
多项式回归
一个数据集,用散点图画出来如下图,可以看到此时用一条直线(或者超平面)是不能拟合的,所以需要用一个多项式表示的曲线(或者超曲面)才能得到更好的拟合结果。
下面可以看一个例子:有不同职位,分成10个等级,不同等级的工资不同,可以根据等级(横坐标)和工资(纵坐标)来画一个散点图,具体见下图:
可以看到该散点图呈曲线分布,所以可以用多项式回归来拟合。上方的数据可以从该链接获取(https://pan.baidu.com/s/1fYR3VPFaldz0Bnzfm5wsvg),获取数据文件后,将文件导入到你用python编程的同一个目录下,接下来就是编程实现拟合了,代码如下:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
# 下面导入的包是用来实现多项式的
from sklearn.preprocessing import PolynomialFeatures
# 载入数据
data = np.genfromtxt("job.csv",delimiter= ",")
x_data = data[1:,1]
y_data = data[1:,2]
# 下面是将取得的数据画一个散点图
# plt.scatter(x_data,y_data)
# plt.show()
x_data = data[1:,1,np.newaxis] # 或者x_data = x_data[:,np.newaxis]
y_data = data[1:,2,np.newaxis] # 或者y_data = y_data[:,np.newaxis]
# 创建并拟合模型
# model = LinearRegression()
# model.fit(x_data,y_data)
# 画图
# plt.plot(x_data,y_data,'b.') #画一个蓝色点的图
# plt.plot(x_data,model.predict(x_data),'r') # 此处用的线性回归模型进行预测,将预测值作为y值,画一个红色的直线拟合
# plt.show()
# 定义多项式回归,degree的值可以调节多项式的特征
poly_reg = PolynomialFeatures(degree=5)
# 特征处理
x_poly = poly_reg.fit_transform(x_data)
# 定义回归模型
lin_reg = LinearRegression()
# 训练模型
lin_reg.fit(x_poly,y_data)
# 画图
plt.plot(x_data,y_data,'b.')
plt.plot(x_data,lin_reg.predict(poly_reg.fit_transform(x_data)),c = 'r')
plt.title('Truth or Bluff(Polynomial Regression)')
plt.xlabel('Position level')
plt.ylabel('Salary')
plt.show()
最后结果如下:
代码被注释的11-13行,是画一个散点图;被注释掉的19-25行表示用线性回归来实现拟合(即用一条直线来拟合数据集),此运行结果与多项式回归(当degree=1时)的运行结果是一样的。代码中的x_poly,当degree=1时,x_poly表示在原始数据前面加一列(原始数据的0次方),当degree=2时,在原始数据前面加一列和后面加一列(原始数据的平方);其他类推,后面加3次方、4次方、5次方……degree的数值越大,拟合的结果也就越好。
原始数据:
[[ 1.]
[ 2.]
[ 3.]
[ 4.]
[ 5.]
[ 6.]
[ 7.]
[ 8.]
[ 9.]
[10.]]
degree = 1:
[[ 1. 1.]
[ 1. 2.]
[ 1. 3.]
[ 1. 4.]
[ 1. 5.]
[ 1. 6.]
[ 1. 7.]
[ 1. 8.]
[ 1. 9.]
[ 1. 10.]]
degree = 2:
[[ 1. 1. 1.]
[ 1. 2. 4.]
[ 1. 3. 9.]
[ 1. 4. 16.]
[ 1. 5. 25.]
[ 1. 6. 36.]
[ 1. 7. 49.]
[ 1. 8. 64.]
[ 1. 9. 81.]
[ 1. 10. 100.]]
可以看到上方的代码画出的多项式拟合的曲线还是不够平滑,这是因为取的点太少的缘故,我们可以在区间内把区间划分为更多小区间,再用predict函数去画曲线,只需要把上方代码的画图部分修改一下即可,具体代码如下:
# 画图
plt.plot(x_data,y_data,'b.') #用蓝色的点把数据集表示出来
x_test = np.linspace(1,10,100) #linspace(a,b,c)表示划分区间[a,b],等分c份
x_test = x_test[:,np.newaxis] #设置x_test数组格式为一列
plt.plot(x_test,lin_reg.predict(poly_reg.fit_transform(x_test)),c = 'r')
plt.title('Truth or Bluff(Polynomial Regression)')
plt.xlabel('Position level')
plt.ylabel('Salary')
plt.show()在这里插入图片描述
最后画出来的结果如下,可以看见曲线更加平滑了。