您的位置:首页 > 编程语言 > Python开发

PRML之多项式曲线拟合

2017-11-27 18:53 357 查看
给定⼀个训练集。这个训练集由x的N次观测组成,写作x≡ (x1,…,xN)T,伴随这对应的t的观测值,记作t≡ (t1,…,tN)T。图1展⽰了由N = 10个数据点组成的图像。图中的输⼊数据集合x通过选择xn(n= 1,...,N)的值来⽣成。这些xn均匀分布在区间[0,1],⽬标数据集t的获得⽅式是:⾸先计算函数sin(2πx)的对应的值,然后给每个点增加⼀个⼩的符合⾼斯分布的随机噪声,从⽽得到对应的tn的值。通过使⽤这种⽅式产⽣数据。

需要导入的模块如下

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
 
#分别在prml的features,linear文件夹下,需要自行下载,我会在文末给出github地址
#特征生成
fromprml.featuresimport PolynomialFeatures
fromprml.linearimport (
   LinearRegressor,
    RidgeRegressor,
   BayesianRegressor
)
 
np.random.seed(1234)

PolynomialCurve Fitting

def func, sample_size, std):

= np(1= func(x)  nprandomnormalscalestd, size.)return 

def (x

     npsin( * np*,=100.25)

x_test  nplinspace0, , =.(,"none", edgecolor,=="training data"

pltplotx_test y_test, c=="$\sin(2\pi x)$"

pltlegend

pltshow




图1:由N = 10个数据点组成的训练集的图像,⽤蓝⾊圆圈标记。每个数据点由输⼊变量x的观测以及对应的⽬标变量t组成。绿⾊曲线给出了⽤来⽣成数据的sin(2πx)函数。我们的⽬标是对于某些新的x值,预测t的值,⽽⽆需知道绿⾊曲线。

多项式函数:



其中M是多项式的阶数(order),xj表⽰x的j次幂。多项式系数w0,...,wM整体记作向量w。 注意,虽然多项式函数y(x,w)是x的⼀个⾮线性函数,它是系数w的⼀个线性函数。类似多项式函数的这种关于未知参数满⾜线性关系的函数有着重要的性质,被叫做线性模型,

选择多项式的阶数M也是⼀个问题。这是⼀个被称为模型对⽐ (modelcomparison)或者模型选择(modelselection)的重要问题的⼀个特例。在图2中,我 们给出了4个拟合多项式的结果。多项式的阶数分别为M = 0,1,3,9,数据集是图1所⽰的数据。


in([0 1 3 9

    plt(2+ )

    feature     X_train .transformx_train

= feature()

= LinearRegressor()

    model(,    y .predictX_test

 

    plt(,"none", edgecolor,=="training data"

    plt(,"g", label).plotx_test y, c,=).ylim-1.5 1.5

    plt(<span lang="EN-US" style="" font-size:"="">"M=<span lang="EN-US" font-size:10.5pt;font-family:"courier="" new";"="">{}"formatdegree xy(-1.(=,),=0..()<span lang="EN-US" style="" font-size:10.5pt;"="">


 


  图2:不同阶数的多项式曲线,⽤红⾊曲线表⽰,拟合了图1中的数据集。

从图中我们可以看出M=0和M=1拟合效果很差,我们称之为欠拟合,M=3拟合看起来和真实 的曲线差不多,但是当M=9的时候,拟合曲线激烈震荡,我们称之为过拟合。如此看来,曲线拟合的泛化性和M的取值有直接的关系,而M得值我们称之为模型特征个数,比如说房子的价格和房子面积有关系,和房子方向(南北向)有关系,那么面积是房子价格数学模型中的一个特征,房子方向也是一个特征。

为了定量考察泛化性和M之间的关系,我们额外考虑一个测试集,这个测试集由100个数据 点组成,这100个数据点的生成方式与训练集的生成方式完全相同,但是在目标值中包含的随机噪声的值不同。对于每个不同的M值,用根均方(RMS)来表示测试误差:



defrmse(a, b):

    return np.sqrt(np.mean(np.square(a- b)))

 

training_errors= []

test_errors= []

 

#不同M下拟合曲线的测试误差与训练误差

for i inrange(10):

    feature = PolynomialFeatures(i)

    X_train = feature.transform(x_train)

    X_test = feature.transform(x_test)

 

    model = LinearRegressor()

    model.fit(X_train, y_train)

    y = model.predict(X_test)

    training_errors.append(rmse(model.predict(X_train), y_train))

    test_errors.append(rmse(model.predict(X_test), y_test + np.random.normal(scale=0.25, size=len(y_test))))

 

plt.plot(training_errors,'o-', mfc="none", mec="b", ms=10, c="b", label="Training")

plt.plot(test_errors,'o-', mfc="none", mec="r", ms=10, c="r", label="Test")

plt.legend()

plt.xlabel("degree")

plt.ylabel("RMSE")

plt.show()


 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息