精华内容
下载资源
问答
  • 多项式回归

    万次阅读 多人点赞 2018-10-02 23:08:37
    多项式回归模型是线性回归模型的一种,此时回归函数关于回归系数是线性的。由于任一函数都可以用多项式逼近,因此多项式回归有着广泛应用。 直线回归研究的是一个因变量与一个自变量之间的回归问题,但在实际情况中...

    多项式回归

    多项式回归,回归函数是回归变量多项式的回归。多项式回归模型是线性回归模型的一种,此时回归函数关于回归系数是线性的。由于任一函数都可以用多项式逼近,因此多项式回归有着广泛应用。

    直线回归研究的是一个因变量与一个自变量之间的回归问题,但在实际情况中,影响因变量的自变量往往不止一个,例如:羊毛的产量受到绵羊体重、体长、胸围等影响,因此需要进行一个因变量与多个自变量间的回归分析,即多元回归分析。

    研究一个因变量与一个或多个自变量间多项式的回归分析方法,称为多项式回归(Polynomial Regression)。如果自变量只有一个时,称为一元多项式回归;如果自变量有多个时,称为多元多项式回归。在一元回归分析中,如果依变量y与自变量x的关系为非线性的,但是又找不到适当的函数曲线来拟合,则可以采用一元多项式回归。

    一元m次多项式回归方程为

    二元二次多项式回归方程为

     

    上图的数据,我们可以使用一元2次多项式来拟合,首先,一个标准的一元高阶多项式函数如下:

    m 表示多项式的阶数,x^{j}表示 x 的 j 次幂,w 则代表该多项式的系数。

    当我们使用上面的多项式去拟合散点时,需要确定两个要素,分别是:多项式系数 w 以及多项式阶数 m,这也是多项式的两个基本要素。当然也可以手动指定多项式的阶数m的大小,这样就只需要确定系数w的值了。得到以下公式:

    如何求解该公式呢?这里使用Scipy的方法。

    使用Scipy提供的最小二乘法函数得到最佳拟合参数:

    该方法:最小化一组方程的平方和(即可以用来实现最小二乘法) 

    import numpy as np
    from scipy.optimize import leastsq
    
    # 拟合数据集
    x = [4, 8, 12, 25, 32, 43, 58, 63, 69, 79]
    y = [20, 33, 50, 56, 42, 31, 33, 46, 65, 75]
    
    def fun(p, x):
        """
        定义想要拟合的函数
        """
        w0,w1 = p  #从参数p获得拟合的参数
        # 如果是二次多项式则:w0,w1,w2 = p ;return w0 + w1*x + w2*x*x  以此类推
        return w0 + w1*x
    
    def err(p, x, y):
        """
        定义误差函数
        """
        return fun(p,x) -y
    
    #定义起始的参数 即从 y = 1*x+1 开始,其实这个值可以随便设,只不过会影响到找到最优解的时间
    p0 = [1,1]   #p0 = [1,1,1]    w系数的个数[w0,w1,w2...]
    
    #将list类型转换为 numpy.ndarray 类型,最初我直接使用
    #list 类型,结果 leastsq函数报错,后来在别的blog上看到了,原来要将类型转
    #换为numpy的类型
    
    x1 = np.array(x)  
    y1 = np.array(y)
    
    xishu = leastsq(err, p0, args=(x1,y1))
    print(xishu[0])
    # xishu[0],即为获得的参数

    一般只要指定前三个参数就可以:

    • func 是我们自己定义的一个计算误差的函数,

    • x0 是计算的初始参数值

    • args 是指定func的其他参数

    通过实践后观察,上面实现1次多项式拟合(2次多项式,p0则需要3个值)但其效果都不是很好,所以下面修改代码尝试N(大于2)项拟合

    """
    	实现N次多项式拟合
    """
    def fit_func(p, x):
    	"""根据公式,定义 n 次多项式函数
    	"""
    	f = np.poly1d(p)   # 这里的np.poly1d函数是用来构造多项式使用的,默认格式为:ax**2+bx+c等,如:ax**3 + bx**2 + cx + d 以此类推
    	return f(x)
    
    def err_func(p, x, y):
    	"""残差函数(观测值与拟合值之间的差距)
    	"""
    	ret = fit_func(p, x) - y
    	return ret
    
    def n_poly(n):
    	"""n 次多项式拟合
    	"""
    	p_init = np.random.randn(n) # 生成 n 个随机数
    	parameters = leastsq(err_func, p_init, args=(np.array(x), np.array(y)))
    	return parameters[0]	# 返回多项式系数w0、w1、w2...
    
    k = n_poly(3)	# 与上面的二次多项式结果一致,只是公式顺序不同
    
    """绘制出 3,4,5,6,7, 8 次多项式的拟合图像
    """
    # 绘制拟合图像时需要的临时点
    x_temp = np.linspace(0, 80, 10000)
    # 绘制子图
    fig, axes = plt.subplots(2, 3, figsize=(15,10))
    
    axes[0,0].plot(x_temp, fit_func(n_poly(4), x_temp), 'r')
    axes[0,0].scatter(x, y)
    axes[0,0].set_title("m = 3")
    
    axes[0,1].plot(x_temp, fit_func(n_poly(5), x_temp), 'r')
    axes[0,1].scatter(x, y)
    axes[0,1].set_title("m = 4")
    
    axes[0,2].plot(x_temp, fit_func(n_poly(6), x_temp), 'r')
    axes[0,2].scatter(x, y)
    axes[0,2].set_title("m = 5")
    
    axes[1,0].plot(x_temp, fit_func(n_poly(7), x_temp), 'r')
    axes[1,0].scatter(x, y)
    axes[1,0].set_title("m = 6")
    
    axes[1,1].plot(x_temp, fit_func(n_poly(8), x_temp), 'r')
    axes[1,1].scatter(x, y)
    axes[1,1].set_title("m = 7")
    
    axes[1,2].plot(x_temp, fit_func(n_poly(9), x_temp), 'r')
    axes[1,2].scatter(x, y)
    axes[1,2].set_title("m = 8")
    plt.show()

    很简单,代码分为两部分,上面为主要的计算系数w的值,下面为直观查看每个次项拟合后的效果图,如下:

    可以清楚的看到当3次项(也就是m=3)时,效果还是一般,但从4次项(m=4)后,对于数据的拟合性就明显优于3次项了,当 m=8 时,曲线呈现出明显的震荡,这也就是线性回归实验中所讲到的过拟和(Overfitting)现象,后面再介绍如何解决这个问题。

    使用scikit-learn进行多项式拟合:

    对于一个二次多项式而言,我们知道它的标准形式为:y(x,w) = w_{0} + w_{1}x + w_{2}x^{2},但是,多项式回归其实相当于是线性回归的特殊形式(开头也提到)。例如,我们这里令x = x_{1}x^{2} = x_{2},那么原方程就转换为:y(x,w) = w_{0} + w_{1}x_{1} + w_{2}x_{2},这也就变成了多元线性回归。完成了一元高次多项式到多元一次项式之间的转换。(如下,看作将多元一次项合并为一个矩阵中线性求解

    举例说明,对于自变量向量 X 和因变量 y,如果 X

                          [[ 3]
              X  =     [-2]
                           [ 4]]

    则可以通过y = w_{0} + w_{1}x线性回归模型进行拟合。同样,如果对于一元二次多项式y(x,w) = w_{0} + w_{1}x + w_{2}x^{2},能得到x = x_{1}x^{2} = x_{2}构成的特征矩阵,即:

                                            [[ 3.  9.]
             X = \left [X X^{2} \right ] =       [-2.  4.]
                                             [ 4. 16.]]

    那么也就可以使用线性回归进行拟合了。

    所以这里有了一个方便的工具,scikit-learn 中,我们可以通过 PolynomialFeatures() 类自动产生多项式特征矩阵

    sklearn.preprocessing.PolynomialFeatures(degree=2, interaction_only=False, include_bias=True)

    • degree: 多项式次数,默认为 2 次多项式

    • interaction_only: 默认为 False,如果为 True 则产生相互影响的特征集。

    • include_bias: 默认为 True,包含多项式中的截距项。

    通过下面代码解决上面一样的问题:

    """
    	使用 PolynomialFeatures 自动生成特征矩阵
    """
    from sklearn.preprocessing import PolynomialFeatures
    
    x = np.array(x).reshape(len(x), 1) # 转换为列向量
    y = np.array(y).reshape(len(y), 1)
    
    poly_features = PolynomialFeatures(degree=2, include_bias=False)    # 特征矩阵模型构建用来多项式的特征矩阵
    poly_x = poly_features.fit_transform(x)    # 通过模型转换x数据
    
    """
        用线性回归拟合上面转换后的数据
    """
    from sklearn.linear_model import LinearRegression
    
    model = LinearRegression()
    model.fit(poly_x,y)		# 这里使用转换后的特征矩阵相当于将一元2次转换为二元一次
    # print(model.intercept_,model.coef_)
    
    """绘制拟合图像
    """
    x_temp = np.linspace(0, 80, 10000)
    x_temp = np.array(x_temp).reshape(len(x_temp),1)
    poly_x_temp = poly_features.fit_transform(x_temp)
    
    plt.plot(x_temp, model.predict(poly_x_temp), 'r')
    plt.scatter(x, y)
    plt.show()         # 得到的结果与上面用leastsq的二次项结果一致

    这里二次项的图(degree=2),若设置更高的次项3,4,5(degree=3,4,5),则可以得到上面leastsq方法相同的效果,只需要通过PolynomialFeatures方法生成对应次项的特征矩阵就行。

    评价指标

    可以使用前一篇文章提到的 平均绝对误差(MAE)、均方误差(MSE)等方法来衡量,具体可以使用sklearn中的以下两个方法:

    from sklearn.metrics import mean_absolute_error
    from sklearn.metrics import mean_squared_error

    2次多项式不一定比线性回归的效果好,需要根据具体的测试结果做决定,可以试试更高次的多项式回归预测 ,下面我们便来验证以一下。

    make_pipeline通道:

    通过实例化 make_pipeline 管道类,实现调用一次 fitpredict 方法即可应用于所有预测器。make_pipeline 是使用 sklearn 过程中的技巧创新,其可以将一个处理流程封装起来使用。 更详细的使用可以参考这里

    上面的多项式回归中,我们需要先使用 PolynomialFeatures 完成特征矩阵转换,再放入 LinearRegression 中。那么,PolynomialFeatures + LinearRegression 这一个处理流程,就可以通过 make_pipeline 封装起来使用。

    以下数据集并非上面的x,y,如下数据(将Year作为特征列train_x,Values为目标值train_y,且数据是按0.7比例分割为训练、测试集):

    """更高次多项式回归预测
    """
    from sklearn.pipeline import make_pipeline
    
    train_x = train_x.reshape(len(train_x),1)
    test_x = test_x.reshape(len(test_x),1)
    train_y = train_y.reshape(len(train_y),1)
    
    for m in [3, 4, 5]:
        model = make_pipeline(PolynomialFeatures(m, include_bias=False), LinearRegression())
        model.fit(train_x, train_y)
        pre_y = model.predict(test_x)
        print("{} 次多项式回归平均绝对误差: ".format(m), mean_absolute_error(test_y, pre_y.flatten()))
        print("{} 次多项式均方根误差: ".format(m), mean_squared_error(test_y, pre_y.flatten()))
        print("---")

    可以看到高次项的误差都比线性回归要低,而2次项则要高,所以对于模型均需要进行验证后使用。

    好了,上面介绍了 多项式回归的原理与Scipy实现、sklearn构建特征矩阵转为线性运算、Pipeline方便的通道运算、以及误差评判,但还有一个很重要的问题,那就是如何选择最佳的n次项?

    几次项才是最佳的选择?

    其实这个问题很简单,我们可以设置一个误差指标(MSE、MAE等),然后绘制增加次项后,预测结果的误差值图。观察图形来选择一个合适的次项点(类似肘部法则也可以作为参考):

    """
    	计算 m 次多项式回归预测结果的 MSE 评价指标并绘图
    """
    mse = [] # 用于存储各最高次多项式 MSE 值
    m = 1 # 初始 m 值
    m_max = 10 # 设定最高次数
    while m <= m_max:
        model = make_pipeline(PolynomialFeatures(m, include_bias=False), LinearRegression())
        model.fit(train_x, train_y) # 训练模型
        pre_y = model.predict(test_x) # 测试模型
        mse.append(mean_squared_error(test_y, pre_y.flatten())) # 计算 MSE
        m = m + 1
    
    # print("MSE 计算结果: ", mse)
    # 绘图
    plt.plot([i for i in range(1, m_max + 1)], mse, 'b')
    plt.scatter([i for i in range(1, m_max + 1)], mse)
    
    # 绘制图名称等
    plt.title("MSE of m degree of polynomial regression")
    plt.xlabel("m")
    plt.ylabel("MSE")
    plt.show()

    如上图,可以明显看到当次数为3时,误差指标已经趋近于平稳了,所以这里选择3最好,当次数项越多可能会出现过拟合的问题,模型的泛化能力会降低。

     

    参考文章:

    https://baike.baidu.com/item/%E5%A4%9A%E9%A1%B9%E5%BC%8F%E5%9B%9E%E5%BD%92/21505384?fr=aladdin

    https://blog.csdn.net/lanchunhui/article/details/50521648

    展开全文
  • 对于所有的线性回归模型(包括多项式回归),我们都可以用最小二乘法或者梯度下降法去求解,这两种算法各有利弊,其中: 对于最小二乘法来说,它是利用线性代数里求解矩阵方程的方法得到参数向量,不需要多次迭代,...

    多项式回归

    对于一个足够光滑的函数,由泰勒公式可知,我们可以用一个多项式对该函数进行逼近,而且随着多项式阶数的提高,拟合的效果会越来越好。
    多项式回归通常可写成下面的形式:

    其中u表示随机干扰项,α0~αk是待定参数。

    我们以下面模型为例,通过python编程实现最小二乘与梯度下降两种算法,并对结果进行可视化以更好地对它们进行比较。在这里插入图片描述

    最小二乘法

    假设有输入数据在这里插入图片描述
    在这里插入图片描述
    那么有在这里插入图片描述

    其中ei表示残差。最小二乘法的原则是选择合适的参数使得全部观察值的残差平方和最小,用数学语言描述就是:
    在这里插入图片描述
    由数学的微积分知识可知,函数的极值在其一阶导数等于零的点取得。于是可令
    在这里插入图片描述

    整理得
    在这里插入图片描述
    写成矩阵形式为

    简写成
    在这里插入图片描述
    其中
    在这里插入图片描述
    在这里插入图片描述

    那么可得参数向量的解为
    在这里插入图片描述
    逆矩阵的计算可以用线性代数中的高斯消元法,这里不作展开。

    梯度下降法

    在这里插入图片描述
    初始化一个噪声向量作为待训练的参数向量(通常从正态分布中取样)。
    在这里插入图片描述

    在这里插入图片描述
    其中在这里插入图片描述
    使用反向传播算法(基于链式法则)对参数向量求偏导,得
    在这里插入图片描述
    得到参数的梯度后,可利用梯度下降法对参数进行更新:
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201125223715667.png#pic_center)其中,小圆圈表示哈达玛乘积。
    其中,Learning_Rate是一个实数,表示参数更新的幅度,不同的学习率会影响收敛的速度以及收敛的效果,比如有时学习率过大,会导致梯度爆炸,参数更新到inf,或者学习率过小,参数无法更新等等,需要耐心的调参以达到最好的训练效果。

    编程实现及效果展示

    利用基于python的numpy库,我们可以轻松实现数据集的创建,矩阵方程的求解,同时利用numpy的广播机制,可以很方便地处理哈达玛乘积等张量的运算操作。
    同时要注意,利用梯度下降法进行求解时,如果创建的输入数据的数值比较大(比如几百或者几千)的时候,算法很容易产生梯度爆炸,这时候要对输入数据进行归一化再去训练参数向量,最后训练完成时,还要将参数向量乘以一个补偿因子来抵消对输入数据归一化产生的影响,具体的补偿因子取决于你的归一化技巧。
    接着,利用python优秀的绘图库matplotlib,我们可以很容易地对训练过程中记录的损失值进行可视化,同时也可以可视化两种算法得到的结果以进一步作比较。
    代码如下:

    import numpy as np
    from matplotlib import pyplot as plt
    from mpl_toolkits.mplot3d import Axes3D
    plt.rcParams['font.sans-serif']=['SimHei']#显示中文
    plt.rcParams['axes.unicode_minus']=False#显示负号
    
    #创建数据
    n  = 60
    xs = np.linspace(0,n,n)
    ys = 0.2*xs**(5/2) - 0.8*xs**(1/2)
    
    X = np.array([
        [n ,             np.sum(xs) ,    np.sum(xs**2) , np.sum(xs**3)],
        [np.sum(xs),     np.sum(xs**2) , np.sum(xs**3) , np.sum(xs**4)],
        [np.sum(xs**2) , np.sum(xs**3) , np.sum(xs**4) , np.sum(xs**5)],
        [np.sum(xs**3) , np.sum(xs**4) , np.sum(xs**5) , np.sum(xs**6)]
        ])
    
    Y = np.array(
        [np.sum(ys) , np.sum(xs*ys) , np.sum(xs**2*ys) , np.sum(xs**3*ys)]
        ).reshape(4,1)
    
    #基于最小二乘法
    w_hat   = np.linalg.solve(X,Y)  #求解矩阵方程
    y_hat_1 = w_hat[0] + w_hat[1]*xs + w_hat[2]*xs**2 + w_hat[3]*xs**3
    
    #基于反向传播和梯度下降法
    #归一化输入,否则输入太大,容易导致梯度爆炸
    X_ = X/X.max()
    Y_ = Y/Y.max()
    lr = 0.01
    steps = 3000
    losses = []
    W = 0.1*np.random.normal(size=(4,1),scale=1,loc=0)
    W_copy = W.copy()
    for step in range(steps):
        W -= lr*(X_.T)@(X_@W - Y_)
        loss = (np.sum((Y_ - X_@W)**2))/2
        losses.append(loss)
        print('Loss = ',loss)
    #补偿归一化
    make_up = Y.max()/X.max()
    W = W*make_up 
    y_hat_2 = W[0] + W[1]*xs + W[2]*xs**2 + W[3]*xs**3
    
    #绘图比较
    plt.subplot(1,2,1)
    plt.scatter(xs,ys,c='b')
    plt.plot(xs,y_hat_1,c='r')
    plt.title('最小二乘法')
    
    plt.subplot(1,2,2)
    plt.scatter(xs,ys,c='b')
    plt.plot(xs,y_hat_2,c='r')
    plt.title('反向传播以及梯度下降法')
    
    plt.show()
    
    #展示损失函数的变化
    plt.scatter(np.array(list(range(len(losses))))+1,losses,s=3) #size=3
    plt.xlabel('Step')
    plt.ylabel('Losses')
    plt.title('损失函数值随迭代周期的变化')
    plt.show()
    

    结果展示

    对比结果:
    在这里插入图片描述
    可见最小二乘法的拟合效果比梯度下降法要更好一些。

    损失曲线:
    在这里插入图片描述
    由损失曲线图可知,梯度下降算法在迭代到200次左右进入收敛。

    其他发现

    在这里插入图片描述
    由上图可看出,即使两个算法求得的参数向量相差巨大,但是它们都能较好地实现对输入数据的拟合!

    总结

    对于所有的线性回归模型(包括多项式回归),我们都可以用最小二乘法或者梯度下降法去求解,这两种算法各有利弊,其中:
    对于最小二乘法来说,它是利用线性代数里求解矩阵方程的方法得到参数向量,不需要多次迭代,也不需要调参,运算效率很高而且通常拟合效果很好,但缺点是系数矩阵并不总是可逆的,此时就需要调整系数矩阵,让它变得可逆,这样无疑会使得算法变得很复杂。
    对于梯度下降法,其优点是基于梯度对参数进行更新,所以该算法不会出现失效的情况,但缺点是需要解决由输入数据带来的梯度爆炸/消失以及参数训练过程中的过拟合/欠拟合等一系列问题,这些问题需要通过一些正则化技巧以及耐心的调参来解决,同时,该算法属于迭代算法,所以运算效率比较低。

    如果有什么问题,欢迎到评论区留言!!!

    展开全文
  • 多项式回归详解 从零开始 从理论到实践一、多项式回归的理解1.1、字面含义1.2、引申1.2.1、多项式回归二、sklearn的使用2.1、方法与属性2.2、实例应用2.2.1、拟合非线性关系2.2.2、处理特征之间的影响 一、多项式...

    一、多项式回归的理解

    上一章是对线性关系的建模。比如在线性回归中,会假设建筑物的楼层数和建筑物的高度是一个线性关系,20层楼是10层楼的两倍左右高,10层楼是5层楼的两倍左右高。(即便不是线性关系,但是近似线性关系,误差很小,即可以等同线性关系)

    然而在现实生活中,许多关系则几乎完全不是线性的,比如学生学习的时间和考试分数之间的关系,在60分及格分以上,考试每提高10分,所花的时间会越多(因为后面基本都是越来越难的题目,需要花更多时间练习,而不是每道题目难度一样)。

    多项式回归是线性回归的一种扩展,它可以使我们对非线性关系进行建模。线性回归使用直线来拟合数据,如一次函数 y = k x + b y=kx+b y=kx+b等。而多项式回归则使用曲线来拟合数据,如二次函数 y = a x 2 + b x + c y=ax^2+bx+c y=ax2+bx+c、三次函数 y = a x 3 + b x 2 + c x + d y=ax^3+bx^2+cx+d y=ax3+bx2+cx+d以及多次函数等来拟合数据。

    通过线性回归所不能解决的问题出发,由此来介绍多项式回归。

    参考1 一次函数与直线的关系
    参考2 线性函数 非线性函数 多项式函数


    1.1、字面含义

    多项式的理解:
    “多项式回归”由“多项式”和“回归”组成。

    “多项式”(polynomial)的含义:在数学中,多项式是指由若干个单项式(monomial)相加组成的代数式叫做多项式(若有减法:减一个数等于加上它的相反数)。

    多项式中的每个单项式叫做多项式的,这些单项式中的最高项次数,就是这个多项式的次数。单项式由单个或多个变量(一般为单个 x x x)和系数相乘组成,或者不含变量,即不含字母的单个系数(常数)组成,这个不含字母的项叫做常数项

    多项式函数:
    形如 f ( x ) = a n x n + a n − 1 x ( n − 1 ) + … + a 2 x 2 + a 1 x + a 0 f(x)=a_nx^n+a_{n-1}x^{(n-1)}+…+a_2x^2+a_1x+a_0 f(x)=anxn+an1x(n1)++a2x2+a1x+a0的函数,叫做多项式函数,它是由常数与自变量x经过有限次乘法与加法运算得到的。显然,当n=1时,其为一次函数 y = k x + b y=kx+b y=kx+b,当n=2时,其为二次函数。

    参考3 多项式
    参考4 整式
    参考5 多项式函数


    1.2、引申

    1.2.1、多项式回归

    有时直线难以拟合全部的数据,需要曲线来适应数据,如二次模型、三次模型等等。
    在这里插入图片描述
    一般情况下,数据的回归函数是未知的,即使已知也难以用一个简单的函数变换转化为线性模型,所以常用的做法是多项式回归(Polynomial Regression),即使用多项式函数拟合数据。

    次数的选择:
    多项式函数有多种,一般来说,需要先观察数据的形状,再去决定选用什么形式的多项式函数来处理问题。比如,从数据的散点图观察,如果有一个“弯”,就可以考虑用二次多项式;有两个“弯”,可以考虑用三次多项式;有三个“弯”,则考虑用四次多项式,以此类推。
    当然,如果预先知道数据的属性,则有多少个

    虽然真实的回归函数不一定是某个次数的多项式,但只要拟合的好,用适当的多项式来近似模拟真实的回归函数是可行的。

    多元线性回归比较复杂,如二元二次的线性回归函数,仅二元就很复杂了。
    y = β 0 + β 1 x 1 + β 2 x 2 + β 3 x 1 x 2 + β 4 x 1 2 + β 5 x 2 2 y=\beta_0+\beta_1x_1+\beta_2x_2+\beta_3x_1x_2+\beta_4x_1^2+\beta_5x_2^2 y=β0+β1x1+β2x2+β3x1x2+β4x12+β5x22

    所以主要通过一元多项式回归模型来理解回归算法,它的结构如下:
    y = β 0 + β 1 x + . . . + β n x n + ϵ y=\beta_0+\beta_1x+...+\beta_nx^n+\epsilon y=β0+β1x+...+βnxn+ϵ
    同样,假设有 p p p 个样本,它的矩阵形式为:
    y = X β + ϵ y=X\beta+\epsilon y=Xβ+ϵ
    其中: y = [ y 1 y 2 ⋮ y p ] y=\begin{bmatrix} y_1&\\ y_2&\\ {\vdots}&\\ y_p&\\ \end{bmatrix} y=y1y2yp X = [ 1 x 1 x 1 2 ⋯ x 1 n 1 x 2 x 2 2 ⋯ x 2 n ⋮ ⋮ ⋮ ⋱ ⋮ 1 x p x p 2 ⋯ x p n ] X=\begin{bmatrix} 1&{x_{1}}&{x_{1}^2}&{\cdots}&{x_{1}^n}\\ 1&{x_{2}}&{x_{2}^2}&{\cdots}&{x_{2}^n}\\ {\vdots}&{\vdots}&{\vdots}&{\ddots}&{\vdots}\\ 1&{x_{p}}&{x_{p}^2}&{\cdots}&{x_{p}^n}\\ \end{bmatrix} X=111x1x2xpx12x22xp2x1nx2nxpn β = [ β 0 β 1 β 2 ⋮ β n ] \beta=\begin{bmatrix} \beta_0&\\ \beta_1&\\ \beta_2&\\ {\vdots}&\\ \beta_n&\\ \end{bmatrix} β=β0β1β2βn ϵ = [ ϵ 0 ϵ 1 ϵ 2 ⋮ ϵ p ] \epsilon=\begin{bmatrix} \epsilon_0&\\ \epsilon_1&\\ \epsilon_2&\\ {\vdots}&\\ \epsilon_p&\\ \end{bmatrix} ϵ=ϵ0ϵ1ϵ2ϵp

    x 1 = x x_1=x x1=x x 2 = x 2 x_2=x^2 x2=x2 x 3 = x 3 x_3=x^3 x3=x3 x 4 = x 4 x_4=x^4 x4=x4
    原方程改写为 y = β 0 + β 1 x 1 + β 2 x 2 + β 3 x 3 + β 4 x 4 + β 5 x 5 y=\beta_0+\beta_1x_1+\beta_2x_2+\beta_3x_3+\beta_4x_4+\beta_5x_5 y=β0+β1x1+β2x2+β3x3+β4x4+β5x5
    于是有关线性回归的方法都可以使用了,也就是说,线性回归并不“知道” x 2 x^2 x2 x x x的二次变换,而是把它当做两一个变量来处理,只是为模型添加了特征而没有改变线性回归拟合模型的方式。

    由一元多项式回归模型的公式可以知道,只有一个自变量 x x x,但是 x x x 的级数(Degree) 不同。


    二、sklearn的使用

    多项式没有直接生成模型的方法,而是数据预处理效果,即:数据预处理(多项式特征)+线性模型。

    该方法在sklearn包中的preprocessing模块中
    class sklearn.preprocessing.PolynomialFeatures(degree=2, *, interaction_only=False, include_bias=True, order='C')


    2.1、方法与属性

    模型类函数的参数:

    参数取值说明
    degreeint, default=2多项式特征的次数
    interaction_onlybool, default=False如果为True,只生成交互特征,即不存在自己和自己相结合的特征项,如degree=2的2个特征属性 a a a b b b的数据进行多项式化,则没有 a 2 a^2 a2 b 2 b^2 b2这两个属性,只有 [ 1 , a , b , a b ] [1, a, b, ab] [1,a,b,ab]这四个属性
    include_biasbool, default=True表示有无 β 0 \beta_0 β0项。如果为True,则包含一列为1的偏差项,该列特征在多项式中的幂为0,在模型中充当截距。如interaction_only参数中的[1, a, b, ab]中的1,为False,则只有[a, b, ab]。
    order{‘C’, ‘F’}, default=‘C’在密集情况下,对输出数组进行控制的指令。'F’指令对于计算而更快,但是会减慢后续的拟合速度

    作用(两个):
    1 生成多项式
    2 生成交互特征。

    结果:
    生成一个含有新特征的矩阵,该矩阵由指定的少于或者等于degree的特征次数的多项式组合而组成。
    例如:
    输入为2个特征 [ a , b ] [a, b] [a,b]
    生成二次多项式特征,输出为6个特征 [ 1 , a , b , a 2 , a b , b 2 ] [1, a, b, a^2, ab, b^2] [1,a,b,a2,ab,b2]

    本质:
    不是像线性模型那样,直接构建多项式模型,而是数据预处理效果,即在生成模型前,提前将数据特征转变为多项式特征,所以达到即便是线性模型,还可以生成曲线。

    模型类的属性:

    参数输出值说明
    PolynomialFeature.powers_n维数组,形状(i, j)幂运算数组,根据degree的值而确定行,根据属性个数而确定列。degree=2、3分别对应6行和10行,2、3个属性就对应2列、3列,该矩阵与属性值数组进行计算而得出多项式结果
    PolynomialFeature.n_input_features_int, =j输入特征的总数,即属性个数,代表幂运算矩阵的列
    PolynomialFeature.n_output_features_int, =i输出特征的总数,即多项式化后,属性的个数,代表幂运算矩阵的行

    举例理解:

    from sklearn.preprocessing import PolynomialFeatures
    import numpy as np
    
    x = np.arange(6).reshape(3, 2)
    x
    """
    array([[0, 1],
           [2, 3],
           [4, 5]])
    """
    
    # 数据预处理,将有两列的数组,即有两个特征属性的数组进行多项式化,degree=2,多项式变成6个项
    plot = PolynomialFeatures(degree=2)
    
    # 查看该类的幂运算数组
    plot.powers_
    """
    array([[0, 0],
           [1, 0],
           [0, 1],
           [2, 0],
           [1, 1],
           [0, 2]], dtype=int64)
    """
    

    对于上面的幂运算数组:
    [ 0 , 0 ] [0, 0] [0,0] 表示 a 0 × b 0 = 1 a^0\times b^0=1 a0×b0=1
    [ 1 , 0 ] [1, 0] [1,0] 表示 a 1 × b 0 = a a^1\times b^0=a a1×b0=a
    [ 0 , 1 ] [0, 1] [0,1] 表示 a 0 × b 1 = b a^0\times b^1=b a0×b1=b
    [ 2 , 0 ] [2, 0] [2,0] 表示 a 2 × b 0 = a 2 a^2\times b^0=a^2 a2×b0=a2
    [ 1 , 1 ] [1, 1] [1,1] 表示 a 1 × b 1 = a b a^1\times b^1=ab a1×b1=ab
    [ 0 , 2 ] [0, 2] [0,2] 表示 a 0 × b 2 = b 2 a^0\times b^2=b^2 a0×b2=b2

    # 类属性,查看输入特征与输出特征
    plot.n_input_features_
    """
    2
    """
    
    plot.n_output_features_
    """
    6
    """
    
    # 幂运算矩阵与x进行运算,生成(i, j)即(6, 2)的数组
    x_plot = plot.fit_transform(x)
    x_plot
    """
    array([[ 1.,  0.,  1.,  0.,  0.,  1.],
           [ 1.,  2.,  3.,  4.,  6.,  9.],
           [ 1.,  4.,  5., 16., 20., 25.]])
    """
    

    按照幂运算数组的计算规则, x x x 的每一行代表 [ a , b ] [a, b] [a,b] 进行计算:

    # x
    array([[0, 1],
           [2, 3],
           [4, 5]])
    
    # 幂运算数组
    array([[0, 0],
           [1, 0],
           [0, 1],
           [2, 0],
           [1, 1],
           [0, 2]], dtype=int64)
    

    对于第一行 [ 0 , 1 ] [0, 1] [0,1],即:
    [ 0 0 × 1 0 , 0 1 × 1 0 , 0 0 × 1 1 , 0 2 × 1 0 , 0 1 + 1 1 , 0 0 + 1 2 ] = [ 1 , 0 , 1 , 0 , 0 , 1 ] [0^0\times1^0, 0^1\times1^0, 0^0\times1^1, 0^2\times1^0, 0^1+1^1, 0^0+1^2 ]=[1, 0, 1, 0, 0, 1] [00×10,01×10,00×11,02×10,01+11,00+12]=[1,0,1,0,0,1]
    后面的也类似这样计算。


    2.2、实例应用

    2.2.1、拟合非线性关系

    非线性关系拟合过程的理解

    将特征提升到某个幂次(二次方,三次方等)来创建新特征。模型添加的新特征越多,拟合的“线”就越灵活。

    以波士顿数据第一个属性为例:

    from sklearn.linear_model import LinearRegression
    from sklearn.datasets import load_boston
    from sklearn.preprocessing import PolynomialFeatures
    
    # 加载数据集,并只选取 1 个特征
    boston =load_boston()
    features = boston.data[:, 0:1]
    target = boston.target
    
    # 创建多项式特征
    polynomial = PolynomialFeatures(degree=3, include_bias=False)
    features_polynomial = polynomial.fit_transform(features)
    
    # 创建线性回归对象与实例
    linear = LinearRegression()
    model = linear.fit(features_polynomial, target)
    

    观察第一个样本,手动创建多项式特征

    # 由于参数设置degree=3,所以最高维3阶
    # 一阶不变
    features[0]
    "array([0.00632])"
    
    # 升到二阶
    features[0]**2
    "array([3.99424e-05])"
    
    # 升到三阶
    features[0]**3
    "array([2.52435968e-07])"
    

    观察PolynomialFeatures函数产生的多项式特征

    features_polynomial[0]
    "array([6.32000000e-03, 3.99424000e-05, 2.52435968e-07])"
    

    结果一样,三个特征 x x x x 2 x^2 x2 x 3 x^3 x3 都包含在特征矩阵中,然后进行线性回归,就构造出了一个多项式回归模型


    2.2.2、处理特征之间的影响

    有时,对某个特征变量的影响会取决于另一个特征。比如现实生活中冲咖啡的例子,有一组二元特征:是否加糖(sugar)和是否搅拌(stirred)。要预测某咖啡是否是甜的。如果只把糖加入咖啡(sugar=1, stirred=0)不会使咖啡变甜,所有糖沉在咖啡底部,只搅拌咖啡而不加糖(sugar=0, stirred=1)也不会让它变甜。加糖和搅拌对咖啡变甜的影响是相互依赖的。

    利用这种交互特征进行建模,可得到二元二次多项式函数,不过剔除了二次项:
    y ^ = β ^ 0 + β ^ 1 x 1 + β ^ 2 x 2 + β ^ 3 x 1 x 2 + ϵ \hat y=\hat\beta_0+\hat\beta_1x_1+\hat\beta_2x_2+\hat\beta_3x_1x_2+\epsilon y^=β^0+β^1x1+β^2x2+β^3x1x2+ϵ
    其中, x 1 x_1 x1 x 2 x_2 x2分别是sugar和stirred的值, x 1 x 2 x_1x_2 x1x2代表两者之间的相互作用。

    在类方法中的参数interaction_only,调整为True就表示生成交互特征。

    以波士顿房价的前两个属性为实例:

    from sklearn.linear_model import LinearRegression
    from sklearn.datasets import load_boston
    from sklearn.preprocessing import PolynomialFeatures
    
    # 加载数据集,并只选取 2 个特征
    boston =load_boston()
    features = boston.data[:, 0:2]
    target = boston.target
    
    # 创建交互特征
    interaction = PolynomialFeatures(degree=3, include_bias=False, interaction_only=True)
    features_interaction = interaction.fit_transform(features)
    
    # 创建线性回归对象与实例
    linear = LinearRegression()
    model = linear.fit(features_interaction, target)
    
    interaction.powers_
    """
    array([[1, 0],
           [0, 1],
           [1, 1]], dtype=int64)
    """
    

    第一个样本的交互特征

    features_interaction[0]
    """
    array([6.3200e-03, 1.8000e+01, 1.1376e-01])
    """
    

    手动计算交互特征

    features[0]
    """
    array([6.32e-03, 1.80e+01])
    """
    
    import numpy as np
    interaction_term = np.multiply(features[0, 0], features[0, 1])
    np.array([interaction_term])
    """
    array([0.11376])
    """
    
    np.concatenate((features[0], np.array([interaction_term])))
    """
    array([6.3200e-03, 1.8000e+01, 1.1376e-01])
    """
    

    结果相等


    2.2.3、多项式回归与不同degree的对比

    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn.preprocessing import PolynomialFeatures
    from sklearn.linear_model import LinearRegression
    
    # 创建训练集和测试集
    def f(x):
        return x * np.sin(x)
    x_plot = np.linspace(0, 10, 100)
    
    x = np.linspace(0, 10, 100)
    rng = np.random.RandomState(3)
    rng.shuffle(x)
    x = np.sort(x[:30])
    y = f(x)
    
    
    # 创建训练集X(30)和测试集X_plot(100)
    X = x[:, np.newaxis]
    X_plot = x_plot[:, np.newaxis]
    
    # 设置不同degree的颜色和线的样式
    colors = ['m', 'r', 'g']
    linestyles = ['-', '--', ':']
    
    fig = plt.figure(figsize=(15, 6))
    plt.plot(x_plot, f(x_plot), color='blue', linewidth=1, label='ground truth')
    plt.scatter(x, y, color='navy', s=10, marker='o', label='training points')
    
    
    for count, degree in enumerate([3, 4, 5]):
        polynomial = PolynomialFeatures(degree=degree, include_bias=False)
        train_polynomial = polynomial.fit_transform(X)
        test_polynomial = polynomial.fit_transform(X_plot)
    
        linear = LinearRegression()
        model = linear.fit(train_polynomial, y)
        y_plot = model.predict(test_polynomial)
        plt.plot(x_plot, y_plot, color=colors[count], linewidth=1, linestyle='-', label="degree %d" % degree)
        #plt.plot(1,2, linestyle='--')
        plt.legend(loc='lower left')
    plt.show()
    

    结果展示:
    在这里插入图片描述
    从图像可以看出,degree=3,图像有两个“弯”;degree=4,图像有3个“弯”,接近标准曲线;而degree=4时,图像也只有3个“弯”(已经是标答),且相对于degree=4的曲线偏上一点,也就是更接近标准曲线。

    可见阶数越高,曲线的弯曲形状越大,越接近函数曲线。



    展开全文
  • 文章目录一、多项式对数据的处理① 一维数据集简单案例 ---- (维度针对特征数而言)② 多维数据集案例 ---- (维度针对特征数而言)♦ 二维测试♦ 三维测试③ 多项式回归处理非线性问题④ 可视化二、多项式回归的可...


    一、多项式对数据的处理

    除了分箱之外,另一种更普遍的用于解决"线性回归只能处理线性数据"问题的手段,就是使用多项式回归对线性回归进行改进。这样的手法是机器学习研究者们从支持向量机中获得的:支持向量机通过升维可以将非线可分数据转化为线性可分,然后使用核函数在低维空间中进行计算,这是一种高维呈现,低维解释的思维。我们也可以让线性回归使用类似于升维的转换,将数据由非线性转换为线性,从而为线性回归赋予处理非线性数据的能力。
    在这里插入图片描述
    接下来,我们就来看看线性模型中的升维工具:多项式变化。这是一种通过增加自变量上的次数,而将数据映射到高维空间的方法,只要我们设定一个自变量上的次数(大于1),就可以相应地获得数据投影在高次方的空间中的结果,简单的举个例子说就是将二维数据转为三维、四维空间数据。这种方法可以非常容易地通过 sklearn中的PolynomialFeatures类来实现。

    注意区分:
    • 多项式变化是在高维呈现时进行,多项式核函数是在地位解释的时候进行
    • 类似于分箱,多项式变化也都是在原始数据集上进行处理,使得数据集能够实现线性回归拟合

    class sklearn.preprocessing.PolynomialFeatures(degree=2, *, interaction_only=False, 
                                                   include_bias=True, order='C')
    

    在这里插入图片描述

    from sklearn.preprocessing import PolynomialFeatures
    import numpy as np
    
    # 假设原始数据是一维的,经过转换成为2维
    x = np.arange(1,4).reshape(-1,1)
    print(x.ndim) # 2
    # [[1],
    #  [2],
    #  [3]]
    # 二次多项式,参数degree控制多项式的次方
    ploy = PolynomialFeatures(degree=2)
    # 接口transform直接调用,
    x_ = ploy.fit_transform(x)
    # [[1. 1. 1.],
    #  [1. 2. 4.],
    #  [1. 3. 9.]]
    
    ploy = PolynomialFeatures(degree=3)
    # 接口transform直接调用
    x__ = ploy.fit_transform(x)
    # [[ 1.  1.  1.  1.],
    #  [ 1.  2.  4.  8.],
    #  [ 1.  3.  9. 27.]]
    
    ploy = PolynomialFeatures(degree=4)
    # 接口transform直接调用
    x___ = ploy.fit_transform(x)
    # [[ 1.  1.  1.  1.  1.],
    #  [ 1.  2.  4.  8. 16.],
    #  [ 1.  3.  9. 27. 81.]]
    

    不难注意到,多项式变化后数据看起来不太一样了:首先,数据的特征(维度)增加了,这正符合我们希望的将数据转换到高维空间的愿望。其次,维度的增加是有一定的规律的。不难发现,如果我们本来的特征矩阵中只有一个特征x,而转换后我们得到:
    在这里插入图片描述
    这个规律在转换为二次多项式的时候同样适用。原本,我们的模型应该是形似y=ax+b的结构,而转换后我们的特征变化导致了模型的变化。根据我们在支持向量机中的经验,现在这个被投影到更高维空间中的数据在某个角度上看起来已经是一条直线了,于是我们可以继续使用线性回归来进行拟合。线性回归是会对每个特征拟合出权重w的,所以当我们拟合高维数据的时候,我们会得到下面的模型:
    在这里插入图片描述

    这就是大家会在大多数数学和机器学习教材中会看到的"多项式回归"的表达式。这个过程看起来非常简单,只不过是将原始的x上的次方增加,并且为这些次方项都加上权重w,然后增加一列所有次方为0的列作为截距乘数的x0,参数 include_bias就是用来控制x0的生成的

    返回顶部


    ① 一维数据集简单案例 ---- (维度针对特征数而言)

    # 原始数据集x
    x = np.arange(1,4).reshape(-1,1)
    # 对数据集进行多项式变化
    ploy = PolynomialFeatures(degree=3)
    xxx = ploy.fit_transform(x)
    # [[ 1.  1.  1.  1.],
    #  [ 1.  2.  4.  8.],
    #  [ 1.  3.  9. 27.]]
    
    # 生成数据集y
    rnd = np.random.RandomState(42)
    y = rnd.random(3)
    # [0.37454012 0.95071431 0.73199394]
    
    # 对x、y进行线性拟合
    result = LinearRegression().fit(xxx,y)
    
    # 查看生成的系数w
    print(result.coef_)
    # [-9.71445147e-16  2.48123876e-01  4.31857528e-01 -1.38217467e-01]
    # 查看生成的截距
    print(result.intercept_)
    # -0.1672238171928806
    

    在这里插入图片描述

    在这里结合多项式表达式我们可以看到,线性回归并没有把多项式生成的w0当作是截距项,因为对于程序而言只负责处理输入的数据,并没有指明哪一项数据是截距项。

    • 所以我们可以选择:关闭多项式回归中的 include_bias
    • 也可以选择:关闭线性回归中的 fit_intercept
    result1 = LinearRegression(fit_intercept=False).fit(xxx,y)
    print(result1.coef_)  # [-0.13619259  0.1912333   0.46288875 -0.14338934]
    print(result1.intercept_) # 0.0
    

    当我们关闭线性回归模型中的截距生成项的时候,从生成的W中选取一项为w0,并与x0相乘,然后加上没有生成的截距0。总体看来也就相当于将截距整合在了前面的w0、x0中了。

    返回顶部


    ② 多维数据集案例 ---- (维度针对特征数而言)

    在现实的生活中,处理一维数据是不现实的。更多的是处理多维(多特征)的数据集,这个时候,针对于一维的多项式转化规律已经不能完全适用了。

    ♦ 二维测试

    from sklearn.preprocessing import PolynomialFeatures
    import numpy as np
    
    x = np.arange(6).reshape(3,2)
    #[[0 1],
    # [2 3],
    # [4 5]]
    
    # 测试多项式转化 --- 二次多项式
    poly = PolynomialFeatures(degree=2).fit_transform(x)
    #[[ 1.  0.  1.  0.  0.  1.],
    # [ 1.  2.  3.  4.  6.  9.],
    # [ 1.  4.  5. 16. 20. 25.]]
    

    在这里插入图片描述

    ♦ 三维测试

    poly_ = PolynomialFeatures(degree=3).fit_transform(x)
    # [[  1.   0.   1.   0.   0.   1.   0.   0.   0.   1.],
    #  [  1.   2.   3.   4.   6.   9.   8.  12.  18.  27.],
    #  [  1.   4.   5.  16.  20.  25.  64.  80. 100. 125.]]
    

    在这里插入图片描述
    不难发现:当我们进行多项式转换的时候,多项式会产出到最高次数为止的所有低高次项比如如果我们规定多项式的次数为2,多项式就会产出所有次数为1和次数为2的项反馈给我们,相应的如果我们规定多项式的次数为n,则多项式会产出所有从次数为1到次数为n的项。注意,x₁x₂和x₁² 一样都是二次项,一个自变量的平方其实也就相当于是x₁x₁,所以在三次多项式中x₁²x₂就是三次项。

    在多项式回归中,我们可以规定是否产生平方或立方项,其实如果我们只要求高次项的话,x1x2会是一个比x₁²更好的高次项,因为x₁x₂和x₁之间的共线性会比x₁²与x1之间的共线性好那么一点点(只是一点点,虽然结果有时相同),而我们多项式转化之后是需要使用线性回归模型来进行拟合的,就算机器学习中不是那么在意数据上的基本假设,但是太过分的共线性还是会影响到模型的拟合。因此 sklearn中存在着控制是否要生成平方和立方项的参数 interactiononly默认为 False,以减少共线性。来看这个参数是如何工作的:

    # 测试多项式转化 --- 二次多项式
    poly = PolynomialFeatures(degree=2).fit_transform(x)
    #[[ 1.  0.  1.  0.  0.  1.],
    # [ 1.  2.  3.  4.  6.  9.],
    # [ 1.  4.  5. 16. 20. 25.]]
    poly_interaction_true = PolynomialFeatures(degree=2,interaction_only=True).fit_transform(x)
    # [[ 1.  0.  1.  0.], 
    #  [ 1.  2.  3.  6.], 
    #  [ 1.  4.  5. 20.]]
    

    通过对比可以发现,当参数interaction_only为True的时候,多项式转化只生成了交互项。这里所谓的交互项是指形如x₁x₁的多项式。

    随着原特征矩阵的维度上升,随着我们规定的最高次数的上升,数据会变得越来越复杂,维度越来越多,并且这种维度的增加并不能用太简单的数学公式表达出来。因此,多项式回归没有固定的模型表达式,多项式回归的模型最终长什么样子是由数据和最高次数决定的,因此我们无法断言说某个数学表达式"就是多项式回归的数学表达",因此要求解多项式回归不是一件容易的事儿。

    返回顶部


    ③ 多项式回归处理非线性问题

    • 首先使用线性回归进行一次拟合,之后便于和多项式回归拟合效果进行对比。
    # 设置随机种子数
    rnd = np.random.RandomState(42) # 设置随机种子数
    x = rnd.uniform(-3,3,size=100)
    y = np.sin(x) + rnd.normal(size=len(x)) / 3
    
    # 准备好数据集
    x = x.reshape(-1,1)
    
    # 创建测试数据集 x0 ---- 等差数列(均匀分布在训练集x的取值范围内的1000个点)
    line  =np.linspace(-3,3,1000,endpoint=False).reshape(-1,1)
    
    # 对原始数据进行拟合
    LinearR = LinearRegression().fit(x,y)
    score = LinearR.score(x,y) # 0.5361526059318595
    
    # 对测试数据集进行拟合效果的评分
    score_test = LinearR.score(line,np.sin(line)) # 0.6800102369793312
    
    • 使用多项式转化数据为高维后,在进行拟合
    # 多项式转化
    x_ = PolynomialFeatures(degree=5).fit_transform(x)
    line_ = PolynomialFeatures(degree=5).fit_transform(line)
    
    # 多项式训练数据集拟合
    LinearR_ = LinearRegression().fit(x_,y)
    x_score = LinearR_.score(x_,y) # 0.8561679370344799
    
    # 多项式测试数据集拟合
    line_score = LinearR_.score(line_,np.sin(line)) # 0.9868904451787983
    

    通过对比可以明显的发现,通过多项式回归,对于线性回归处理非线性数据的提升效果十分明显。

    返回顶部


    ④ 可视化

    # -*- coding: utf-8
    #  @Time    : 2021/1/19 11:34
    #  @Author  : ZYX
    #  @File    : Example13_多项式回归处理可视化.py
    # @software: PyCharm
    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn.linear_model import LinearRegression
    from sklearn.preprocessing import PolynomialFeatures
    
    # 设置随机种子数
    rnd = np.random.RandomState(42) # 设置随机种子数
    x = rnd.uniform(-3,3,size=100)
    y = np.sin(x) + rnd.normal(size=len(x)) / 3
    # 准备好数据集
    x = x.reshape(-1,1)
    # 创建测试数据集 x0 ---- 等差数列(均匀分布在训练集x的取值范围内的1000个点)
    line  =np.linspace(-3,3,1000,endpoint=False).reshape(-1,1)
    
    # 对原始数据进行拟合
    LinearR = LinearRegression().fit(x,y)
    
    # 多项式转化
    x_ = PolynomialFeatures(degree=5).fit_transform(x)
    line_ = PolynomialFeatures(degree=5).fit_transform(line)
    # 多项式训练数据集拟合
    LinearR_ = LinearRegression().fit(x_,y)
    
    # 放置画布
    fig,ax1 = plt.subplots(1)
    # 将测试数据代入predict接口,获得模型的拟合效果
    ax1.plot(line,LinearR.predict(line),linewidth=2,color='green',label='linear regression')
    ax1.plot(line,LinearR_.predict(line_),linewidth=2,color='red',label='Polynomial regression')
    # 绘制原数据集
    ax1.plot(x[:,0],y,'o',c='k')
    #其他图形选项
    ax1. legend(loc="best")
    ax1. set_ylabel("Regression output")
    ax1. set_xlabel("Input feature")
    ax1. set_title("Result before discretization")
    plt. tight_layout()
    plt. show()
    

    在这里插入图片描述


    d = 2
    在这里插入图片描述
    过低的高次项,会使得拟合没有明显的效果!


    d = 10
    在这里插入图片描述

    d = 20
    在这里插入图片描述
    过高的高次项会使得过拟合!


    从这里大家可以看出,多项式回归能够较好地拟合非线性数据,还不容易发生过拟合,可以说是保留了线性回归作为线性模型所带的“不容易过拟合和“计算快速”的性质,同时又实现了优秀地拟合非线性数据。

    返回顶部


    二、多项式回归的可解释性 < get_ feature_names() >

    线性回归是一个具有高解释性的模型,它能够对每个特征拟合出参数w以帮助我们理解每个特征对于标签的贡献程度。当我们进行了多项式转换后,尽管我们还是形成形如线性回归的方程,但随着数据维度和多项式次数的增加,对应的特征也变得异常复杂,我们可能无法一眼看出增维后的特征是由之前的什么特征组成的(之前我们都是肉眼可以直接进行判断)。不过,多项式回归的可解释性依然是存在的,我们可以使用接口get_ feature_names来调用生成的新特征矩阵的各个特征上的名称,以便帮助我们解释模型。来看下面的例子:

    import numpy as np
    from sklearn.preprocessing import PolynomialFeatures
    from sklearn.linear_model import  LinearRegression
    
    # 创建原始数据集
    x = np.arange(9).reshape(3,3)
    
    # 对数据集进行多项式转化
    poly = PolynomialFeatures(degree=5).fit(x)
    
    # 调用重要接口get_feature_names --- 获取高维特征的组合
    feature_names = poly.get_feature_names()
    '''
    ['1', 'x0', 'x1', 'x2', 'x0^2', 'x0 x1', 'x0 x2', 'x1^2', 'x1 x2', 'x2^2',
     'x0^3', 'x0^2 x1', 'x0^2 x2', 'x0 x1^2', 'x0 x1 x2', 'x0 x2^2', 'x1^3', 
     'x1^2 x2', 'x1 x2^2', 'x2^3', 'x0^4', 'x0^3 x1', 'x0^3 x2', 'x0^2 x1^2',
     'x0^2 x1 x2', 'x0^2 x2^2', 'x0 x1^3', 'x0 x1^2 x2', 'x0 x1 x2^2', 'x0 x2^3', 
     'x1^4', 'x1^3 x2', 'x1^2 x2^2', 'x1 x2^3', 'x2^4', 'x0^5', 'x0^4 x1', 'x0^4 x2',
     'x0^3 x1^2', 'x0^3 x1 x2', 'x0^3 x2^2', 'x0^2 x1^3', 'x0^2 x1^2 x2', 'x0^2 x1 x2^2',
     'x0^2 x2^3', 'x0 x1^4', 'x0 x1^3 x2', 'x0 x1^2 x2^2', 'x0 x1 x2^3', 'x0 x2^4', 
     'x1^5', 'x1^4 x2', 'x1^3 x2^2', 'x1^2 x2^3', 'x1 x2^4', 'x2^5']
    '''
    

    通过简单的数据集的应用,我们可以发现get_feature_names()返回的是线性回归拟合后的回归系数代表的特征组合,这样一来就很好的解释了某个ω的具体含义。

    下面我们使用加利福尼亚房屋价值数据集进一步探究:

    ① 读取加利福尼亚数据集

    # 分析处理加利福尼亚数据
    import pandas as pd
    from sklearn.datasets import fetch_california_housing as fch
    
    # 加载数据集
    house_value = fch()
    x = pd.DataFrame(house_value.data)
    y = house_value.target
    feature_name = house_value.feature_names
    # ['MedInc', 'HouseAge', 'AveRooms', 'AveBedrms', 'Population', 'AveOccup', 'Latitude', 'Longitude']
    

    返回顶部


    ② 多项式转化加利福尼亚数据集并进行解释

    # 使用多项式转化加利福尼亚数据集
    poly = PolynomialFeatures(degree=2).fit(x,y)
    name1 = poly.get_feature_names()
    '''
    ['1', 'x0', 'x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x0^2', 'x0 x1', 'x0 x2', 'x0 x3', 
    'x0 x4', 'x0 x5', 'x0 x6', 'x0 x7', 'x1^2', 'x1 x2', 'x1 x3', 'x1 x4', 'x1 x5', 'x1 x6', 
    'x1 x7', 'x2^2', 'x2 x3', 'x2 x4', 'x2 x5', 'x2 x6', 'x2 x7', 'x3^2', 'x3 x4', 'x3 x5', 
    'x3 x6', 'x3 x7', 'x4^2', 'x4 x5', 'x4 x6', 'x4 x7', 'x5^2', 'x5 x6', 'x5 x7', 'x6^2', 
    'x6 x7', 'x7^2']
    '''
    # 在get_feature_names中传入列名,结果就会显示出具体列名的组合
    name2 = poly.get_feature_names(feature_name)
    '''
    ['1', 'MedInc', 'HouseAge', 'AveRooms', 'AveBedrms', 'Population', 'AveOccup', 'Latitude', 
    'Longitude', 'MedInc^2', 'MedInc HouseAge', 'MedInc AveRooms', 'MedInc AveBedrms', 
    'MedInc Population', 'MedInc AveOccup', 'MedInc Latitude', 'MedInc Longitude', 
    'HouseAge^2', 'HouseAge AveRooms', 'HouseAge AveBedrms', 'HouseAge Population', 
    'HouseAge AveOccup', 'HouseAge Latitude', 'HouseAge Longitude', 'AveRooms^2', 
    'AveRooms AveBedrms', 'AveRooms Population', 'AveRooms AveOccup', 'AveRooms Latitude', 
    'AveRooms Longitude', 'AveBedrms^2', 'AveBedrms Population', 'AveBedrms AveOccup', 
    'AveBedrms Latitude', 'AveBedrms Longitude', 'Population^2', 'Population AveOccup', 
    'Population Latitude', 'Population Longitude', 'AveOccup^2', 'AveOccup Latitude', 
    'AveOccup Longitude', 'Latitude^2', 'Latitude Longitude', 'Longitude^2']
    '''
    

    返回顶部


    ③ 对转化高维数据进行线性回归拟合

    # 将数据转换为多项式特征
    x_ = poly.transform(x)
    # 构建线性回归模型,训练数据集x_
    reg = LinearRegression().fit(x_,y)
    # 获取 coef_ 回归系数
    coef = reg.coef_
    # 使用zip方法,将回归系数与特征对应
    point_coef = [*zip(name2,coef)]
    '''
    [('1', 5.919548140983327e-08), ('MedInc', -11.24302560111705), ('HouseAge', -0.8488985550865563),
     ('AveRooms', 6.441059400883809), ('AveBedrms', -31.591330845036552), ('Population', 0.00040609067821869747),
      ('AveOccup', 1.0038623251695358), ('Latitude', 8.705681915719547), ('Longitude', 5.880632747311831), 
      ('MedInc^2', -0.03130812100951305), ('MedInc HouseAge', 0.0018599475393629849), ('MedInc AveRooms', 0.0433020363878387), 
      ('MedInc AveBedrms', -0.18614228848200254), ('MedInc Population', 5.7283140110601324e-05), ('MedInc AveOccup', -0.0025901945074209877), 
      ('MedInc Latitude', -0.15250571869449078), ('MedInc Longitude', -0.14424294470380816), ('HouseAge^2', 0.00021172536249781818), 
      ('HouseAge AveRooms', -0.0012621898121656394), ('HouseAge AveBedrms', 0.010611503740612389), ('HouseAge Population', 2.8188531235643024e-06), 
      ('HouseAge AveOccup', -0.001817169463553861), ('HouseAge Latitude', -0.010069037408715655), ('HouseAge Longitude', -0.009999501833718248), 
      ('AveRooms^2', 0.0072694776...
    '''
    

    返回顶部


    ④ 利用多项式回归的可解释性找出重要特征

    • 主要就是将组合的特征转为DataFrame,在对其按照回归系数的比重进行排序。
    # 将对应结果转为DF,进行降序排序
    sort_coef = pd.DataFrame(point_coef,columns=['feature','coef']).sort_values(by="coef",ascending=False)
    ''' 主要是回归系数占比较大的前几个特征
    feature coef 
    [7: Latitude 8.705681915719547], 
    [3: AveRooms 6.441059400883809], 
    [8: Longitude 5.880632747311831], 
    [6: AveOccup 1.0038623251695358], 
    [30: AveBedrms^2 0.16018095673076496], 
    [43: Latitude Longitude 0.10810717328652852], 
    [28: AveRooms Latitude 0
    '''
    

    返回顶部


    三、探索多项式回归对于模型表现的提升

    import pandas as pd
    from time import time
    from sklearn.linear_model import LinearRegression
    from sklearn.datasets import fetch_california_housing as fch
    from sklearn.preprocessing import PolynomialFeatures
    from sklearn.ensemble import RandomForestRegressor as RFR
    
    # 读取数据集
    house_value = fch()
    x = pd.DataFrame(house_value.data)
    y = house_value.target
    
    # 将数据集进行多项式转化
    poly = PolynomialFeatures(degree=4).fit(x,y)
    x_ = poly.transform(x)
    
    # 对原始数据进行线性回归进行拟合
    reg = LinearRegression().fit(x,y)
    # 获取R2指数
    score = reg.score(x,y) # 0.6062326851998051
    
    # 对多项式化数据集进行线性回归拟合
    reg_ = LinearRegression().fit(x_,y)
    # 获取R2指数
    score_ = reg_.score(x_,y) # 0.7451596609109877
    # 查看解释
    point = poly.get_feature_names(house_value.feature_names)
    coef = reg_.coef_
    combine = [*zip(point,coef)]
    sort_coef = pd.DataFrame(combine,columns=['features','coef']).sort_values(by='coef')
    

    可以发现,对于非线性数据集,在使用了多项式回归处理后,其效果会有很大的提升。从原本的0.606提升至了0.745,说明多项式回归在某种意义上能够有效的解决非线性数据集问题。

    # 对比:使用随机森林回归非线性模型进行处理
    time0 = time()
    RFR_score = RFR(n_estimators=100).fit(x,y).score(x,y) # 0.9741543756049823
    print("time:{}".format(time()-time0))
    # time:11.149184942245483
    
    # 对多项式化数据集进行线性回归线性模型处理
    time0 = time()
    reg_ = LinearRegression().fit(x_,y)
    # 获取R2指数
    score_ = reg_.score(x_,y) # 0.7451596609109877
    print("time:{}".format(time()-time0)) # time:0.7400212287902832
    

    与此同时,我们使用随机森林回归,预设定生成100棵树,然后对原始数据集进行回归拟合,其效果达到了0.974。但是同时,与其高度的拟合效果所相反的就是它耗费了大量的时间。我们可以看到,使用多项式回归后的线性回归拟合用时0.75秒左右,而随机森林回归的用时是11.15秒左右,约为15倍。在实际的应用过程中,一般来说需要运行较为快的,但是不排除精确结果情况,所以需要根据具体的需求,对模型进行适当的选择。

    返回顶部


    四、多项式回归属于线性模型?还是非线性模型

    对于普通的非线性而言,就是我们拟合的数据结果中,不含有高次自变量。单从这一个角度以及如下公式来看,多项式回归属于非线性模型无疑。
    在这里插入图片描述
    在这里插入图片描述


    在这里插入图片描述


    返回顶部


    展开全文
  • 一个简单的方法就是将每一个特征的幂次方添加为一个新的特征,然后在这个拓展的特征集上进行线性拟合,这种方法成为多项式回归。回归分析的目标是根据自变量(或自变量向量)x 的值来模拟因变量 y 的期望值。在简单...
  • 1,什么是线性 ...接下来我们看看线性回归模型改进的核心之一:帮助线性回归解决非线性问题。 1.1,变量之间的线性关系 ”线性“这个词用于描述不同事物时有着不同的含义。我们最常使用的线性是指“变量
  • 凌云时刻 · 技术导读:在前面的笔记中,我们使用的样本数据都是具有一定线性关系的,我们使用简单线性回归或者多元线性回归来拟合这些数据。但是这种具有强假设的数据集在实际应用中是比较少的,大...
  • 如果一个方程,自变量的指数大于1,那么所有拟合这个方程的点就符合多项式回归多项式回归有个很重要的因素就是指数(degree)。如果我们发现数据的分布大致是一条曲线,那么很可能符合多项式回归,但是我们不知道...
  • 多项式回归 扩展可能是假设某些多项式函数, 同样,在标准线性模型方法(使用GLM的条件正态分布)中,参数可以使用最小二乘法获得,其中在。 即使此多项式模型不是真正的多项式模型,也可能仍然是一个很好的...
  • 一、线性回归与多项式回归 上一篇对于Y=2x1−3x2+4x3−5Y=2x_1-3x_2+4x_3-5Y=2x1​−3x2​+4x3​−5函数进行了拟合,如果函数对于Y=2t4−3t3+4t2−5Y=2t^4-3t^3+4t^2-5Y=2t4−3t3+4t2−5该如何拟合?{x1=t4x2=t3x3=...
  • Topic:关于多项式正则化问题Description:对历届奥运会男子自由泳100米取胜时间数据进行拟合Environment:Win 10 + matlab 2015Date:2018.10.18-19 by hw_Chen(需要程序和数据集的朋友可以私聊Q:1621673079,并备注...
  • 多元线性回归 上一个博客 我们说了一元线性回归,那么来看一下多元线性回归 一元函数的公式是 而多元函数的公式: 其实就是相当于位置参数的变量都增多了,我们的解决办法依旧可以使用我们一元线性回归当中的代价...
  • 回归问题-多项式回归

    2019-07-22 12:00:27
    多项式回归(Polynomial Regression) 区分一下多元回归与多项式回归的区别: 多元回归可以分为:多元线性回归和多元非线性回归,多元回归指的是:一个因变量(y)与多个自变量(,)之间的关系。其中若y与,之间...
  • 曲线回归------(二)多项式回归

    千次阅读 2018-09-04 21:45:54
    一、多项式回归方程 (1)多项式回归方程式 当两个变数间的曲线关系很难确定时,可用多项式逼近 ,称多项式回归(polynomial regression)。 最简单的多项式是二次多项式,方程为: 三次多项式方程为: 具有两...
  • 文章目录多项式回归介绍多项式回归基础实现二次多项式拟合实现N次多项式拟合 多项式回归介绍 前面我们拟合直线用到了线性回归,而非线性回归中,则需要建立因变量和自变量之间的非线性关系。从直观上讲,也就是拟合...
  • 四、一元线性回归 1. 预测函数 输入 输出 0 1 1 3 2 5 3 7 4 9 … … 预测函数为:y=1+2xy=1+2xy=1+2x 预测:输入10;输出21 y=w0+w1xy=w_0+w_1xy=w0​+w1​x,任务就是寻找预测函数中的...
  • 1.线性回归参数求解一般的线性模型,等式如下所示:ŷ是预测值。n是特征的数量。xi是第i个特征值。θj是第j个模型参数(包括偏置项θ0和特征权重θ1,θ2,...,θn)。这可以使用向量的形式写得更简洁:θ是模型的...
  • 我们可以使用线性回归模型来拟合数据,然而,在现实中,数据未必总是线性(或接近线性)的。当数据并非线性时,直接使用LinearRegression的效果可能会较差,产生欠拟合。 import numpy as np import matplotlib as...
  • 文章目录多项式回归(波士顿房价预测)导入模块获取数据训练模型报告决定系数可视化 多项式回归(波士顿房价预测) 导入模块 import pandas as pd import numpy as np import matplotlib.pyplot as plt from matplotlib...
  • 通过本篇文章你可以学习到:1、可视化数据集的重要特征2、估计回归模型的系数3、使用RANSAC拟合高鲁棒性回归模型4、如何来评价回归模型5、多项式回归6、决策树回归7、随机森林回归数据集下载地址:...
  • 面板平滑转移回归(PSTR)分析案例实现 3.matlab中的偏最小二乘回归(PLSR)和主成分回归(PCR) 4.R语言泊松Poisson回归模型分析案例 5.R语言回归中的Hosmer-Lemeshow拟合优度检验 6.r语言中对LASSO回归,Ridge岭回归...
  • 在上一篇文章中笔者详细的介绍了什么是线性回归以及一个典型的应用场景,同时还介绍了如何通过开源的sklearn来搭建一个简单的线性回归模型,使得对于线性回归的核心思想有了一定的掌握。接下来,笔记继续带领读者来...
  • 核平滑方法——局部多项式回归

    千次阅读 多人点赞 2020-05-31 14:31:25
    1. 核平滑方法 代码实现 2. 局部多项式回归 2.1 加权最小二乘法(Weighted least squares) 2.2 局部多项式回归(Local polynomial kernel regression) 代码实现
  • scikit-learn : 线性回归,多元回归,多项式回归

    万次阅读 多人点赞 2016-06-17 23:36:53
    使用scikit-learn学习线性回归,多元回归,多项式回归
  • 文章目录书山有路勤为径,学海无涯苦作舟(行行代码要手敲)零、吃水不忘挖井人一、回归1.1回归的定义1.2线性回归 书山有路勤为径,学海无涯苦作舟(行行代码要手敲) 零、吃水不忘挖井人 原文链接 一、回归 1.1...
  • Topic:关于多项式正则化问题 Description:对历届奥运会男子自由泳100米取胜时间数据进行拟合 Environment:Win 10 + matlab 2015 Date:2018.10.18-19 by hw_Chen (PS:需要程序和数据集的朋友可以私聊Q:...
  • 特征和多项式回归

    2019-06-08 23:15:33
    人工智能 个人学习笔记(不定时更新) ... 得到一个特征房子面积大小,上面两个方式都可以应用到线性回归模型,也即可以自由徐选择使用什么特征,并通过设计不同的特征,能够用更复杂的函数拟...
  • 1.多项式回归模型 2.训练多项式回归模型 3.学习曲线 4.偏差/方差权衡 一、线性回归 1.线性模型 概括地说, 线性模型 就是对输入特征加权求和,再加上一个偏置项(也称为截距项)的常数,以此进行预测。 线性...
  • pytorch实现多项式回归

    2021-04-06 11:41:09
    一元线性回归模型虽然能拟合出一条直线,但精度依然欠佳,拟合的直线并不能穿过每个点,对于复杂的拟合任务需要多项式回归拟合,提高精度。多项式回归拟合就是将特征的次数提高,线性回归的次数使一次的,实际我们...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 10,995
精华内容 4,398
关键字:

多项式回归模型公式