1. 程式人生 > >深度學習基礎系列(四)之 sklearn SVM

深度學習基礎系列(四)之 sklearn SVM

1、背景

1.1 最早是由 Vladimir N. Vapnik 和 Alexey Ya. Chervonenkis 在1963年提出

1.2 目前的版本(soft margin)是由Corinna Cortes 和 Vapnik在1993年提出,並在1995年發表

1.3 深度學習(2012)出現之前,SVM被認為機器學習中近十幾年來最成功,表現最好的演算法

2、舉例

2.1 例子
這裡寫圖片描述

兩類?哪條線最好?

2.2 SVM尋找區分兩類的超平面(hyper plane), 使邊際(margin)最大

這裡寫圖片描述

總共可以有多少個可能的超平面?無數條

如何選取使邊際(margin)最大的超平面 (Max Margin Hyperplane)?

超平面到一側最近點的距離等於到另一側最近點的距離,兩側的兩個超平面平行

3、線性可區分(linear separable) 和 線性不可區分 (linear inseparable)

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

4、定義與公式建立

超平面可以定義為:
這裡寫圖片描述

W: weight vectot, 這裡寫圖片描述
n 是特徵值的個數
X: 訓練例項
b: bias

這裡寫圖片描述

4.1 假設2維特徵向量:X = (x1, X2)
把 b 想象為額外的 wight

超平面方程變為:這裡寫圖片描述

所有超平面右上方的點滿足:這裡寫圖片描述
所有超平面左下方的點滿足:這裡寫圖片描述

調整weight,使超平面定義邊際的兩邊:
這裡寫圖片描述

綜合以上兩式,得到(1):
這裡寫圖片描述

所有坐落在邊際的兩邊的的超平面上的被稱作”支援向量(support vectors)

分界的超平面和H1或H2上任意一點的距離為 1/|| W || (其中||W||是向量的範數(norm))

這裡寫圖片描述

所以,最大邊際距離為:2 / || W ||

5、求解

5.1 SVM如何找出最大邊際的超平面呢(MMH)?

利用一些數學推倒,以上公式 (1)可變為有限制的凸優化問題(convex quadratic optimization) 利用 Karush-Kuhn-Tucker (KKT)條件和拉格朗日公式,可以推出MMH可以被表示為以下“決定邊界 (decision boundary)”

其中,

{yi} 是支援向量點{Xi} (support vector)的類別標記(class label)

{X^T}是要測試的例項

{alpha _i} 和 {b0} 都是單一數值型引數,由以上提到的最有演算法得出

l 是支援向量點的個數

5.2 對於任何測試(要歸類的)例項,帶入以上公式,得出的符號是正還是負決定

這裡寫圖片描述

這裡寫圖片描述

6、程式碼:

簡單例項:

In [65]:  from sklearn import svm

In [66]: x = [[2, 0], [1, 1], [2, 3]]

In [67]: y = [0, 0, 1]

In [68]: clf = svm.SVC(kernel = 'linear')

In [69]: clf.fit(x, y)
Out[69]: 
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
  decision_function_shape=None, degree=3, gamma='auto', kernel='linear',
  max_iter=-1, probability=False, random_state=None, shrinking=True,
  tol=0.001, verbose=False)

In [70]: print(clf)
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
  decision_function_shape=None, degree=3, gamma='auto', kernel='linear',
  max_iter=-1, probability=False, random_state=None, shrinking=True,
  tol=0.001, verbose=False)

In [71]: clf.support_vectors_
Out[71]: 
array([[ 1.,  1.],
       [ 2.,  3.]])

In [72]: clf.support_
Out[72]: array([1, 2], dtype=int32)

In [73]: clf.n_support_
Out[73]: array([1, 1], dtype=int32)

圖例:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue May 30 09:27:21 2017

@author: xiaolian
"""



print(__doc__)

import numpy as np
import pylab as pl
from sklearn import svm

# we create 40 separable points
np.random.seed(1)
X = np.r_[np.random.randn(20, 2) - [2, 2], np.random.randn(20, 2) + [2, 2]]
Y = [0] * 20 + [1] * 20

# fit the model
clf = svm.SVC(kernel='linear')
clf.fit(X, Y)

# get the separating hyperplane
w = clf.coef_[0]
a = -w[0] / w[1]
xx = np.linspace(-4, 4)
yy = a * xx - (clf.intercept_[0]) / w[1]

# plot the parallels to the separating hyperplane that pass through the
# support vectors
b = clf.support_vectors_[0]
yy_down = a * xx + (b[1] - a * b[0])
b = clf.support_vectors_[-1]
yy_up = a * xx + (b[1] - a * b[0])


print("w: ", w)
print("a: ", a)
# print " xx: ", xx
# print " yy: ", yy
print("support_vectors_: ", clf.support_vectors_)
print("clf.coef_: ", clf.coef_)

# In scikit-learn coef_ attribute holds the vectors of the separating hyperplanes for linear models. It has shape (n_classes, n_features) if n_classes > 1 (multi-class one-vs-all) and (1, n_features) for binary classification.
# 
# In this toy binary classification example, n_features == 2, hence w = coef_[0] is the vector orthogonal to the hyperplane (the hyperplane is fully defined by it + the intercept).
# 
# To plot this hyperplane in the 2D case (any hyperplane of a 2D plane is a 1D line), we want to find a f as in y = f(x) = a.x + b. In this case a is the slope of the line and can be computed by a = -w[0] / w[1].




# plot the line, the points, and the nearest vectors to the plane
pl.plot(xx, yy, 'k-')
pl.plot(xx, yy_down, 'k--')
pl.plot(xx, yy_up, 'k--')

pl.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1],
           s=80, facecolors='none')
pl.scatter(X[:, 0], X[:, 1], c=Y, cmap=pl.cm.Paired)

pl.axis('tight')
pl.show()

輸出:

這裡寫圖片描述