1. 程式人生 > >線性迴歸原理和實現基本認識

線性迴歸原理和實現基本認識

一:介紹

 定義:線性迴歸在假設特證滿足線性關係,根據給定的訓練資料訓練一個模型,並用此模型進行預測。為了瞭解這個定義,我們先舉個簡單的例子;我們假設一個線性方程 Y=2x+1, x變數為商品的大小,y代表為銷售量;當月份x =5時,我們就能根據線性模型預測出 y =11銷量;對於上面的簡單的例子來說,我們可以粗略把 y =2x+1看到迴歸的模型;對於給予的每個商品大小都能預測出銷量;當然這個模型怎麼獲取到就是我們下面要考慮的線性迴歸內容;並且在現實中影響銷量(y)的因素好有很多,我們就拿商品大小(x₁),商品價格為例 (x₂)為例:

      在機器學習之前,獲取資料是第一步(無米難巧婦之炊),假定我們的樣本如下:其中x1 為商品的大小,x2 為商品的價格,y 為商品的銷量;

   

二 :模型推導

        為了推導模型,在假設資料滿足線性模型條件下,可以設定線性模型為;x1特徵為商品的大小,X2特徵為商品的價格;

         

       模型假定好後,我們把訓練資料代入上面的設定模型中,可以通過模型預測一個樣本最終值;

         

      然後樣本真實值 y 和模型訓練預測的值之間是有誤差 ε ,再假設訓練樣本的資料量很大的時候,根據中心極限定律可以得到   ∑ε   滿足 (u ,δ²)高斯分佈的;由於方程有截距項 ,故使用可以 u =0; 故滿足(0,δ²)的高斯分佈;

  

如上面可知,對於每一個樣本 x ,代入到 p (y |x ;θ) 都會得到一個y 的概率;又因為設定樣本是獨立同分布的;對其求最大似然函式:


對其化簡如下:


以上就得到了迴歸的損失函式最小二乘法的公式,對於好多介紹一般對線性迴歸的線性損失函式就直接給出了上面的公式二乘法。下面我們就對上面做了階段性的總結:線性迴歸,根據大數定律和中心極限定律假定樣本無窮大的時候,其真實值和預測值的誤差ε 的加和服從u=0,方差=δ²的高斯分佈且獨立同分布,然後把ε =y-Øx 代入公式,就可以化簡得到線性迴歸的損失函式;

    第二步:對損失函式進行優化也就是求出w,b,使的損失函式最小化;第一種方法使用矩陣(需要滿足可逆條件)

 以上就是按矩陣方法優化損失函式,但上面方法有一定的侷限性,就是要可逆;下面我們來說一說另外一個優化方法 梯度下降法;對於梯度下降法的說明和講解資料很多,深入的講解這裡不進行,可以參考:http://www.cnblogs.com/ooon/p/4947688.html這篇部落格,博主對梯度下降方法進行了講解,我們這裡就簡單的最了流程解說;


總體流程就如上所示,就是求出每個變數的梯度;然後順著梯度方向按一定的步長a,進行變數更新;下面我們就要求出每個變數的梯度,下面對每個θ進行梯度求解公式如下:


如上我們求出變數的梯度;然後迭代代入下面公式迭代計算就可以了:


上面每次更新變數,都要把所有的樣本的加起來,資料量大的時候效率不高,下面還有一種就是按單個樣本進行優化,就是隨機梯度下降:


按上面優化步驟就可以求出w,b,就可以獲得優化的特徵方程:說這麼多先上個程式碼:

#!/usr/bin/python
# -*- coding:utf-8 -*-

import numpy as np
import warnings
from sklearn.exceptions import  ConvergenceWarning
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression,RidgeCV,LassoCV,ElasticNetCV
import matplotlib as mpl
import matplotlib.pyplot as plt

if __name__ == "__main__":

    warnings.filterwarnings(action='ignore', category=ConvergenceWarning)
    np.random.seed(0)
    np.set_printoptions(linewidth=1000)
    N = 9
    x = np.linspace(0, 6, N) + np.random.randn(N)
    x = np.sort(x)
    y = x**2 - 4*x - 3 + np.random.randn(N)
    x.shape = -1, 1
    y.shape = -1, 1
    p =Pipeline([
        ('poly', PolynomialFeatures()),
        ('linear', LinearRegression(fit_intercept=False))])
    mpl.rcParams['font.sans-serif'] = [u'simHei']
    mpl.rcParams['axes.unicode_minus'] = False
    np.set_printoptions(suppress=True)
    plt.figure(figsize=(8, 6), facecolor='w')
    d_pool = np.arange(1, N, 1)  # 階
    m = d_pool.size
    clrs = []  # 顏色
    for c in np.linspace(16711680, 255, m):
        clrs.append('#%06x' % c)
    line_width = np.linspace(5, 2, m)
    plt.plot(x, y, 'ro', ms=10, zorder=N)
    for i, d in enumerate(d_pool):
        p.set_params(poly__degree=d)
        p.fit(x, y.ravel())
        lin = p.get_params('linear')['linear']
        output = u'%s:%d階,係數為:' % (u'線性迴歸', d)
        print output, lin.coef_.ravel()
        x_hat = np.linspace(x.min(), x.max(), num=100)
        x_hat.shape = -1, 1
        y_hat = p.predict(x_hat)
        s = p.score(x, y)
        z = N - 1 if (d == 2) else 0
        label = u'%d階,$R^2$=%.3f' % (d, s)
        plt.plot(x_hat, y_hat, color=clrs[i], lw=line_width[i], alpha=0.75,label=label, zorder=z)
        plt.legend(loc='upper left')
        plt.grid(True)
       # plt.title('線性迴歸', fontsize=18)
        plt.xlabel('X', fontsize=16)
        plt.ylabel('Y', fontsize=16)
    plt.show()
執行程式碼後可見列印控制檯資訊如下:

影象顯示如下:


從上面影象可以看出,當模型複雜度提高的時候,對訓練集的資料擬合很好,但會出現過度擬合現象,為了防止這種過擬合現象的出現,我們在損失函式中加入了懲罰項,根據懲罰項不同分為以下:


最後一個為Elastic Net 迴歸,把 L1 正則和 L2 正則按一定的比例結合起來:

L1會趨向於產生少量的特徵,而其他的特徵都是0,而L2會選擇更多的特徵,這些特徵都會接近於0。Lasso在特徵選擇時候非常有用,而Ridge就只是一種規則化而已。在所有特徵中只有少數特徵起重要作用的情況下,選擇Lasso比較合適,因為它能自動選擇特徵。而如果所有特徵中,大部分特徵都能起作用,而且起的作用很平均,那麼使用Ridge也許更合適。對於各種迴歸的比較可以看下圖: