【筆記】sklearn中的SVM以及使用多項式特征以及核函數


sklearn中的SVM以及使用多項式特征以及核函數

sklearn中的SVM的使用

SVM的理論部分

需要注意的是,使用SVM算法,和KNN算法一樣,都是需要做數據標准化的處理才可以,因為不同尺度的數據在其中的話,會嚴重影響SVM的最終結果

(在notebook中)

加載好需要的包,使用鳶尾花數據集,為了方便可視化,只取前兩個特征,然后將其繪制出來

  import numpy as np
  import matplotlib.pyplot as plt
  from sklearn import datasets

  iris = datasets.load_iris()

  X = iris.data
  y = iris.target

  X = X[y<2,:2]
  y = y[y<2]

  plt.scatter(X[y==0,0],X[y==0,1],color='red')
  plt.scatter(X[y==1,0],X[y==1,1],color='blue')

圖像如下

首先進行數據的標准化的操作,實例化並fit操作,然后對x進行transform操作,傳入x_standard,這樣就完成了標准化的操作

  from sklearn.preprocessing import StandardScaler

  standardScaler = StandardScaler()
  standardScaler.fit(X,y)
  X_standard = standardScaler.transform(X)

在標准化以后就可以調用SVM算法了,對於線性的SVM,可以直接使用LinearSVC類,然后實例化操作,在進行fit,設置C為10的九次方

  from sklearn.svm import LinearSVC

  svc = LinearSVC(C=1e9)
  svc.fit(X_standard,y)

使用先前的繪制函數並繪制圖像

from matplotlib.colors import ListedColormap
def plot_decision_boundary(model, axis):

    x0,x1 = np.meshgrid(  
        np.linspace(axis[0],axis[1],int((axis[1]-axis[0])*100)).reshape(-1,1),
        np.linspace(axis[2],axis[3],int((axis[3]-axis[2])*100)).reshape(-1,1)
    )
    X_new = np.c_[x0.ravel(),x1.ravel()]
    y_predict = model.predict(X_new)
    zz = y_predict.reshape(x0.shape)
    custom_cmap = ListedColormap(['#EF9A9A', '#FFF59D', '#90CAF9'])

    plt.contourf(x0, x1, zz, linewidth=5, cmap=custom_cmap)

  plot_decision_boundary(svc,axis=[-3,3,-3,3])
  plt.scatter(X_standard[y==0,0],X_standard[y==0,1])
  plt.scatter(X_standard[y==1,0],X_standard[y==1,1])

圖像如下(這就相當於是Hard margin SVM得到的結果)

設置C為0.01,並繪制圖像

  svc2 = LinearSVC(C=0.01)
  svc2.fit(X_standard,y)

  plot_decision_boundary(svc2,axis=[-3,3,-3,3])
  plt.scatter(X_standard[y==0,0],X_standard[y==0,1])
  plt.scatter(X_standard[y==1,0],X_standard[y==1,1])

圖像如下(將c縮小以后,有一個藍色的點被錯誤分類了)

觀察系數以及截距

結果如下

改造繪制函數,在新的函數中添加新的代碼,在原先的基礎上增加上一些繪制的代碼,首先取出相應的系數w以及截距b,此時,模型直線應該是w0x0+w1x1+b=0的形式,不過可以改寫成x1=-w0/w1*x0-b/w1的形式,那么每有一個x0,就能求出相應的x1,找到對應的點,將其串聯起來就得到了需要的直線

對於繪制的點,在axis[0],axis[1]之間取兩百個點,這樣就可以求出來上下的直線,將上直線設置為up_y,下設置為down_y,具體可以看這里(鏈接),由於擔心可能超出設置的y的范圍,那么就要設置一個過濾,要大於等於最小值,小於等於最大值,然后繪制出兩條直線

from matplotlib.colors import ListedColormap
def plot_svc_decision_boundary(model, axis):

    x0,x1 = np.meshgrid(  
        np.linspace(axis[0],axis[1],int((axis[1]-axis[0])*100)).reshape(-1,1),
        np.linspace(axis[2],axis[3],int((axis[3]-axis[2])*100)).reshape(-1,1)
    )
    X_new = np.c_[x0.ravel(),x1.ravel()]
    y_predict = model.predict(X_new)
    zz = y_predict.reshape(x0.shape)
    custom_cmap = ListedColormap(['#EF9A9A', '#FFF59D', '#90CAF9'])

    plt.contourf(x0, x1, zz, linewidth=5, cmap=custom_cmap)
    
    w = model.coef_[0]
    b = model.intercept_[0]
    
    plot_x = np.linspace(axis[0],axis[1],200)
    up_y = -w[0]/w[1] * plot_x-b/w[1] + 1/w[1]
    down_y = -w[0]/w[1] * plot_x-b/w[1] - 1/w[1]
    
    up_index = (up_y >= axis[2])&(up_y <= axis[3])
    down_index = (down_y >= axis[2])&(down_y <= axis[3])
    
    plt.plot(plot_x[up_index],up_y[up_index],color="black") 
  plt.plot(plot_x[down_index],down_y[down_index],color="black")

調用新的繪制函數並進行繪制svc圖像

  plot_svc_decision_boundary(svc,axis=[-3,3,-3,3])
  plt.scatter(X_standard[y==0,0],X_standard[y==0,1])
  plt.scatter(X_standard[y==1,0],X_standard[y==1,1])

圖像如下

繪制svc2的圖像

  plot_svc_decision_boundary(svc2,axis=[-3,3,-3,3])
  plt.scatter(X_standard[y==0,0],X_standard[y==0,1])
  plt.scatter(X_standard[y==1,0],X_standard[y==1,1])

圖像如下

以上就是線性問題的svm的使用,那么SVM不止可以解決線性問題,也可以解決非線性數據的問題

在svm中使用多項式特征以及核函數(使用svm來處理非線性數據的問題)

具體實現

(在notebook中)

自動生成非線性的數據make_moons來生成數據集,繪制圖像看一下長什么樣

  import numpy as np
  import matplotlib.pyplot as plt
  from sklearn import datasets

  X,y = datasets.make_moons()

  plt.scatter(X[y==0,0],X[y==0,1])
  plt.scatter(X[y==1,0],X[y==1,1])

圖像如下

但是這個有點太規整了,所以添加一些噪音進去,設置noise為0.15,其實質上就是使數據的標准差增大,設置隨機種子為666,然后再繪制圖像看一下

  X,y = datasets.make_moons(noise=0.15,random_state=666)

  plt.scatter(X[y==0,0],X[y==0,1])
  plt.scatter(X[y==1,0],X[y==1,1])

圖像如下

繪制函數

from matplotlib.colors import ListedColormap
def plot_decision_boundary(model, axis):

    x0,x1 = np.meshgrid(  
        np.linspace(axis[0],axis[1],int((axis[1]-axis[0])*100)).reshape(-1,1),
        np.linspace(axis[2],axis[3],int((axis[3]-axis[2])*100)).reshape(-1,1)
    )
    X_new = np.c_[x0.ravel(),x1.ravel()]
    y_predict = model.predict(X_new)
    zz = y_predict.reshape(x0.shape)
    custom_cmap = ListedColormap(['#EF9A9A', '#FFF59D', '#90CAF9'])

    plt.contourf(x0, x1, zz, linewidth=5, cmap=custom_cmap)

使用多項式特征的管道的詳情原理

首先生成多項式的特征,然后數據標准化,最后調用LinearSVC的方法,設置C的默認值為1.0

  from sklearn.preprocessing import PolynomialFeatures
  from sklearn.preprocessing import StandardScaler
  from sklearn.svm import LinearSVC
  from sklearn.pipeline import Pipeline

  def PolynomialSVC(degree,C=1.0):
      return Pipeline([
          ("poly",PolynomialFeatures(degree=degree)),
          ("std_scaler",StandardScaler()),
          ("linearSVC",LinearSVC(C=C))
      ])

調用管道,再進行fit操作,然后將圖像繪制出來

  poly_svc = PolynomialSVC(degree=3)
  poly_svc.fit(X,y)

  plot_decision_boundary(poly_svc,axis=[-1.5,2.5,-1.0,1.5])
  plt.scatter(X[y==0,0],X[y==0,1])
  plt.scatter(X[y==1,0],X[y==1,1])

圖像如下(可以看出來,邊界變成了曲線,說明將結果轉換成了一個高維的有多項式項特征的數據以后在使用linearSVM中)

其實SVM有一種特殊的方式,可以直接使用多項式特征,這種稱為多項式和,想要使用這種方式,就要調用SVC這個類,先定義一個函數,在這種情況下,只需要兩步,第一步對數據進行標准化,第二步實例化一個SVC對象,使用SVC函數,就需要傳入一個參數kernel,其中傳入一個字符串poly,這樣就會自動對傳入的數據進行多項式化,進行訓練

  from sklearn.svm import SVC

  def PolynomialKernelSVC(degree,C=1.0):
      return Pipeline([
          ("std_scaler",StandardScaler()),
          ("kernelSVC",SVC(kernel="poly",degree=degree,C=C))
      ])

調用函數,並進行訓練,然后繪制出圖像

  poly_kernel_svc = PolynomialKernelSVC(degree=3)
  poly_kernel_svc.fit(X,y)

  plot_decision_boundary(poly_kernel_svc,axis=[-1.5,2.5,-1.0,1.5])
  plt.scatter(X[y==0,0],X[y==0,1])
  plt.scatter(X[y==1,0],X[y==1,1])

圖像如下

以上就是SVM的兩種多項式計算的方式


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM