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的兩種多項式計算的方式

