sklearn庫學習之核支援向量機
阿新 • • 發佈:2018-12-16
核支援向量機
核SVM的重要引數是正則化引數C、核的選擇以及與核相關的引數。
- 在低維資料和高維資料上表現都很好。
- 但對樣本個數的縮放表現不好。
- 預處理資料和調參都需要非常小心。
線性模型在低維空間中可能非常受限,因為線和平面的靈活性有限,新增更多的特徵讓線性模型更加靈活。
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)
核技巧
核技巧可以在更高維的空間中學習分類器,而不用實際計算可能非常大的新的資料表示。原理是直接計算擴充套件特徵表示中資料點的距離(內積),而不用實際對擴充套件進行計算。
支援向量機將資料對映到更高維空間中的兩種常用方法
- 多項式核,在一定階數內計算原始特徵所有可能的多項式。
- 徑向基函式核(高斯核),考慮所有階數的所有可能的多項式。但階數越高,特徵的重要性越小。
支援向量:位於類別邊界上的那些點。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