1. 程式人生 > >PRML之多項式曲線擬合

PRML之多項式曲線擬合

給定⼀個訓練集。這個訓練集由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

#分別在prmlfeatureslinear資料夾下,需要自行下載,我會在文末給出github地址

#特徵生成

fromprml.featuresimport PolynomialFeatures

fromprml.linearimport (

   LinearRegressor,

    RidgeRegressor,

   BayesianRegressor

)

np.random.seed(1234)

PolynomialCurve Fitting

deffunc, sample_size, std):
= np(1= func(x)  nprandomnormalscale
std, 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([0139
    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.51.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()