机器学习入门:支持向量机
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
图 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)
图 3
6.3.2.5查看x中唯一的元素有哪些
In [17]: np.unique(x)
图 4
6.3.2.6将图像重新映射成8*8 大小,
In [21]: images = x.reshape(-1, 8, 8) # 图像大小映射成8*8
...: images.shape
图 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...')
图 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()
图 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)
...:
图 8
6.4.3.2打印训练的相关信息
In [35]: t1 = time()
...: t = t1 - t0
...: print ('训练+CV耗时:%d分钟%.3f秒' % (int(t/60), t - 60*int(t/60)))
图 9
6.4.3.3打印模型最优参数
In [36]: print ('最优参数:\t', model.best_params_)
图 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
7、参考答案
- 代码清单svm_case.py
图 12
8、总结
完成本次实验,需要了解、掌握关于支持向量机的相关知识,以及动手编程。实验最后,我们通过GridSearchCV搜索模型的最优参数,使得模型的精度得到提升。在自己做的时候,可以配置不同的参数字典获得模型的最优参数。同样,本实验涉及大量代码编程,需要大家多动手编程,有不理解的方法、类能够自行查阅相关api文档解决。