1. 程式人生 > 實用技巧 >【筆記】多項式迴歸的思想以及在sklearn中使用多項式迴歸和pipeline

【筆記】多項式迴歸的思想以及在sklearn中使用多項式迴歸和pipeline

多項式迴歸以及在sklearn中使用多項式迴歸和pipeline

多項式迴歸

線性迴歸法有一個很大的侷限性,就是假設資料背後是存線上性關係的,但是實際上,具有線性關係的資料集是相對來說比較少的,更多時候,資料之間是具有的非線性的關係,那麼我們想要用線性迴歸法來對非線性的資料進行處理應該怎麼辦呢,我們可以使用多項式迴歸的手段來改進線性迴歸法,使線性迴歸法也可以對非線性的資料進行處理,並進行預測

通過多項式迴歸可以引出一個很重要的概念,即模型泛化的問題

什麼是多項式迴歸呢?

對於線性迴歸來說,對於資料,我們想找到一條直線,使其儘可能的擬合這些資料,若只有一個特徵的話,我們可以稱直線為y=ax+b(x為樣本特徵,a和b為引數),但是對於很多的資料來說,雖然可以使用一條直線來擬合數據,但是其分佈很多時候是具有更強的非線性的關係,也就是說,使用二次曲線來擬合這些資料的話效果會更好,如果也是隻有一個特徵的話,那麼方程就可以寫成y=ax²+bx+c

雖然稱其為一個特徵的二次方程,但是可以從另一個方向來理解這個方程,如果將X²看成是一個特徵,X看成另一個特徵,這就將其看成是含有兩個特徵的資料集,多了一個X²的特徵,從這個方向來看的話,這個式子依然是一個線性迴歸的式子,從X的角度來看,就是一個非線性的方程,這樣的方式就稱為多項式迴歸

相當於為樣本多添加了幾個特徵,這些特徵是原先樣本的多項式項(像是X²就是對X進行了平方),增加了這些特徵以後就可以使用線性迴歸的思路,來更好的擬合原來的資料,本質上就是,求出了原來的特徵而言的非線性的曲線,即為了更好地擬合數據進行了升維

需要注意的是,思路方面,對資料集的操作裡,PCA是對資料集進行降維處理,而多項式迴歸是讓資料集進行升維,在升維以後可以更好地擬合高維的資料,這兩種要看情況使用

實現

(在notebook中)

仍然是載入好需要的包,接著生成一個隨機的資料作為樣本資料,從-3到3之間進行100個隨機的取值,接著reshape成一個二維陣列,設定y為0.5乘上x的平方加上x再加上2以後新增一些噪點,視覺化一下關係影象來看一下資料集

  import numpy as np
  import matplotlib.pyplot as plt

  x = np.random.uniform(-3,3,size=100)
  X = x.reshape(-1,1)
  y = 0.5 * x**2 + x + 2 + np.random.normal(0,1,size=100)

  plt.scatter(x,y)

影象如下

用線性迴歸的方式

首先引用LinearRegression這個類,然後例項化以後進行fit,fit傳入X和y

  from sklearn.linear_model import LinearRegression

  lin_reg = LinearRegression()
  lin_reg.fit(X,y)

結果如下

擬合以後,使用predict方法將X傳入,得到預測結果,並對其進行繪製

  y_predict = lin_reg.predict(X)

  plt.scatter(x,y)
  plt.plot(x,y_predict,color='r')

影象如下

從影象可以發現,使用直線來擬合有弧度的曲線,效果不是特別好,那麼我們新增一個特徵來解決這個情況

對X中的每一個數據進行平方,X²其本身就是一個新的特徵,使用(X**2).shape,可以看出其是一個100行1列的矩陣

用hstack的方法將原來的X和新的X²合在一起組成一組新的含有100行2列的資料集

  X2 = np.hstack([X,X**2])
  X2.shape

結果如下

現在就可以使用新的資料集進行訓練,操作同上,同時得出預測結果以後將新的預測結果繪製出來,需要注意的是,如果還是使用plt.plot(x,y_predict2,color='r')來繪製的話,生成的圖是亂的(因為x是沒有順序的),如果想生成平滑的曲線的話,就要對x進行從小到大的排序才可以,對於預測結果來說,也要對排序以後的x進行預測才可以

  lin_reg2 = LinearRegression()
  lin_reg2.fit(X2,y)
  y_predict2 = lin_reg2.predict(X2)

  plt.scatter(x,y)
  plt.plot(np.sort(x),y_predict2[np.argsort(x)],color='r')

影象如下

顯然,這條曲線對資料集的擬合是比直線更好的

使用lin_reg2.coef_看一下係數

同時使用lin_reg2.intercept_來看一下截距

可以發現,這個和之前假設的生成資料大致上是擬合的,因為先前設定了噪音,所以會有偏差

這就是多項式迴歸的思路,其關鍵在於為原來的資料樣本新增新的特徵,而得到新的特徵的方式是原有的特徵的多項式組合,使用這種方式,我們就可以解決一些非線性問題

在sklearn中使用多項式迴歸和pipeline

(在notebook中,和上面的不是一個檔案)

首先載入好需要的包,再設定好的虛擬的資料集,之後引用PolynomialFeatures類,使用方法同樣的,先進行例項化,傳入引數degree,其表示為原來的資料集新增的最高的冪,這裡設定為2,這就初始化好了,然後fit一下X,之後呼叫poly.transform這個方式,將其轉換成多項式的特徵

  from sklearn.preprocessing import PolynomialFeatures

  poly = PolynomialFeatures(degree=2)
  poly.fit(X)
  X2 = poly.transform(X)

我們使用X2.shape可以看到這是一個100*3的矩陣

我們看一下前5行的資料

  X2[:5,:]

結果如下(第一列的1可以看作為x的0次方,第2列就是原來的樣本特徵,第3列就是x的平方的特徵,以此類推)

驗證一下是不是,將x的前5行也輸出出來X[:5,:],可以發現和x2的第2列是一樣的

之後的操作同上,引用LinearRegression這個類,然後例項化再進行fit,擬合後,使用predict方法得到預測結果,並對其進行繪製

  from sklearn.linear_model import LinearRegression

  lin_reg2 = LinearRegression()
  lin_reg2.fit(X2,y)
  y_predict2 = lin_reg2.predict(X2)

  plt.scatter(x,y)
  plt.plot(np.sort(x),y_predict2[np.argsort(x)],color='r')

影象如下

同樣的,看一下係數和截距

關於PolynomialFeatures的運算邏輯

試一下設定x為兩個特徵,設定成一到十的數字分成兩列

  X = np.arange(1,11).reshape(-1,2)
  X.shape

結果如下

其內容X如下

現在試一下PolynomialFeatures,首先進行操作,將其轉換成最多包含二次冪的資料集

  poly = PolynomialFeatures(degree=2)
  poly.fit(X)
  X2 = poly.transform(X)
  X2.shape

結果如下(其為五行六列的資料集)

其中X2內的資料為

從圖中可以看出來,第一列仍然是0次冪,第二列和第三列也是原來的,第四列為原來的第一列的平方,第六列是原來的第二列的平方,那麼第五列變成了原來兩列特徵相乘的結果,這裡就得注意,原來有二次冪的特徵,再生成二次冪的話就會產生三列,為第一列的平方,第一列和第二列的乘積,第二列的平方

可想而知,如果degree為3的話,就更加複雜了,其有十列資料,為什麼呢,因為這就相當於是,0次方,1次方,2次方,3次方的全部的集合,且包含相互的乘積,設第一列為x1,第二列為x2,則其中就有1,x1,x2,x2的平方,x1的平方,x1乘x2,x1的三次方,x2的三次方,x1的平方乘上x2,x2的平方乘上x1

那麼就說明PolynomialFeatures的degree傳入的是i的話,那麼其將自動生成不小於i的相應的所有的多項式的項,這就涉及到了所有的多項式的特徵

在具體實現的時候如果使用sklearn的話,由於sklearn中沒有多項式迴歸這個類,那麼使用pipeline建立一個多項式迴歸的類就可以方便使用這種多項式迴歸的方式

想要實現多項式迴歸的話,先要將原先的資料升維成多項式的樣本的資料,但是如果degree非常的大的話,樣本之間的差距也會特別的大,像是線性迴歸的時候用梯度下降法,如果資料不均衡的話,搜尋會非常的慢,需要進行資料歸一化,然後線上性迴歸,需要進行三步,而使用pipeline的話,可以將這三步合在一起

具體操作,同樣的使用虛擬的測試用例

  x = np.random.uniform(-3,3,size=100)
  X = x.reshape(-1,1)
  y = 0.5 * x**2 + x + 2 + np.random.normal(0,1,size=100)

然後引用pipeline這個類,進行例項化,對pipeline進行構造,其中的列表就是對應的每一個步驟的對應的類,第一步進行多項式的過程,第二步進行資料歸一化,第三步就是進行線性迴歸,這就建立了一個管道

  from sklearn.pipeline import Pipeline
  from sklearn.preprocessing import StandardScaler

  poly_reg = Pipeline([
      ("poly",PolynomialFeatures(degree=2)),
      ("std_scaler",StandardScaler()),
      ("lin_reg",LinearRegression())
  ])

使用方式與其他的封裝的演算法是一樣的,呼叫fit,將原始的x和y,其過程很智慧,再傳入以後進行預測,繪製出影象

  poly_reg.fit(X,y)
  y_predict = poly_reg.predict(X)

  plt.scatter(x,y)
  plt.plot(np.sort(x),y_predict[np.argsort(x)],color='r')

影象如下

以上