0x00 數(shù)據(jù)準備
為了簡單起見我就開始自己造數(shù)據(jù),開始分類
線性可分
(x ,y) label
(-1 ,0) 0
(0 ,1) 1
(1 ,0) 1
補充數(shù)據(jù):
(-2,-3) 0
(1 ,1) 1
線性不可分
(x ,y) label
(0 ,0) 0
(1 ,0) 0
(0 ,1) 0
(-1 ,0) 0
(0 ,-1) 0
(0 ,2) 1
(1 ,2) 1
(2 ,2) 1
(2 ,1) 1
(2 ,0) 1
(2 ,-1) 1
(2 ,-2) 1
(1 ,-2) 1
(0 ,-2) 1
(-1 ,-2) 1
(-2 ,-2) 1
(-2 ,-1) 1
(-2 ,0) 1
(-2 ,1) 1
(-2 ,2) 1
(-1 ,2) 1
因為SVM支持向量機非常強大,所以能做的事情非常多,實例中我們會以fetch_lfw_people作為例子
0x01 筆算機器學(xué)習(xí)
我們先將點的坐標畫出來
非SCV區(qū)分的方法.png
發(fā)現(xiàn)如果用我們已知的方法用一條直線區(qū)分,這條直線有很多條,但是很明顯有些直線是毫無用處的,只要數(shù)據(jù)增加就會被修改.
于是我們就會想,是不是根據(jù)這些點,我們可以找到最適合的那條直線,
那什么是最適合的直線呢?
于是SVM定義,距離這條直線最近的點,與直線距離最大,也就是邊界最大化.
比如說這個
邊界最大化.png
于是我們把在邊界上的點稱為支持向量
比如這里的(-1,0),(0,1),(1,0)
如果刪除或增加不是支持向量的點,不會影響結(jié)果.
但是我們這個例子是屬于線性可分的例子.
還有一些情況是先行不可分,
比如
第二組數(shù)據(jù)
非線性可分.png
很明顯正常的分發(fā)是化成圓圈,不能用一條直線進行區(qū)分
于是我們想辦法把該坐標投射到3維度中去
比如使第三維度z=(x12+x22)
或者z=np.exp(-(x12+x22))
投影之后,就是一個線性可分的3維圖形
區(qū)分非線性可分.png
代碼如下
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
x=np.array([[0 ,0],[1 ,0],[0 ,1],[-1 ,0],[0 ,-1],[0 ,2],[1 ,2],[2 ,2],[2 ,1],[2 ,0],[2 ,-1],[2 ,-2],[1 ,-2],[0 ,-2],[-1 ,-2],[-2 ,-2],[-2 ,-1],[-2 ,0],[-2 ,1],[-2 ,2],[-1 ,2]])
y=np.array([0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1])
plt.figure(figsize=(6,6))
plt.scatter(x[:,0],x[:,1],c=y,cmap='autumn',s=500)
z=np.exp(-(x**2).sum(1))
from mpl_toolkits import mplot3d
from ipywidgets import interact,fixed
def plot_3D(elev=30,azim=30,x=x,y=y):
ax=plt.subplot(projection='3d')
ax.scatter3D(x[:,0],x[:,1],z,c=y,s=50,cmap='autumn')
ax.view_init(elev=elev,azim=azim)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('r')
from mpl_toolkits import mplot3d
def plot_3D(elev=30,azim=30,x=x,y=y):
ax=plt.subplot(projection='3d')
ax.scatter3D(x[:,0],x[:,1],r,c=y,s=50,cmap='autumn')
ax.view_init(elev=elev,azim=azim)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('r')
interact(plot_3D,elev=(-90,90),azim=(-180,180),x=fixed(x),y=fixed(y));
0x03 使用支持向量機
我們開始使用 SVM 進行區(qū)分
from sklearn.datasets import fetch_lfw_people
"""
下載的過程非常緩慢,所以提前下載更加合適
圖片地址:
https://ndownloader.figshare.com/files/5976018 #lfw.tgz
https://ndownloader.figshare.com/files/5976015 #lfw-funneled.tgz
https://ndownloader.figshare.com/files/5976012 #pairsDevTrain.txt
https://ndownloader.figshare.com/files/5976009 #pairsDevTest.txt
https://ndownloader.figshare.com/files/5976006 #pairs.txt
保存到 ~/scikit_learn_data/lfw_home
然后將lfw.tgz與lfw-funneled.tgz解壓
"""
faces = fetch_lfw_people(min_faces_per_person=60,download_if_missing=True)
print(faces.target_names)
print(faces.images.shape)
import matplotlib.pyplot as plt
fig,ax = plt.subplots(3,5,)
for i, axi in enumerate(ax.flat):
axi.imshow(faces.images[i],cmap='bone')
axi.set(xticks=[],yticks=[],xlabel=faces.target_names[faces.target[i]])
"""
這一步是提取特征值,我們還沒有基礎(chǔ),所以只需要知道,這一部試講原本的近3000個像素點,提取其中的150個
"""
from sklearn.svm import SVC
from sklearn.decomposition import RandomizedPCA
from sklearn.pipeline import make_pipeline
pca = RandomizedPCA(n_components=150,whiten=True,random_state=0)
"""
C:懲罰參數(shù)C(越大,邊界越硬)
kernel:內(nèi)核類型。
'linear':線性
'poly':表示算法使用多項式核函數(shù)
'rbf':表示算法使用高斯核函數(shù),分類非線性可分的樣本的分類
'sigmoid':
'precomputed'
degree: 多項式核函數(shù)的次數(shù)('poly')外厂。 被所有其他內(nèi)核忽略冕象。
gamma: 'rbf','poly'和'sigmoid'的核系數(shù)汁蝶。 如果gamma是'auto'渐扮,那么將使用1 / n_features。
"""
svc = SVC(kernel='rbf',class_weight = 'balanced')
model=make_pipeline(pca,svc)
"""
分割訓(xùn)練集和測試集合
"""
from sklearn.cross_validation import train_test_split
xtrain,xtest,ytrain,ytest=train_test_split(faces.data,faces.target,random_state=0)
"""
使用網(wǎng)格法,找出最適合的參數(shù)
注意參數(shù)格式:
scv__C
函數(shù)名稱 2*下劃線 函數(shù)的變量名稱
"""
from sklearn.grid_search import GridSearchCV
param_grid ={
'svc__C':[1,5,10,50],
'svc__gamma':[0.0001,0.0005,0.001,0.005]}
grid = GridSearchCV(model,param_grid)
grid.fit(xtrain,ytrain)
print(grid.best_params_)
model = grid.best_estimator_
yfit = model.predict(xtest)
"""
制作文字報告
比如:
precision recall f1-score support
Ariel Sharon 0.92 0.69 0.79 16
Colin Powell 0.84 0.87 0.85 61
Donald Rumsfeld 0.75 0.69 0.72 35
George W Bush 0.78 0.97 0.86 125
Gerhard Schroeder 0.90 0.66 0.76 29
Hugo Chavez 1.00 0.63 0.77 19
Junichiro Koizumi 1.00 0.76 0.87 17
Tony Blair 0.96 0.77 0.86 35
avg / total 0.85 0.83 0.83 337
"""
from sklearn.metrics import classification_report
print(classification_report(ytest,yfit,target_names=faces.target_names))
值得一提的是,對于sklearn的支持向量機
我們可以用方法將支持向量顯示出來
一些方法:
支持向量的下標
model.support_
支持向量具體的坐標
model.support_vectors_
兩個邊分別含有的支持向量的個數(shù)
model.n_support_
賦予特征的權(quán)重(原始問題中的系數(shù))掖棉。 這僅適用于線性內(nèi)核墓律。
model.coef_
0x04 一些想法
- 支持向量機是深度學(xué)習(xí)之前最成功的算法
- 支持向量機不僅能解決線性分類問題,還能解決非線性分類問題.
- 訓(xùn)練好的模型的復(fù)雜度,由支持向量個數(shù)決定,而不是數(shù)據(jù)的維度決定的
- SVM不太容易過擬合,因為處理支持向量的點,其他點都不重要
- 對于一些超參數(shù),比如核函數(shù)
如果線性可分,我們使用'linear'
如果線性不可分,我們使用'rbf'