1. 程式人生 > >sklearn庫學習之核支援向量機

sklearn庫學習之核支援向量機

核支援向量機

核SVM的重要引數是正則化引數C、核的選擇以及與核相關的引數。

  1. 在低維資料和高維資料上表現都很好。
  2. 但對樣本個數的縮放表現不好。
  3. 預處理資料和調參都需要非常小心。

線性模型在低維空間中可能非常受限,因為線和平面的靈活性有限,新增更多的特徵讓線性模型更加靈活。

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

X,y = make_blobs(centers = 4, random_state = 8)
y = y%2 #將四個聚類分成兩個類別
mglearn.discrete_scatter(X[:,0],X[:,1],y)
plt.xlabel("Feature 0")
plt.ylabel("Feature 1")

#用於分類的線性模型只能用一條直線劃分資料
from sklearn.svm import LinearSVC
linear_svm = LinearSVC().fit(X,y)

mglearn.plots.plot_2d_separator(linear_svm,X) #邊界視覺化

#新增第二個特徵的平方,作為一個新的特徵,將每個資料點表示為三維點
X_new = np.hstack([X,X[:,1:]**2])
#print(X_new)
from mpl_toolkits.mplot3d import Axes3D,axes3d
figure = plt.figure()
#3D視覺化
ax = Axes3D(figure, elev = -152, azim = -26)
#首先畫出所有y == 0的點,然後畫出所有y == 1的點
mask = y == 0

#mask為true時,這一行就有
ax.scatter(X_new[mask,0],X_new[mask,1],X_new[mask,2], c = 'b', cmap = mglearn.cm2, s = 60)
ax.scatter(X_new[~mask,0],X_new[~mask,1],X_new[~mask,2], c = 'r', marker = '^', cmap = mglearn.cm2, s = 60)

ax.set_xlabel = ("feature0")
ax.set_ylabel = ("feature1")
ax.set_zlabel = ("feature1 ** 2")

#現在可以用線性模型將這兩個類別分開
linear_svm_3d = LinearSVC().fit(X_new, y)
coef, intercept = linear_svm_3d.coef_.ravel(), linear_svm_3d.intercept_

#顯示線性決策邊界
'''
print(X_new[:,0].min() - 2)
print(X_new[:,0].max() + 2)
'''

xx = np.linspace(X_new[:,0].min() - 2, X_new[:,0].max() + 2, 50)
yy = np.linspace(X_new[:,1].min() - 2, X_new[:,1].max() + 2, 50)

XX,YY = np.meshgrid(xx,yy)

ZZ = (coef[0] * XX + coef[1] * YY + intercept) / -coef[2]
ax.plot_surface(XX,YY,ZZ, rstride = 8, cstride = 8, alpha = 0.3)

#此時,如果將線性SVM看作原始特徵的函式,它實際上已經不是線性的了
fig = plt.figure()
ax = fig.add_subplot(111)
ZZ = YY ** 2
dec = linear_svm_3d.decision_function(np.c_[XX.ravel(),YY.ravel(),ZZ.ravel()])
plt.contourf(XX, YY, dec.reshape(XX.shape),levels = [dec.min(),0,dec.max()],cmap = mglearn.cm2, alpha = 0.5)
mglearn.discrete_scatter(X[:,0],X[:,1],y)

核技巧

核技巧可以在更高維的空間中學習分類器,而不用實際計算可能非常大的新的資料表示。原理是直接計算擴充套件特徵表示中資料點的距離(內積),而不用實際對擴充套件進行計算。

支援向量機將資料對映到更高維空間中的兩種常用方法

  1. 多項式核,在一定階數內計算原始特徵所有可能的多項式。
  2. 徑向基函式核(高斯核),考慮所有階數的所有可能的多項式。但階數越高,特徵的重要性越小。

支援向量:位於類別邊界上的那些點。SVM學習 每個訓練資料點 對於 表示兩個類別的之間的決策邊界的重要性。

對新樣本點預測,預測它與每個支援向量之間的距離。分類決策是基於它與支援向量之間的距離 以及 在訓練過程中學習到的 支援向量重要性 做出的。資料點之間的距離由核給出,可以是高斯核。

#在forge資料集上訓練SVM
from sklearn.svm import SVC
import mglearn
import matplotlib.pyplot as plt

X,y = mglearn.tools.make_handcrafted_dataset()
#核心是高斯核。C引數是正則化引數,限制每個點的重要性。gamma引數用於控制高斯核的寬度,決定了點與點之間的靠近是指多大的距離。
svm = SVC(kernel = 'rbf', C = 10, gamma = 0.1).fit(X,y) 

mglearn.plots.plot_2d_separator(svm, X, eps=.5) #決策邊界視覺化
mglearn.discrete_scatter(X[:,0],X[:,1],y) #畫點

sv = svm.support_vectors_ #賦值支援向量
#print(sv)
sv_labels = svm.dual_coef_.ravel() > 0 #支援向量的類別標籤由dual_coef_的正負號給出
#print(sv_labels)
mglearn.discrete_scatter(sv[:,0],sv[:,1],sv_labels, s = 15, markeredgewidth = 3) #markeredgewidth標記邊緣寬度,s標記大小

plt.xlabel("Feature 0")
plt.ylabel("Feature 1")


#gamma較小,說明高斯核的半徑較大,很多點被看作比較靠近,小的gamma值表示決策邊界變化很慢,生成複雜度較低的模型
#C值很小,說明模型非常受限,每個點的影響範圍都有限
fig, axes = plt.subplots(3,3,figsize = (15,10))
for ax, C in zip(axes, [-1,0,3]):
    for a, gamma in zip(ax, range(-1,2)):
        mglearn.plots.plot_svm(log_C = C, log_gamma = gamma, ax = a)
        
axes[0,0].legend(['class 0','class 1','sv class 0','sv class 1'],ncol = 4, loc = (.9,1.2))

#將RBF核SVM應用到乳腺癌資料集上,預設下C = 1, gamma = 1/n_features
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC

cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target,random_state = 0)

svc = SVC()
svc.fit(X_train, y_train)

#SVM對引數的設定和資料的縮放非常敏感,它要求所有特徵有相似的變化範圍
print("Accuracy on training set:{:.3f}".format(svc.score(X_train,y_train)))
print("Accuracy on test set:{:.3f}".format(svc.score(X_test,y_test)))

#檢視每個特徵的最小值和最大值,並繪製在對數座標上
plt.plot(X_train.min(axis = 0),'o',label = 'min')
plt.plot(X_train.max(axis = 0),'^',label = 'max') #axis = 0即列
plt.legend(loc = 4)
plt.xlabel('Feature index')
plt.ylabel('Feature magnitude')
plt.yscale('log') #座標的刻度
#確定乳腺癌資料集的特徵具有完全不同的數量級

#對資料進行縮放,使其大致都位於同一範圍,如將所有特徵縮放到0和1之間
min_on_training = X_train.min(axis = 0)#計算訓練集中每個特徵的最小值
#計算訓練集中每個特徵的範圍 
range_on_training = (X_train - min_on_training).max(axis = 0)
#減去最小值除以範圍
X_train_scaled = (X_train - min_on_training) / range_on_training
print("Mininum for each feature\n{}".format(X_train_scaled.min(axis = 0)))
print("Maxinum for each feature\n{}".format(X_train_scaled.max(axis = 0)))


#訓練集和測試集的效能非常接近,但還沒接近百分之百,所以可能欠擬合,嘗試增大C或gamma

對程式碼中的疑惑