【火炉炼AI】机器学习005-多项式回归器的创建和测试

【火炉炼AI】机器学习005-多项式回归器的创建和测试

(本文所使用的Python库和版本号: Python 3.5, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )

前面讲到了简单线性回归器和岭回归器,这两类回归器都是将数据集拟合成直线,但现实生活中,有很多情况,数据集的分布并不是简单的线性关系,还有可能是曲线关系,聚类关系,随机分布关系等,对于这些不同的数据集分布关系,需要使用不同的回归器来拟合。


1. 分析数据集

由于缺少数据集,我自己用代码生成了一些数据,数据的生成过程和(【火炉炼AI】机器学习003-简单线性回归器的创建,测试,模型保存和加载)类似,如下代码所示。

# 构建服从多项式回归特性的数据集
np.random.seed(37) # 使得每次运行得到的随机数都一样
x=np.arange(2,102) 
x_shift=np.random.normal(size=x.shape)
x=x+x_shift # 构建的x含有100个数,通过在整数点引入偏差得到

error=np.random.normal(size=x.shape)*800 # 构建噪音,*800是扩大噪音的影响
y=1.19*x*x+0.82*x+5.95+error
plt.scatter(x,y) # 可以查看生成的数据集的分布情况

dataset=[(i,j) for i,j in zip(x,y)]
from sklearn.model_selection import train_test_split
train_set,test_set=train_test_split(dataset,test_size=0.2,random_state=37)
X_train=np.array([i for (i,j) in train_set]).reshape(-1,1) # 后面的fit需要先reshape
y_train=np.array([j for (i,j) in train_set]).reshape(-1,1)
X_test= np.array([i for (i,j) in test_set]).reshape(-1,1)
y_test= np.array([j for (i,j) in test_set]).reshape(-1,1)
生成的数据集分布

########################小**********结###############################

1,数据集的构建可以采用在标准数据中引入误差的方式。

2,在回归或分类模型中,经常要将数据集映射到二维平面上,通过散点图的方式来查看数据集的空间分布,有了直观的初步印象后,才能选择更合适的回归或分类模型。

#################################################################


2. 简单线性回归器模型拟合数据集

图中显示的数据集好像服从线性关系,也好像服从多项式关系,对于这样的情况,可以先用简单线性回归器拟合得到回归模型,然后用测试集看看该模型的优劣。如下代码:

# 如果采用简单线性回归器进行拟合得到简单的拟合直线
from sklearn import linear_model
linear_regressor=linear_model.LinearRegression() # 创建线性回归器对象
linear_regressor.fit(X_train,y_train) # 使用训练数据集训练该回归器对象

# 查看拟合结果
y_predict=linear_regressor.predict(X_train) # 使用训练后的回归器对象来拟合训练数据
plt.figure()
plt.scatter(X_train,y_train,label='train_set')
plt.scatter(X_test,y_test,color='r',label='test_set')
plt.plot(X_train,y_predict,'-b',linewidth=3,label='fitted_line')
plt.legend()

# 用测试集看看该线性回归器模型的测试结果
y_predict_test=linear_regressor.predict(X_test)
import sklearn.metrics as metrics
print('简单线性回归器模型的评测结果----->>>')
print('均方误差MSE:{}'.format(
    round(metrics.mean_squared_error(y_predict_test,y_test),2)))
print('解释方差分:{}'.format(
    round(metrics.explained_variance_score(y_predict_test,y_test),2)))
print('简单线性回归器得到的直线方程为:y={:.3f}x+{:.3f}'
      .format(linear_regressor.coef_[0][0],linear_regressor.intercept_[0]))

-------------------------------------输---------出--------------------------------

简单线性回归器模型的评测结果----->>>
均方误差MSE:1906916.26
解释方差分:0.85
简单线性回归器得到的直线方程为:y=117.061x+-1924.904

--------------------------------------------完-------------------------------------

简单线性回归得到的拟合直线

########################小**********结###############################

1,使用简单线性回归器得到的模型在测试集上的MSE非常大,看来还有非常大的优化空间。

#################################################################


3. 采用多项式回归器

由于简单线性回归器模型在该数据集上的表现非常差,故而我们需要改进模型,所以尝试使用多项式回归器。

# 使用多项式回归器来对数据集进行拟合,得到多项式方程
from sklearn.preprocessing import PolynomialFeatures
polynomial=PolynomialFeatures(degree=2) # 构建多项式回归器对象
# degree是多项式的次数,此处初步的设置为2

X_train_transformed=polynomial.fit_transform(X_train)
# print(X_train_transformed) #transformed之后的数据是degree+1维
from sklearn import linear_model
poly_regressor=linear_model.LinearRegression() # 也是构建线性回归器
poly_regressor.fit(X_train_transformed,y_train) # 对多项式回归器进行训练

# 查看拟合结果
y_predict_polynomial=poly_regressor.predict(X_train_transformed) 
plt.figure()
plt.scatter(X_train,y_train,label='train_set')
plt.scatter(X_test,y_test,color='r',label='test_set')

# print(y_predict_polynomial.shape) #(80, 1)
plt.plot(X_train,y_predict_polynomial,'-b',linewidth=3,label='fitted_poly') 
# 上面的plot会产生很多条线。。。。。
plt.legend()

# 用测试集看看该线性回归器模型的测试结果
X_test_transformed=polynomial.fit_transform(X_test)
y_predict_test=poly_regressor.predict(X_test_transformed)
import sklearn.metrics as metrics
print('多项式回归器模型的评测结果----->>>')
print('均方误差MSE:{}'.format(
    round(metrics.mean_squared_error(y_predict_test,y_test),2)))
print('解释方差分:{}'.format(
    round(metrics.explained_variance_score(y_predict_test,y_test),2)))
print('得到的多项式方程为:y={:.3f}x^2+({:.3f}x)+{:.3f}'
      .format(poly_regressor.coef_[0][-1],
              poly_regressor.coef_[0][-2],
              poly_regressor.intercept_[0]))

-------------------------------------输---------出--------------------------------

多项式回归器模型的评测结果----->>>
均方误差MSE:525885.05
解释方差分:0.97
得到的多项式方程为:y=1.374x^2+(-22.187x)+487.664

--------------------------------------------完-------------------------------------

多项式回归得到的多条拟合直线

########################小**********结###############################

1,采用多项式回归器,首先需要将X特征向量经过fit_transform()函数转变到对应的维度,然后才能使用LinearRegression()对象的fit()进行训练。

2,虽然使用了多项式回归器进行拟合,但是得到的MSE仍然比较大,只是比线性回归器得到的MSE小一些而已。所以MSE这个指标是不是不靠谱?

3,从解释方差分上来看,多项式回归器对test set有了更大改进,数值为0.97

4,图中线条比较多,是因为19行plt.plot(X_train,y_predict_polynomial)绘制了多次所导致,我暂时没有明白为什么会plot多个线条 。

#################################################################


4. 对新数据进行预测

对于训练好的模型,不管是简单线性回归器还是稍复杂的多项式回归器,都要用来进行新数据的预测,下面我分别用这两个回归器预测一个新数据。

# 使用多项式回归器预测新的数据值
data_X=[[66]] # 需要计算的数据点 X值
print('用直线回归器得到的数值:{}'.format(linear_regressor.predict(data_X)))
print('用拟合直线计算的数值:{}'.format(
    linear_regressor.coef_[0][0]*data_X[0][0]+linear_regressor.intercept_[0]))

data_X_transormed=polynomial.fit_transform(data_X)
data_X_predict=poly_regressor.predict(data_X_transormed)
# print(poly_regressor.coef_, '\n',poly_regressor.intercept_)
print('用多项式回归器得到的数值:{}'.format(data_X_predict))
print('用多项式曲线计算的数值:{}'.format(
    poly_regressor.coef_[0][-1]*np.power(data_X[0][0],2)+
    poly_regressor.coef_[0][-2]*data_X[0][0]+
    poly_regressor.intercept_[0]))
# 两者数据相等,代表predict的确是按照这个曲线方程来计算的。

-------------------------------------输---------出--------------------------------

用直线回归器得到的数值:[[5801.09012059]]
用拟合直线计算的数值:5801.090120592645
用多项式回归器得到的数值:[[5010.58753529]]
用多项式曲线计算的数值:5010.587535291616

--------------------------------------------完-------------------------------------

########################小**********结###############################

1,由于模型不同,对新数据进行预测,得到的结果也不同,但是由于多项式回归器模型对于test set的解释方差分要大一些,故而我们认为本例中多项式回归器模型更好一些,故而对新数据预测的结果更可靠一些。

2,如果某些数据集并不是服从简单的二项式,可以增加PolynomialFeatures(degree=2) 中degree的数值大小来提高x的最高次,得到的模型可能会更准确一些,但是要防止模型对train set的过拟合。

#################################################################


注:本部分代码已经全部上传到(我的github)上,欢迎下载。

参考资料:

1, Python机器学习经典实例,Prateek Joshi著,陶俊杰,陈小莉译

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容