Python高級--支持向量機SVM

一、支持向量機原理

1)支持向量機基本概念

Support Vector Machine

支持向量機,其含義是通過支持向量運算的分類器。
其中“機”的意思是機器,可以理解爲分類器。 那麼什麼是支持向量呢?在求解的過程中,會發現只根據部分數據就可以確定分類器,這些數據稱爲支持向量。

見下圖,在一個二維環境中,其中點R,S,G點和其它靠近中間黑線的點可以看作爲支持向量,它們可以決定分類器,也就是黑線的具體參數。
這裏寫圖片描述

2)舉例說明

在很久以前的七夕,大俠要去救他的女神,但魔鬼和他玩了一個遊戲。

魔鬼在桌子上似乎有規律放了兩種顏色的球,說:“你能不能分開它們?要求:儘量在放更多球之後,仍然適用。”

這裏寫圖片描述

於是大俠這樣放,乾的不錯?這裏寫圖片描述

然後魔鬼,又在桌上放了更多的球,似乎有一個球站錯了陣營這裏寫圖片描述

SVM就是試圖把棍放在最佳位置,好讓在棍的兩邊有儘可能大的間隙這裏寫圖片描述

現在即使魔鬼放了更多的球,棍仍然是一個好的分界線這裏寫圖片描述

魔鬼看到大俠已經學會了一個trick,於是魔鬼給了大俠一個新的挑戰

這裏寫圖片描述

現在,大俠沒有棍可以很好幫他分開兩種球了,現在怎麼辦呢?當然像所有武俠片中一樣大俠桌子一拍,球飛到空中。然後,憑藉大俠的輕功,大俠抓起一張紙,插到了兩種球的中間

這裏寫圖片描述

現在,從魔鬼的角度看這些球,這些球看起來像是被一條曲線分開了這裏寫圖片描述

愚蠢的人類,把球叫做 「data」
把棍子叫做 「classifier」
最大間隙的技巧叫做「optimization (最優化)」
幾種劃分方式叫做「kernelling內核」
那張紙叫做「hyperplane超平面」

3)三種內核的效果比較

1、Linear核

線性函數
其實就是畫直線(一次方)

主要用於線性可分的情形。參數少,速度快,適用於一般數據
這裏寫圖片描述

2、RBF核

徑向基函數 (Radial Basis Function 簡稱 RBF)
基於半徑的函數
其實就是畫曲線(二次方)

主要用於線性不可分的情形。參數多,分類結果非常依賴於參數的情況。

這裏寫圖片描述

3、polynomial model

參數較多,在另外兩種都不適用的時候選擇
(多項式 n次方)(一般來說什麼都畫不好)
這裏寫圖片描述

4)優缺點

1、論效果

svm不像knn那樣容易過擬合 有很好的泛化能力
svm是找兩類之間的最大距離 所以不像線性迴歸那樣容易欠擬合

2、論效果

論效率 svm和knn一樣,每個點都要計算距離,計算量比較大,所以一般針對小樣本數據

3、總結

總結: SVM是一種主要針對小樣本數據進行學習、分類和迴歸的方法

二、使用SVM畫出決策邊界

對兩堆數據進行分類,並畫出

import numpy as np
import pandas as pd
from pandas import Series,DataFrame
import matplotlib.pyplot as plt

支持向量機導包

from sklearn.svm import SVC

1)創造數據

產生兩堆數據 20個樣本,每個樣本有兩個特徵

## 以0爲中心 標準差是1的 一堆正太分佈的數據
# 分開兩堆數據的中心
dot1 = np.random.randn(20,2)-[1,4]  # 將中心向左下移動
dot2 = np.random.randn(20,2)+[2,3]  # 將中心向 右上移動

將產生的數據繪製查看

plt.scatter(dot1[:,0],dot1[:,1])
plt.scatter(dot2[:,0],dot2[:,1])

這裏寫圖片描述

2)合併數據作爲訓練集並創建目標值

X_train = np.concatenate((dot1,dot2))
# dot1的目標值是0 dot2的目標值是1
# 則y_train中前面20個是0 後面20個是1
y_train = [0]*20 + [1]*20

根據訓練集和目標值繪圖

plt.scatter(X_train[:,0],X_train[:,1],c=y_train)

這裏寫圖片描述

3)使用內核爲linear的支持向量機模型繪製超平面分隔線

1、創建內核爲linear的模型並訓練

svc = SVC(kernel='linear')
svc.fit(X_train,y_train)

4)超平面

f(x) = w*x + b

1、提取係數獲取分隔線斜率

svc.coef_

array([[0.22671513, 0.56914011]])

這兩個分別是兩個特徵的權重,但這並不是我們想要的
第一個權重:w0 是 y_train/X_train[:,0]
第二個權重:w1 是 y_train/X_train[:,1]

現在要求的是將x0作爲橫軸,x1作爲縱軸
這條線的斜率爲 x1 / x0
w = w1 / w0
w = y_train/X_train[:,1] / y_train/X_train[:,0]

svc.coef_
svc.coef_[0,0]
svc.coef_[0,1]
w = -svc.coef_[0,0]/svc.coef_[0,1]

2、提取係數獲取分隔線截距

svc.intercept_ 

array([0.00599865])

這裏的截距是目標值上面的截距,但是我們現在要找的是x1上的截距
X_train[:,1]和y_train的 斜率是 w1 svc.coef_[0,1]
w1已知 在y_train上的截距也是已知的 求在X_train[:,1]上的截距
svc.intercept_/-??? = svc.coef_[0,1]
??? = -svc.intercept_/svc.coef_[0,1]
求出這條分隔線的斜率

b = -svc.intercept_[0]/svc.coef_[0,1]

-0.010539844074062357

5)畫出這條分割線

1、創建分割線的x值

x = np.linspace(-4,4,100)

2、算出分割線的y值並繪圖顯示

y = w*x+b

plt.scatter(X_train[:,0],X_train[:,1],c=y_train)
plt.plot(x,y)

這裏寫圖片描述

6)支持向量

使用svc.support_vectors_找出支持向量,即離分割線最近的點集合,繪製出支持向量的所有點

1、找出支持向量的點

svevtor = svc.support_vectors_
svevtor

array([[-0.02126202, -1.7591068 ],
       [ 1.18685372,  1.2737174 ]])

2、繪製出支持向量的點

plt.scatter(svevtor[:,0],svevtor[:,1],c='r',alpha=0.3,s=100)  # 支持向量
plt.scatter(X_train[:,0],X_train[:,1],c=y_train)  # 所有點
plt.plot(x,y)

這裏寫圖片描述

7)繪製經過兩個支持向量的點

已知 斜率 和 經過的點 畫線
把兩個直線的 b求出來 即可 b1 b2

# 第一個支持向量點
p1 = svevtor[0]
p1
#
p2 = svevtor[1]
p2
#已知k,x,y 求b
y = k*x+b
b = y-k*x

b1 = p1[1]-w*p1[0]
b1

b2 = p2[1]-w*p2[0]
b2

求出y1 y2 畫出兩條經過支持向量的線

y1 = w*x+b1
y2 = w*x+b2

plt.scatter(svevtor[:,0],svevtor[:,1],c='r',alpha=0.3,s=100)  # 支持向量
plt.scatter(X_train[:,0],X_train[:,1],c=y_train)  # 所有點
plt.plot(x,y)  # 分類的中心線
# 分類的上邊界 和 下邊界
plt.plot(x,y1,ls='--')
plt.plot(x,y2,ls='--')

這裏寫圖片描述

三、使用多種核函數對iris數據進行分類

1)導包

from sklearn.svm import SVC 

2)數據獲取

只提取兩個特徵,方便畫圖

from sklearn.datasets import load_iris
iris = load_iris()
data = iris.data[:,:2]
target = iris.target

3)創建模型並訓練

l = SVC(kernel='linear')
r = SVC(kernel='rbf')  # 二次曲線
p = SVC(kernel='poly')  # 高次曲線

l.fit(data,target)
r.fit(data,target)
p.fit(data,target)

4)創建測試集

我們取畫布上的所有點進行測試

x = np.linspace(data[:,0].min(),data[:,0].max(),200)
y = np.linspace(data[:,1].min(),data[:,1].max(),200)

xx,yy =np.meshgrid(x,y)

X_test = np.c_[xx.flatten(),yy.flatten()]

5)預測並繪圖

1、用linear內核做預測

y1_ = l.predict(X_test)  # 用linear內核做預測
plt.scatter(X_test[:,0],X_test[:,1],c=y1_)

這裏寫圖片描述

2、用rbf內核做預測

y2_ = r.predict(X_test)  # 用rbf內核做預測
plt.scatter(X_test[:,0],X_test[:,1],c=y2_)

這裏寫圖片描述

3、用poly內核做預測

y3_ = p.predict(X_test)  # 用poly內核做預測
plt.scatter(X_test[:,0],X_test[:,1],c=y3_)

這裏寫圖片描述

四、使用SVM多種核函數進行迴歸

1)導包

from sklearn.svm import SVR 

2)創建樣本點並生成sin曲線

x = np.linspace(-np.pi,np.pi,40)
y = np.sin(x)
plt.scatter(x,y)

這裏寫圖片描述

3)數據加噪

每隔四個添加一個噪聲

noise = np.random.random(10) - 0.5  # [-0.5, 0.5)
y[::4]+=noise

這裏寫圖片描述

4)建立SVR模型並訓練數據

# 獲取模型
l = SVR(kernel='linear')
r = SVR(kernel='rbf')
p = SVR(kernel='poly')
# 訓練模型
l.fit(x.reshape(-1,1),y)
r.fit(x.reshape(-1,1),y)
p.fit(x.reshape(-1,1),y)

5)創建測試數據並分別預測

# 生成一些測試的X_test
X_test = np.linspace(-np.pi,np.pi,15).reshape(-1,1)
y1_ = l.predict(X_test)
y2_ = r.predict(X_test)
y3_ = p.predict(X_test)

6)繪製比較三種不同內核的迴歸效果

plt.figure(figsize=(12,6))
plt.scatter(x,y,c='k',label='real')  # 真實數據
plt.plot(X_test,y1_,c='r',label='linear')  # linear內核
plt.plot(X_test,y2_,c='g',label='rbf')   # 二次曲線
plt.plot(X_test,y3_,c='b',label='poly')   # 高次曲線
plt.legend()  #顯示圖例

這裏寫圖片描述
由圖像可以觀察得出rbf 對於曲線效果是最好的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章