多项式函数的拟合问题,说明过拟合与模型的选择问题

先看效果图,如果不是你想找的资料,请直接移步。

问题描述:假定一个训练数据集:T = {(x1,y1),(x2,y2),...,(xn,yn)},其中n=10。多项式拟合的任务是假设给定数据由M次多项式生成,选择最优可能生成这些数据的M次多项式函数,即在M次多项式函数中选择一个对已知数据及未知数据都有很好预测能力的函数。

解题思路:

(1)生成这10个数据点

(2)这10个数据点的可视化,判断大致的规律

(3)用sklearn拟合数据点

(4)评价

具体做法:

(1)生成这10个数据点:

我采用的是正弦型函数+高斯噪声来生成这10个数据点。

问题一:为什么要采用正弦型函数?

答:根据高数中的泰勒定理可知,任何n阶可导的函数,一定能写成多项式的和,正好正弦型函数n阶可导。

问题二:为什么要加高斯噪声?

答:如果不加高斯噪声,生成的数据就一定符合某个函数解析式,而且是完全相等(点就是由某个函数产生的),就没必要是拟合的问题了。

python代码:

#数据的产生
X = np.linspace(0,2*np.pi,10,endpoint=True)  #0到2pi上均匀产生10个数
Y = np.sin(X)
average = 0
sigma = 0.12
for i in range(X.size):
    X[i] += random.gauss(average,sigma)
    Y[i] += random.gauss(average,sigma)

产生的数据如下:

(-0.0086607015539967268, 0.046640267459409392)
(0.63988577452638629, 0.66763215333197345)
(1.5765394142915448, 1.0011937195346221)
(2.1469473903248719, 0.71407117620307103)
(2.7472844222665986, 0.25736883764300039)
(3.3797521471921779, -0.096798931131669264)
(4.1367221867677184, -0.75786232875251713)
(4.7842435861592172, -0.89872880432578006)
(5.5560623572294228, -0.54735342635385387)
(6.2845501538650312, -0.059034585898417841)

(2)这10个数据点的可视化,判断大致的规律

从一开始给出的那个图能轻易看出,数据点大致符合正弦型函数的规律,(这个是先有鸡还是先有蛋的问题),我们现在的角度是假设这个数据是别人直接给你的,你并不知道是用什么模型产生的。

(3)用sklearn拟合数据点

这里说一个比较“显而易见”的常识,1阶多项式可以完美拟合2个点,二阶多项式可以完美拟合3个点,以此类推,9阶多项式可以完美拟合10个点,所以我采用:M = [0,1,3,9],M为多项式的最高阶次数。

完整代码:

# -*- coding: utf-8 -*-
__author__ = 'wys'
import numpy as np
import matplotlib.pyplot as plt
from sklearn import linear_model
from sklearn.preprocessing import PolynomialFeatures
import random
"""
多项式函数的拟合问题,说明过拟合与模型的选择。
"""
#数据的产生
X = np.linspace(0,2*np.pi,10,endpoint=True)  #0到2pi上均匀产生10个数
Y = np.sin(X)
average = 0
sigma = 0.12
for i in range(X.size):
    X[i] += random.gauss(average,sigma)
    Y[i] += random.gauss(average,sigma)
fig = plt.figure(figsize=(10,6), facecolor = 'gray')
lenth = len(X)
x = np.array(X).reshape([lenth,1])
y = np.array(Y).reshape([lenth,1])
print("输入数据为10个2维坐标点(数据的产生是正弦函数 ""+高斯噪声):")
for x1,y1 in zip(x,y):
    print((x1[0],y1[0]))
M = [0,1,3,9]
print("M为多项式的最高次数:"+"M=",M)
intercept=[]
coef=[]
for i in range(1,5):
    ax1 = fig.add_subplot(2,2,i)
    plt.plot(X,Y,linestyle='',marker='.')
    for j in M:
        ploy_reg = PolynomialFeatures(degree=j)
        X_ploy = ploy_reg.fit_transform(x)
        lin_reg = linear_model.LinearRegression()
        lin_reg.fit(X_ploy,y)
        intercept.append(lin_reg.intercept_)
        coef.append(lin_reg.coef_)
        plt.plot(x,lin_reg.predict(ploy_reg.fit_transform(x)),color='blue',label='M='+str(j))
        plt.legend()
        M.pop(0)
        break
print("学习到的拟合函数截距(偏置系数)",intercept)
print("学习到的拟合函数参数(权重系数)",coef)
plt.legend()
print("绘图...")
plt.show()

程序执行的结果:

(4)评价

选择三阶多项式来拟合该数据相对比较好。

纯手打,点个赞呗!