分類演算法-支援向量機(SVM)
支援向量機(Support Vector Machine,SVM)是Corinna Cortes和Vapnik等於1995年首先提出的,它在解決小樣本、非線性及高維模式識別中表現出許多特有的優勢,並能夠推廣應用到函式擬合等其他機器學習問題中。
在機器學習中,支援向量機(SVM,還支援向量網路)是與相關的學習演算法有關的監督學習模型,可以分析資料,識別模式,用於分類和迴歸分析。
在機器學習中,支援向量機(SVM,還支援向量網路)是與相關的學習演算法有關的監督學習模型,可以分析資料,識別模式,用於分類和迴歸分析。給定一組訓練樣本,每個標記為屬於兩類,一個SVM訓練演算法建立了一個模型,分配新的例項為一類或其他類,使其成為非概率二元線性分類。一個SVM模型的例子,如在空間中的點,對映,使得所述不同的類別的例子是由一個明顯的差距是儘可能寬劃分的表示。新的實施例則對映到相同的空間中,並預測基於它們落在所述間隙側上屬於一個類別。
除了進行線性分類,支援向量機可以使用所謂的核技巧,它們的輸入隱含對映成高維特徵空間中有效地進行非線性分類。
圖C的容忍度比較大,效果較好
越胖越好
我們要求一個點到一個超平面的距離
wTx’=-b,wTx”=-b
法向量w垂直於超平面就一定垂直於超平面上的線,於是w垂直於x”-x’
有wT(x”-x’)=0
向量x-x’對映到w單位方向上即x到平面距離
distance(x,b,w)=|wT/||w| * |(x-x’)|=1/||w||*|wTx+b|
資料集(x1,y1)(x2,y2)到(xn,yn)
Y為樣本的類別,
當x為正例的時候Y=+1
當x為負例的時候Y=-1
y(x)=wT*φ(x)+b
y={1 如果w.z+b>0 -1如果w.z+b<0
保證預測值和真實值的乘積是正數
接下來我們要找所有樣本中離切平面最近的點使它離切平面的距離最遠
通過放縮乘1化簡式子
下一步需要把求極大值轉換成求極小值
很簡單,只要把求它的極大值轉換成求它倒數的極小值就好了
在這裡需要變換一下,因為求w的模不方便,所以變成求w的平方,而為了之後計算方便在前面再加個1/2,對式子是沒有影響的
約束條件是:yi(wT·φ(xi)+b)>=1
表示必須在把點分的開的情況下才能求
約束條件變成拉格朗日乘子法的標準約束
1-yi(wT·φ(xi)+b)<=0
變換之後:
g(x)=1-yi(wT·φ(xi)+b)
要求解的問題就變成了f(x)+αg(x)的min
轉換成對偶問題求解
最大值中最小的肯定比最小值中最大的要大
先求最小值,也就是求偏導
例子:
求最小值,直接求導
問題延伸:
當有個別不合群點的時候就放棄掉,因為絕大多數還是很聽話的
同上,步驟省略了……
支援向量機中核函式的應用:
應用SMO演算法求解支援向量機
其中(xi,yi)表示訓練樣本資料,xi為樣本特徵,yi∈{-1,1}為樣本標籤,C為懲罰係數由自己設定。上述問題是要求解N個引數(α1,α2,α3,……,αN),其他引數均為已知,有多種演算法可以對上述問題求解,但是演算法複雜度均很大。但1988年,由Platt提出的序列最小最優化演算法(SMO)可以高效的求解上述SVM問題,它把原始求解N個引數二次規劃問題分解成很多個
子二次規劃問題分別求解,每個子問題只需要求解2個引數,方法類似於座標上升,節省時間成本和降低了記憶體需求。每次啟發式選擇兩個變數進行優化,不斷迴圈,直到達到函式最優值。
Python實現:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import ListedColormap
def plot_decision_regions(X, y, classifier, test_idx=None, resolution=0.02):
# setup marker generator and color map
markers = ('s', 'x', 'o', '^', 'v')
colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')
cmap = ListedColormap(colors[:len(np.unique(y))])
# plot the decision surface
x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution), np.arange(x2_min, x2_max, resolution))
Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
Z = Z.reshape(xx1.shape)
plt.contourf(xx1, xx2, Z, alpha=0.4, cmap=cmap)
plt.xlim(xx1.min(), xx1.max())
plt.ylim(xx2.min(), xx2.max())
# plot class samples
for idx, cl in enumerate(np.unique(y)):
plt.scatter(x=X[y == cl, 0], y=X[y == cl, 1],alpha=0.8, c=cmap(idx),marker=markers[idx], label=cl)
# highlight test samples
if test_idx:
X_test, y_test = X[test_idx, :], y[test_idx]
plt.scatter(X_test[:, 0], X_test[:, 1], c='', alpha=1.0, linewidth=1, marker='o', s=55, label='test set')
from sklearn import datasets
import numpy as np
from sklearn.cross_validation import train_test_split
iris = datasets.load_iris() # 由於Iris是很有名的資料集,scikit-learn已經原生自帶了。
X = iris.data[:, [1, 2]]
y = iris.target # 標籤已經轉換成0,1,2了
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0) # 為了看模型在沒有見過資料集上的表現,隨機拿出資料集中30%的部分做測試
# 為了追求機器學習和最優化演算法的最佳效能,我們將特徵縮放
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
sc.fit(X_train) # 估算每個特徵的平均值和標準差
sc.mean_ # 檢視特徵的平均值,由於Iris我們只用了兩個特徵,所以結果是array([ 3.82857143, 1.22666667])
sc.scale_ # 檢視特徵的標準差,這個結果是array([ 1.79595918, 0.77769705])
X_train_std = sc.transform(X_train)
# 注意:這裡我們要用同樣的引數來標準化測試集,使得測試集和訓練集之間有可比性
X_test_std = sc.transform(X_test)
X_combined_std = np.vstack((X_train_std, X_test_std))
y_combined = np.hstack((y_train, y_test))
# 匯入SVC
from sklearn.svm import SVC
svm1 = SVC(kernel='linear', C=0.1, random_state=0) # 用線性核
svm1.fit(X_train_std, y_train)
svm2 = SVC(kernel='linear', C=10, random_state=0) # 用線性核
svm2.fit(X_train_std, y_train)
fig = plt.figure(figsize=(10,6))
ax1 = fig.add_subplot(1,2,1)
#ax2 = fig.add_subplot(1,2,2)
plot_decision_regions(X_combined_std, y_combined, classifier=svm1)
plt.xlabel('petal length [standardized]')
plt.ylabel('petal width [standardized]')
plt.title('C = 0.1')
ax2 = fig.add_subplot(1,2,2)
plot_decision_regions(X_combined_std, y_combined, classifier=svm2)
plt.xlabel('petal length [standardized]')
plt.ylabel('petal width [standardized]')
plt.title('C = 10')
plt.show()
svm1 = SVC(kernel='rbf', random_state=0, gamma=0.1, C=1.0) # 令gamma引數中的x分別等於0.1和10
svm1.fit(X_train_std, y_train)
svm2 = SVC(kernel='rbf', random_state=0, gamma=10, C=1.0)
svm2.fit(X_train_std, y_train)
fig = plt.figure(figsize=(10,6))
ax1 = fig.add_subplot(1,2,1)
plot_decision_regions(X_combined_std, y_combined, classifier=svm1)
plt.xlabel('petal length [standardized]')
plt.ylabel('petal width [standardized]')
plt.title('gamma = 0.1')
ax2 = fig.add_subplot(1,2,2)
plot_decision_regions(X_combined_std, y_combined, classifier=svm2)
plt.xlabel('petal length [standardized]')
plt.ylabel('petal width [standardized]')
plt.title('gamma = 10')
plt.show()