0#07 SVM 支持向量机

0x00 数据准备

为了简单起见我就开始自己造数据,开始分类

线性可分
(x  ,y)     label
(-1 ,0)     0
(0  ,1)     1
(1  ,0)     1
补充数据:
(-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 笔算机器学习

我们先将点的坐标画出来


非SCV区分的方法.png

发现如果用我们已知的方法用一条直线区分,这条直线有很多条,但是很明显有些直线是毫无用处的,只要数据增加就会被修改.

于是我们就会想,是不是根据这些点,我们可以找到最适合的那条直线,

那什么是最适合的直线呢?
于是SVM定义,距离这条直线最近的点,与直线距离最大,也就是边界最大化.
比如说这个


边界最大化.png

于是我们把在边界上的点称为支持向量
比如这里的(-1,0),(0,1),(1,0)
如果删除或增加不是支持向量的点,不会影响结果.
但是我们这个例子是属于线性可分的例子.

还有一些情况是先行不可分,
比如
第二组数据

非线性可分.png

很明显正常的分发是化成圆圈,不能用一条直线进行区分
于是我们想办法把该坐标投射到3维度中去
比如使第三维度z=(x12+x22)
或者z=np.exp(-(x12+x22))
投影之后,就是一个线性可分的3维图形
区分非线性可分.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 进行区分

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]])

"""
这一步是提取特征值,我们还没有基础,所以只需要知道,这一部试讲原本的近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:惩罚参数C(越大,边界越硬)
kernel:内核类型。 
        'linear':线性
        'poly':表示算法使用多项式核函数
        'rbf':表示算法使用高斯核函数,分类非线性可分的样本的分类
        'sigmoid':
        'precomputed'
degree:  多项式核函数的次数('poly')。 被所有其他内核忽略。
gamma:  'rbf','poly'和'sigmoid'的核系数。 如果gamma是'auto',那么将使用1 / n_features。
"""
svc = SVC(kernel='rbf',class_weight = 'balanced')
model=make_pipeline(pca,svc)

"""
分割训练集和测试集合
"""
from sklearn.cross_validation import train_test_split
xtrain,xtest,ytrain,ytest=train_test_split(faces.data,faces.target,random_state=0)

"""
使用网格法,找出最适合的参数
注意参数格式:
scv__C
函数名称 2*下划线 函数的变量名称
"""
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_
两个边分别含有的支持向量的个数
model.n_support_
赋予特征的权重(原始问题中的系数)。 这仅适用于线性内核。
model.coef_

0x04 一些想法

  1. 支持向量机是深度学习之前最成功的算法
  2. 支持向量机不仅能解决线性分类问题,还能解决非线性分类问题.
  3. 训练好的模型的复杂度,由支持向量个数决定,而不是数据的维度决定的
  4. SVM不太容易过拟合,因为处理支持向量的点,其他点都不重要
  5. 对于一些超参数,比如核函数
    如果线性可分,我们使用'linear'
    如果线性不可分,我们使用'rbf'
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • "清明时节雨纷纷,路上行人欲断魂。"这是古诗里的清明节。 "囡囡,乖,过来,给祖宗跪下。先三拜三鞠躬,再三跪九叩头...
    艾七的时光阅读 1,234评论 0 1
  • 一、自定义View需要继承UIView 注意的几点问题: 1.initWithFrame init和initWit...
    宙斯YY阅读 5,711评论 0 1
  • 今天我们完成了老大指定的任务29分提前完成,我们很高兴,大家也很给力,一天7分的好成绩为我们的任务化了一个完美的句...
    LK_245a阅读 1,144评论 0 0

友情链接更多精彩内容