机器学习入门:支持向量机

1、实验描述

  • 本实验提供一些人手写的数字图片,并使用SVM 对手写数据集进行识别,并将识别结果用图展示出来。接着再使用交叉验证的方式,寻找算法的最优参数。
  • 实验时长:45分钟
  • 主要步骤:
  • 加载训练数据
  • 加载测试数据
  • 数据集预处理
  • 绘制训练数据、测试数据的灰度图
  • 模型训练
  • 模型的预测
  • 模型评估
  • 使用交叉验证 确定最优参数

2、实验环境

  • 虚拟机数量:1
  • 系统版本:CentOS 7.5
  • scikit-learn版本: 0.19.2
  • numpy版本:1.15.1
  • matplotlib版本:2.2.3
  • python版本:3.5
  • IPython版本:6.5.0

3、相关技能

  • Python编程
  • Scikit-learn编程
  • Matplotlib编程
  • Numpy编程
  • SVM建模

4、相关知识点

  • 支持向量机
  • 特征空间
  • 核空间
  • 交叉验证
  • 模型创建
  • 训练模型
  • 模型预测

5、实现效果

  • 支持向量机对手写数字图片识别效果如下图所示:

基于支持向量机的车辆目标检测_支持向量机


图 1

6、实验步骤

6.1支持向量机概念:

6.1.1假设我们要通过一条线将某个任务分成两类。

6.1.1.1那么有无数多条线可以完成这个任务。

6.1.1.2在SVM中,我们寻找一条最优的分界线使得它到两边的margin都最大。

6.1.1.3在这种情况下处于边缘,能够确定该线的位置的几个数据点,就叫support vector,这也是此分类算法名字的由来。

6.1.2核函数:

6.1.2.1可以使用核函数,将原始输入空间映射到新的特征空间,从而,使得原本线性不可分的样本能在核空间可分。

6.1.2.2常见的核函数:多项式核函数、高斯核RBF函数、Sigmoid核函数。在实际应用中,往往依赖先验领域知识/交叉验证等方案才能选择有效的核函数。若没有更多先验信息时,则使用高斯核函数

6.2进入Anaconda创建的虚拟环境“ML”

6.2.1从zkpk的公共目录下拷贝实验所需的数据文件到zkpk的家目录下

[zkpk@master ~]$ cd
[zkpk@master ~]$ cp /home/zkpk/experiment/optdigits.tra /home/zkpk
[zkpk@master ~]$ cp /home/zkpk/experiment/optdigits.tes /home/zkpk

6.2.2数据集介绍: 该数据来自于43人的手写数字,其中30人的用于训练,另外13 人的用于测试。

6.2.2.1训练集共3823个图片,测试集共1797个图片。

6.2.2.2每个图片为8×8的灰度图像,像素值从0到16,其中,16代表全黑,0代表全亮

6.2.3在zkpk的家目录下执行如下命令

[zkpk@master ~]$ cd
[zkpk@master ~]$ source activate ML
(ML)[zkpk@ master ML]$

6.2.4此时已经进入虚拟环境。键入如下命令,进入ipython交互是编程环境

(ML) [zkpk@ master ML]$ ipython
Python 3.5.4 |Anaconda, Inc.| (default, Nov  3 2017, 20:01:27)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.
In [1]:

6.3在Ipython交互式编程环境中开始实验

6.3.1导入实验所需的包

In [1]: import numpy as np
   ...: import pandas as pd
   ...: from sklearn import svm
   ...: import matplotlib.colors
   ...: import matplotlib.pyplot as plt
   ...: from PIL import Image	# PIL: Python image library
   ...: from sklearn.metrics import accuracy_score
   ...: import os
   ...: from sklearn.model_selection import train_test_split
   ...: from sklearn.model_selection import GridSearchCV
   ...: from time import time

6.3.2加载训练集数据

6.3.2.1指定数据分隔符为’,’

In [13]: data = np.loadtxt('optdigits.tra', dtype=np.float, delimiter=',')	# loadtxt方法返回ndarray;dtype参数用于指定返回的数组中元素类型;delimiter指定分割符
    ...: data.shape

基于支持向量机的车辆目标检测_核函数_02


图 2

6.3.2.2读取对应的x, y 标签

In [14]: x, y = np.split(data, (-1, ), axis=1) # split方法将ndarray进行切分;axis=1按纵向将data进行切分;读取数据,最后一列作为标签,赋给y
    ...: x.shape
    ...: y.shape

6.3.2.3将y标签转换成无符号的整形

In [15]: y = y.ravel().astype(np.int)   # ravel方法,将ndarray转换成一个压平的数组;astype将数组所有元素转换成指定的int类型

6.3.2.4查看y中都有哪些标签值

In [16]: np.unique(y)

基于支持向量机的车辆目标检测_基于支持向量机的车辆目标检测_03


图 3

6.3.2.5查看x中唯一的元素有哪些

In [17]: np.unique(x)

基于支持向量机的车辆目标检测_基于支持向量机的车辆目标检测_04


图 4

6.3.2.6将图像重新映射成8*8 大小,

In [21]: images = x.reshape(-1, 8, 8)   # 图像大小映射成8*8
    ...: images.shape

基于支持向量机的车辆目标检测_核函数_05


图 5

6.3.3对测试集做同样的操作

In [22]: print('Load Test Data Start...')
    ...: data = np.loadtxt('optdigits.tes', dtype=np.float, delimiter=',')
    ...: x_test, y_test = np.split(data, (-1, ), axis=1)
    ...: print(y_test.shape)
    ...: images_test = x_test.reshape(-1, 8, 8)
    ...: y_test = y_test.ravel().astype(np.int)
    ...: print('Load Data OK...')

基于支持向量机的车辆目标检测_python_06


图 6

6.3.4划分数据集

In [23]: x, x_test, y, y_test = train_test_split(x, y, test_size=0.4, random_state=1)

6.3.5查看训练数据和测试数据的灰度图

In [24]: # 训练数据
    ...: for index, image in enumerate(images[:16]):	# 查看头16个图
    ...:     plt.subplot(4,8,index+1)	# 增加子图,并指定子图在画布中的位置
    ...:     plt.imshow(image, cmap=plt.cm.gray_r,interpolation='nearest')	# imshow方法,展示一张图;interpolation='nearest'使用最邻近插值法
    ...:     plt.title(u'train_images: %i' %y[index])
    ...: 
    ...: # 测试数据
    ...: for index, image in enumerate(images_test[:16]):
    ...:     plt.subplot(4,8,index+17)
    ...:     plt.imshow(image,cmap=plt.cm.gray_r,interpolation='nearest')
    ...:     plt.title(u'test_images: %i' % y_test[index])
    ...:     plt.tight_layout()
    ...: plt.show()

基于支持向量机的车辆目标检测_基于支持向量机的车辆目标检测_07


图 7

6.4使用交叉验证确定模型最优参数

6.4.1定义模型参数字典

6.4.1.1SVM模型有两个非常重要的参数C与gamma。其中C是惩罚系数,即对误差的宽容度。C越高,说明越不能容忍出现误差,容易过拟合。C越小,容易欠拟合。C过大或过小,都会导致泛化能力变差

6.4.1.2gamma是选择RBF函数作为kernel后,该函数自带的一个参数。决定了数据映射到新的特征空间后的分布,gamma越大,支持向量越少,gamma值越小,支持向量越多。支持向量的个数影响训练与预测的速度。

In [31]: params = {'C':np.logspace(0, 3, 7), 'gamma':np.logspace(-5, 0, 11)}	# logspace方法创建等比数列

6.4.2使用GridSearchCV构建模型

6.4.2.1使用‘rbf’kernel,使用3折交叉验证。

In [32]: model = GridSearchCV(svm.SVC(kernel='rbf'), param_grid=params, cv=3)

6.4.3使用模型训练

6.4.3.1在训练集上使用模型训练

In [33]: print ('Start Learning...')
    ...: t0 = time()
    ...: model.fit(x, y)
    ...:

基于支持向量机的车辆目标检测_核函数_08


图 8

6.4.3.2打印训练的相关信息

In [35]: t1 = time()
    ...: t = t1 - t0
    ...: print ('训练+CV耗时:%d分钟%.3f秒' % (int(t/60), t - 60*int(t/60)))

基于支持向量机的车辆目标检测_机器学习_09


图 9

6.4.3.3打印模型最优参数

In [36]: print ('最优参数:\t', model.best_params_)

基于支持向量机的车辆目标检测_支持向量机_10


图 10

6.5对模型进行评估

In [37]: print ('Learning is OK...')
    ...: print ('训练集准确率:', accuracy_score(y, model.predict(x)))
    ...: y_hat = model.predict(x_test)
    ...: print ('测试集准确率:', accuracy_score(y_test, model.predict(x_test)))
    ...: print (y_hat)
    ...: print (y_test)

基于支持向量机的车辆目标检测_基于支持向量机的车辆目标检测_11


图 11

7、参考答案

  • 代码清单svm_case.py

基于支持向量机的车辆目标检测_核函数_12


图 12

8、总结

完成本次实验,需要了解、掌握关于支持向量机的相关知识,以及动手编程。实验最后,我们通过GridSearchCV搜索模型的最优参数,使得模型的精度得到提升。在自己做的时候,可以配置不同的参数字典获得模型的最优参数。同样,本实验涉及大量代码编程,需要大家多动手编程,有不理解的方法、类能够自行查阅相关api文档解决。