- SVM 分類器的誤差函式
- 分類誤差函式
- 距離誤差函式
- C 引數
- 非線性邊界的 SVM 分類器(核心方法)
- 多項式核心
- 徑向基函式(RBF)核心
原始碼檔案請點選此處!
SVM 分類器的誤差函式
SVM 使用兩條平行線,使用中心線作為參考系 \(L: \ w_1x_1 + w_2x_2 + b = 0\)。我們構造兩條線,一條在上面,一條在下面,分別為:
分類器由 \(L+\) 和 \(L-\) 組成。為訓練 SVM,我們需要為由兩條線組成的分類器構建一個誤差函式,期望達成的目標有兩個:
- 兩條線中的每一條都應儘可能對點進行分類。
- 兩條線應儘可能彼此遠離。
誤差函式表示如下:
分類誤差函式
點 \((x_1, x_2)\) 的預測函式為
顯然這是一個離散感知器,其中:
定義分類誤差函式如下:
例如,考慮標籤為 \(0\) 的點 \((4,3)\),兩個感知器給出的預測為:
可以看到兩個感知器均預測錯誤,此時分類誤差為:
距離誤差函式
若兩個線性方程如下:
根據兩條平行直線間的距離公式:
則這兩條平行線的垂直距離為:
此為距離誤差。注意到,當 \(w_1^2 + w_2^2\) 很大時,\(d\) 很小;當 \(w_1^2 + w_2^2\) 很小時,\(d\) 很大。因此 \(w_1^2 + w_2^2\) 是一個很好的誤差函式。
C 引數
很多時候我們希望 SVM 分類器能側重於分類誤差或距離誤差其中一個方面,那麼我們可以使用 C 引數:
C 引數如何控制兩者的呢?
- C 很大:誤差公式以分類誤差為主,SVM 分類器更側重於對點進行正確分類;
- C 很小:誤差公式以距離誤差為主,SVM 分類器更側重於保持線之間的距離。
下面是一個例子:
svm_c_001 = SVC(kernel='linear', C=0.01)
svm_c_001.fit(features, labels)
svm_c_100 = SVC(kernel='linear', C=100)
svm_c_100.fit(features, labels)
上圖為 C=0.01 的情況,下圖為 C=100 的情況:
非線性邊界的 SVM 分類器(核心方法)
多項式核心
- 在變數 \(x_1, x_2\) 使用 2 階多項式核心,就需要計算這些單項式:\(x_1, x_2, x_1^2, x_1x_2, x_2^2\),然後嘗試把它們線性組合起來,比如透過檢查發現這是一個有效的分類器公式:\(x_1^2 + x_2^2 = 1\)
- 這相當於將二維平面對映到一個五維平面,即點 \((x_1, x_2)\) 到點 \((x_1, x_2, x_1^2, x_1x_2, x_2^2)\) 的對映
- 類似地,在變數 \(x_1, x_2\) 使用 3 階多項式核心,就需要計算這些單項式:\(x_1, x_2, x_1^2, x_1x_2, x_2^2, x_1^3, x_1^2x_2, x_1x_2^2, x_2^3\),然後嘗試把它們線性組合起來,透過檢查發現一個有效的分類器公式
程式碼如下:
svm_degree_2 = SVC(kernel='poly', degree=2)
svm_degree_2.fit(features, labels)
print("[Degree=2] Accuracy=", svm_degree_2.score(features, labels))
svm_degree_4 = SVC(kernel='poly', degree=4)
svm_degree_4.fit(features, labels)
print("[Degree=4] Accuracy=", svm_degree_4.score(features, labels))
當分類器為 2 階多項式的執行結果:
當分類器為 4 階多項式的執行結果:
徑向基函式(RBF)核心
徑向基函式:
- 當變數只有一個時,最簡單的徑向基函式為 \(y = e^{-x^2}\),此函式看起來像標準正態分佈,函式凸起處為 \(x=0\)
- 當變數有 2 個時,最簡單的徑向基函式為 \(z = e^{-(x^2 + y^2)}\),此函式看起來像標準正態分佈,函式凸起處為 \((0,0)\)
- 當變數有 \(n\) 個時,基本徑向基函式為 \(y = e^{-(x_1^2 + ... + x_n^2)}\),\(n\) 維凸點以 0 為中心
- 若希望以點 \((p_1, ..., p_n)\) 為中心凸起,則基本徑向基函式為 \(y = e^{-[(x_1-p_1)^2 + ... + (x_n-p_n)^2]}\)
- 新增 \(\gamma\) 引數:\(y = e^{-\gamma[(x_1-p_1)^2 + ... + (x_n-p_n)^2]}\),用於控制擬合程度(形象理解,即調整凸起程度)
- 當 \(\gamma\) 值非常小時,模型會欠擬合
- 當 \(\gamma\) 值非常大時,模型會嚴重過擬合,合適的 \(\gamma\) 值非常重要
相似度公式:
- 對於點 \(p\) 和點 \(q\),\(相似度(p,q) = e^{-距離(p,q)^2}\)
- 一維資料集中,點 \(x_1\) 和點 \(x_2\) 的相似度為 \(e^{-(x_1-x_2)^2}\)
- 二維資料集中,點 \(A(x_1, y_1)\) 和點 \(B(x_2, y_2)\) 的相似度為 \(e^{-[(x_1-x_2)^2 + (y_1-y_2)^2]}\)
- 若該資料集有 \(n\) 個資料點,則應計算 \(n^2\) 個相似度;每個點到自身的相似度一定為 1;距離越近,相似度越高
有了相似度公式,就可以定義分類器了。假設資料集有 \(n\) 個資料點 \(X_i\),每個點對應標籤 \(L_i\)(取值為 0 或 1),則對於點 \(X\) 的分類預測如下:
形象理解:這相當於在一個二維平面上,為標記為 0 的點新增了一個“山谷”,為標記為 1 的點新增了一個“山峰”。對每個點都如此操作,最後使用閾值 0 畫出一個“海岸線”,這就是最後的分類邊界(boundary)。
程式碼如下:
svm_gamma_01 = SVC(kernel='rbf', gamma=0.1)
svm_gamma_01.fit(features, labels)
print("[Gamma=0.1] Accuracy=", svm_gamma_01.score(features, labels))
svm_gamma_1 = SVC(kernel='rbf', gamma=1)
svm_gamma_1.fit(features, labels)
print("[Gamma=1] Accuracy=", svm_gamma_1.score(features, labels))
svm_gamma_10 = SVC(kernel='rbf', gamma=10)
svm_gamma_10.fit(features, labels)
print("[Gamma=10] Accuracy=", svm_gamma_10.score(features, labels))
svm_gamma_100 = SVC(kernel='rbf', gamma=100)
svm_gamma_100.fit(features, labels)
print("[Gamma=100] Accuracy=", svm_gamma_100.score(features, labels))
\(\gamma=0.1\) 時的執行結果:
\(\gamma=1\) 時的執行結果:
\(\gamma=10\) 時的執行結果:
\(\gamma=100\) 時的執行結果: