支持向量機同樣是一種分類算法,它的目的是尋找一個超平面來對樣本進行分割,分割的原則是間隔最大化,當訓練樣本線性可分時,通過硬間隔最大化學習一個線性可分支持向量機;當訓練樣本近似線性可分時,通過軟間隔最大化學習一個線性支持向量機;當訓練樣本線性不可分時,通過核技巧和軟間隔最大化學習一個非線性支持向量機,該算法思路比較簡單,但推導過程比較複雜,需要高等數學知識;
算法優點:① 純高等數學知識思維,可解釋性強,不依靠統計方法,從而簡化了通常的分類和迴歸問題;② 採用核技巧之後,可以處理非線性分類/迴歸任務;③ 最終決策函數只由少數的支持向量所確定,計算的複雜性取決於支持向量的數目,而不是樣本空間的維數,這在某種意義上避免了“維數災難”
算法缺陷:① 訓練時間長,時間複雜度;② 當採用核技巧時,如果需要存儲核矩陣,則空間複雜度爲 ;③ 預測時間與支持向量的個數成正比,當支持向量的數量較大時,預測計算複雜度較高。
線性可分
如果一個線性函數(二維空間中的直線)能夠將樣本分開,稱這些數據樣本是線性可分的,在三維空間是一個平面,以此類推,如果不考慮空間維數,這樣的線性函數統稱爲超平面,通常我們所說的線性可分支持向量機就對應着能將數據正確劃分並且間隔最大的直線。
SVM最優化問題
SVM 想要的就是找到各類樣本點到超平面的距離最遠,也就是找到最大間隔超平面。任意超平面可以用下面這個線性方程來描述:
點(x,y)到的距離公式爲:
擴展到 n 維空間後,點x=(x1,x2,x3,x4.....xn)到直線的距離爲:
其中:
經過推導我們的優化問題是:
再做一個轉換,爲了方便計算(去除的根號),得到的最優化問題是:
拉格朗日乘法
可以使用本科高等數學學的拉格朗日程數法是等式約束優化問題思想,構造拉格朗日函數:
核函數
我們可能會碰到的一種情況是樣本點不是線性可分的,這種情況的解決方法就是:將二維線性不可分樣本映射到高維空間中,讓樣本點在高維空間線性可分,對於在有限維度向量空間中線性不可分的樣本,我們將其映射到更高維度的向量空間裏,再通過間隔最大化的方式,學習得到支持向量機,就是非線性 SVM。
用法
sklearn提供了三種基於svm的分類方法:
sklearn.svm.NuSVC()
sklearn.svm.LinearSVC()
sklearn.svm.SVC()
其中用得最多的是 sklearn.svm.SVC(),全稱是C-Support Vector Classification,是一種基於libsvm的支持向量機,由於其時間複雜度爲O(n^2),所以當樣本數量超過兩萬時難以實現。
sklearn.svm.SVC(C=1.0, kernel='rbf', degree=3, gamma='auto', coef0=0.0, shrinking=True,
probability=False, tol=0.001, cache_size=200, class_weight=None,
verbose=False, max_iter=-1, decision_function_shape='ovr',
random_state=None)
- 相關參數
- C (float參數 默認值爲1.0)
表示錯誤項的懲罰係數C越大,即對分錯樣本的懲罰程度越大,因此在訓練樣本中準確率越高,但是泛化能力降低;相反,減小C的話,容許訓練樣本中有一些誤分類錯誤樣本,泛化能力強。對於訓練樣本帶有噪聲的情況,一般採用後者,把訓練樣本集中錯誤分類的樣本作爲噪聲。 - kernel (str參數 默認爲‘rbf’)
該參數用於選擇模型所使用的核函數,算法中常用的核函數有:
-- linear:線性核函數
-- poly:多項式核函數
--rbf:徑像核函數/高斯核
--sigmod:sigmod核函數
--precomputed:核矩陣,該矩陣表示自己事先計算好的,輸入後算法內部將使用你提供的矩陣進行計算 - degree (int型參數 默認爲3)
該參數只對'kernel=poly'(多項式核函數)有用,是指多項式核函數的階數n,如果給的核函數參數是其他核函數,則會自動忽略該參數。 - gamma (float參數 默認爲auto)
該參數爲核函數係數,只對‘rbf’,‘poly’,‘sigmod’有效。如果gamma設置爲auto,代表其值爲樣本特徵數的倒數,即1/n_features,也有其他值可設定。 - coef0:(float參數 默認爲0.0)
該參數表示核函數中的獨立項,只有對‘poly’和‘sigmod’核函數有用,是指其中的參數c。 - probability( bool參數 默認爲False)
該參數表示是否啓用概率估計。 這必須在調用fit()之前啓用,並且會使fit()方法速度變慢。 - shrinkintol: float參數 默認爲1e^-3g(bool參數 默認爲True)
該參數表示是否選用啓發式收縮方式。 - tol( float參數 默認爲1e^-3)
svm停止訓練的誤差精度,也即閾值。 - cache_size(float參數 默認爲200)
該參數表示指定訓練所需要的內存,以MB爲單位,默認爲200MB。 - class_weight(字典類型或者‘balance’字符串。默認爲None)
該參數表示給每個類別分別設置不同的懲罰參數C,如果沒有給,則會給所有類別都給C=1,即前面參數指出的參數C。如果給定參數‘balance’,則使用y的值自動調整與輸入數據中的類頻率成反比的權重。 - verbose ( bool參數 默認爲False)
該參數表示是否啓用詳細輸出。此設置利用libsvm中的每個進程運行時設置,如果啓用,可能無法在多線程上下文中正常工作。一般情況都設爲False,不用管它。 - max_iter (int參數 默認爲-1)
該參數表示最大迭代次數,如果設置爲-1則表示不受限制。 - random_state(int,RandomState instance ,None 默認爲None)
該參數表示在混洗數據時所使用的僞隨機數發生器的種子,如果選int,則爲隨機數生成器種子;如果選RandomState instance,則爲隨機數生成器;如果選None,則隨機數生成器使用的是np.random。
from sklearn import svm
from sklearn import datasets
from sklearn.model_selection import train_test_split as ts
#import our data
iris = datasets.load_iris()
X = iris.data
y = iris.target
#split the data to 7:3
X_train,X_test,y_train,y_test = ts(X,y,test_size=0.3)
# select different type of kernel function and compare the score
# kernel = 'rbf'
clf_rbf = svm.SVC(kernel='rbf')
clf_rbf.fit(X_train,y_train)
score_rbf = clf_rbf.score(X_test,y_test)
print("The score of rbf is : %f"%score_rbf)
# kernel = 'linear'
clf_linear = svm.SVC(kernel='linear')
clf_linear.fit(X_train,y_train)
score_linear = clf_linear.score(X_test,y_test)
print("The score of linear is : %f"%score_linear)
# kernel = 'poly'
clf_poly = svm.SVC(kernel='poly')
clf_poly.fit(X_train,y_train)
score_poly = clf_poly.score(X_test,y_test)
print("The score of poly is : %f"%score_poly)
- 方法
- svc.decision_function(X)
樣本X到分離超平面的距離 - svc.fit(X, y[, sample_weight])
根據給定的訓練數據擬合SVM模型。 - svc.get_params([deep])
獲取此估算器的參數並以字典行書儲存,默認deep=True,以分類iris數據集爲例,得到的參數如下; - svc.predict(X)
根據測試數據集進行預測 - svc.score(X, y[, sample_weight])
返回給定測試數據和標籤的平均精確度 - svc.predict_log_proba(X_test),svc.predict_proba(X_test)
當sklearn.svm.SVC(probability=True)時,纔會有這兩個值,分別得到樣本的對數概率以及普通概率。