SVM最初被用來解決線性分類問題濒持,加入核方法之后能有效解決非線性問題织咧。
分類學(xué)習(xí)基本思想:
基于訓(xùn)練集在樣本空間中找到一個(gè)劃分超平面张弛,將不同類別的樣本分開.
選擇最優(yōu)超平面的依據(jù):
1.無法找到其他繪制方法使得到兩條虛線之間的距離更大
2.最優(yōu)超平面到與兩種類型距其最近的點(diǎn)有相等的距離
支持向量(support.vector)就是離分隔超平面最近的那些點(diǎn)缤骨。
硬間隔(Hard Margin)
嚴(yán)格地規(guī)定所有的數(shù)據(jù)都必須劃分正確列林,即所有數(shù)據(jù)都在虛線兩邊
軟間隔(Soft Margin)
允許一些樣本落在間隔內(nèi)(兩條虛線中間)舍败,防止出現(xiàn)過度擬合威沫。
這種情況下我們要盡可能正確地分類訓(xùn)練數(shù)據(jù)帽衙,間隔要盡可能大。
C值大纸巷,間隔小江醇。C值小,間隔大何暇。
可用交叉驗(yàn)證確定C值。
如果SVM模型過擬合凛驮,可以嘗試通過減小超參數(shù)C去調(diào)整.
線性不可分問題
任何有限維度的非線性問題在更高維度的空間里總可以變化成線性可分問題裆站。
SVM使用拉格朗日乘子法(Lagrange Multiplier)實(shí)現(xiàn)對超平面求解問題的升維。
核函數(shù)
SVM其實(shí)并不需要真正的向量,可以用它們的數(shù)量積來進(jìn)行分類宏胯。這意味著可以避免計(jì)算資源的耗費(fèi)了羽嫡。這就是核函數(shù)的技巧,它可以減少大量的計(jì)算資源的需求肩袍。通常杭棵,內(nèi)核是線性的,所以可得到一個(gè)非線性的分類器:只需改變點(diǎn)積為我們想要的空間氛赐。
在不知道特征映射的形狀時(shí)魂爪,我們并不知道什么樣的核函數(shù)是合適的,于是“核函數(shù)選擇”成為支持向量機(jī)的最大變數(shù)艰管。
線性核(linear)
c=1時(shí)退化為線性核 高斯徑向基核(Gaussian radial basis function)
decision_function()函數(shù)可以返回輸入的數(shù)據(jù)集與模型超平面之間的距離滓侍,用正負(fù)關(guān)系表示在超平面的哪一側(cè)。該距離的絕對值越大則分類的可靠性越高牲芋。
非線性
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_circles
from mpl_toolkits.mplot3d import Axes3D
# generating data
X, Y = make_circles(n_samples = 500, noise = 0.05)
# visualizing data
plt.scatter(X[:, 0], X[:, 1], c = Y, marker = '.')
plt.show()
# adding a new dimension to X
X1 = X[:, 0].reshape((-1, 1))
X2 = X[:, 1].reshape((-1, 1))
X3 = (X1**2 + X2**2)
X = np.hstack((X, X3))
# visualizing data in higher dimension
fig = plt.figure()
axes = fig.add_subplot(111, projection = '3d')
axes.scatter(X1, X2, X1**2 + X2**2, c = Y, depthshade = True)
plt.show()
# consider a grid search with an SVM and different kernels
import multiprocessing
import warnings
warnings.filterwarnings('ignore')
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score
param_grid = [ {'kernel': ['linear', 'rbf', 'poly', 'sigmoid'],
'C': [ 0.1, 0.2, 0.4, 0.5, 1.0, 1.5, 1.8, 2.0, 2.5, 3.0 ]
} ]
gs = GridSearchCV(estimator=SVC(), param_grid=param_grid,
scoring='accuracy', cv=10)
gs.fit(X, Y)
GridSearchCV(cv=10, error_score='raise',
estimator=SVC(C=1.0, kernel='rbf', max_iter=-1),
param_grid=[{'kernel': ['linear', 'rbf', 'poly', 'sigmoid'],
'C': [0.1, 0.2, 0.4, 0.5, 1.0, 1.5, 1.8, 2.0, 2.5, 3.0 ]}],
scoring='accuracy')
print(gs.best_estimator_)
print(gs.best_score_)
# create support vector classifier using a linear kernel
from sklearn import svm
svc = svm.SVC(kernel = 'linear')
svc.fit(X, Y)
w=svc.coef_
b=svc.intercept_
# plotting the separating hyperplane
x1 = X[:, 0].reshape((-1, 1))
x2 = X[:, 1].reshape((-1, 1))
x1, x2 = np.meshgrid(x1, x2)
x3 = -(w[0][0]*x1 + w[0][1]*x2 + b) / w[0][2]
fig = plt.figure()
axes2 = fig.add_subplot(111, projection = '3d')
axes2.scatter(X1, X2, X1**2 + X2**2, c = Y, depthshade = True)
axes1 = fig.gca(projection = '3d')
axes1.plot_surface(x1, x2, x3, alpha = 0.01)
plt.show()
在noise=0.05時(shí)撩笆,輸出結(jié)果顯示最好的核是rbf,且準(zhǔn)確率達(dá)到了98%。
在noise=0.1時(shí)缸浦,最好的核是linear,準(zhǔn)確率為85.6%
人臉識別
from sklearn.datasets import fetch_lfw_people
faces = fetch_lfw_people(min_faces_per_person=60)
print(faces.target_names)
print(faces.images.shape)
from sklearn.svm import SVC
from sklearn.decomposition import PCA
from sklearn.pipeline import make_pipeline
pca = PCA(n_components=150, whiten=True, random_state=19)
svc = SVC(kernel='rbf', class_weight='balanced')
model = make_pipeline(pca, svc)
from sklearn.model_selection import train_test_split
Xtrain, Xtest, ytrain, ytest = train_test_split(faces.data, faces.target,random_state=19)
#用網(wǎng)格搜索交叉檢驗(yàn)來尋找最優(yōu)參數(shù)組合
from sklearn.model_selection import GridSearchCV
param_grid =[{'kernel':['rbf','poly'],
'C': [1, 5, 10, 50], # C:控制邊界線的硬度
'gamma': [0.0001, 0.0005, 0.001, 0.005]}] #gamma:控制徑向基函數(shù)核的大小
grid = GridSearchCV(estimator=SVC(), param_grid=param_grid,
scoring='accuracy',cv=8)
grid.fit(faces.data,faces.target)
GridSearchCV(cv=8, error_score='raise',
estimator=SVC(C=1.0, kernel='rbf', max_iter=-1),
param_grid=[{'kernel': [ 'rbf', 'poly'],
'C': [0.1, 0.5, 1.0, 1.5],
'gamma':[0.0001, 0.0005, 0.001, 0.005]}],
scoring='accuracy')
print(grid.best_estimator_)
print(grid.best_score_)
model = grid.best_estimator_
yfit = model.predict(Xtest)
#from sklearn.metrics import classification_report
#print(classification_report(ytest, yfit, target_names=faces.target_names))
手寫數(shù)字識別
from sklearn.datasets import load_digits
digits = load_digits()
跟上個(gè)例子一樣可以用網(wǎng)格搜索的方法夕冲,只需改成digits.data, digits.target