基于支持向量机的手写数字识别

简介: 基于支持向量机的手写数字识别

1 目的

  对来源于附件2的1617个手写体数字样本进行识别。通过建立数学模型识别数字,在模型建立过程中使用网格搜索的方式确定模型最优参数,使用交叉验证的方式评估模型的泛化能力。

2 实验环境

2.1 硬件环境

  ● 处理器:Intel® Core™ i5-8300H CPU @ 2.30GHz 2.30 GHz

  ● 内存:8GB DDR4 RAM

  ● 存储:256GB SSD

  ● 操作系统:Windows 10

2.2 软件环境

  ● Python:3.9.12

3 方案设计

图1 方案设计

4 预备知识

4.1 支持向量机算法

   SVM 是一种机器学习算法,常用来进行分类预 测。SVM 是基于结构化风险最小化原理,由 Vapnik领导的贝尔实验室研究组于1963年提出的,包括线性和非线性两种类型。其基本思想是在样本或特征空间中寻找最优超平面,使不同类别的样 本数据分开并使空间间隔达到最大化,它能够解决非线性高维

image.png

image.png

  SVM 的分类精度取决于核函数的选择和相关参数的设置,可以根据样本的特征和实际情况来选 择合适的核函数。目前常用的核函数有线性核函数 L N、多项式核函数 P L 、径向基函数 RBFsigmoid核函数 S I G ,径向基核函数常用于非线性高维多分类问题,该函数可以将多类样本从低维空间映射到高维空间中,并在高维空间中执行分类任务。

4.2 网格搜索方法

  网格搜索方法主要用于模型调参,也就是帮助我们找到一组最合适的模型设置参数,使得模型的预测达到更好的效果,这组参数于模型训练过程中学习到的参数不同,它是需要在训练前预设好的,我们称其为超参数(在机器学习的上下文中,超参数是在开始学习过程之前设置值的参数,而不是通过训练得到的参数数据。通常情况下,需要对超参数进行优化,给学习机选择一组最优超参数,以提高学习的性能和效果)。

  网格搜索方法通过将给定的参数列表中的值进行随机组合,并分别评估每个组合的模型效果,从而找到一组最优的超参数。例如某个模型有3个超参数,每个超参数我们分别设定有5种不同的取值范围,那么网格搜索需要分别对5 ∗ 5 ∗ 5 = 125 中参数组合进行效果评估,并从中找出最优的那一组。

4.3 交叉验证法

  交叉验证通过重复使用数据,将得到的样本数据进行切分,组合为不同的训练集和测试集,用训练集来训练模型,用测试集来评估模型预测的好坏。在此基础上可以得到多组不同的训练集和测试集,某次训练集中的某样本在下次可能成为测试集中的样本,即所谓“交叉”。 交叉验证包括简单交叉验证、 折交叉验证和留一法三种。

1.简单交叉验证

  简单交叉验证直接将数据集划分为训练集和验证集,首先利用训练集在不同的参数组合下训练模型,然后在测试集上评价不同参数组合模型的误差,选择测试误差最小的模型。

2.K折交叉验证

  将数据集均匀划分为 个子集,每次迭代,使用一个子集作为测试集,其他的作为训练集。 也可以看做是 折交叉验证的一个特例, 等于样本总数 。对于得到的 个模型,从其中挑选误差最小的作为最终的模型。原理如图2所示:

图2 K折交叉验证图解

3.留一法

  当 K 折交叉验证中的 K等于数据集样本数 K 时,我们便得到了K 折交叉验证的特例:留一法。因为留一法使用的训练集只比原始数据集少了一个样本,因此评估结果往往比较准确。但当样本数据集较大时,需要训练模型也就越多。

5 代码块功能

5.1 加载相关包

1.  from time import time  
2.  from os import listdir  
3.  from os.path import basename  
4.  from PIL import Image  
5.  from sklearn import svm  
6.  from sklearn.model_selection import cross_val_score,\  
7.       ShuffleSplit, LeaveOneOut  
8.  from sklearn.model_selection import GridSearchCV  
9.  import numpy as np

5.2 数据预处理

  首先设置手写数字图像尺寸的宽度和高度,初始值为width, height = 30, 60 ,然后建立loadDigits(dstDir=‘datasets’) 函数,作用为从指定的目录中加载一系列的数字图像后提取这些图像中的数字信息,并加载每个图像信息的标签,最后调动该函数,设置dstDir=‘D:\研[\附件2](file://附件2)’ ,以将图像信息和对应标签信息存储到data元组中。函数调用过程中,首先获取目标目录下所有的文件名,然后筛选出以 .jpg 结尾的文件,即所有的手写数字图像,然后使用 sort 方法对筛选出的文件进行排序,排序的关键是文件的名称(除去后缀前的部分),这样可以将数字图像按照编号顺序排列,并采用循环遍历排序后的数字图像,对于每一个数字图像,使用 Image.open(fn) 打开图像,getpixel 方法获取每个像素的RGB值,计算每个像素的平均颜色值(即亮度)。这个平均值被存储在一个列表中,该列表随后被添加到 digitsData 列表中。然后使用使用 open 函数打开标签文件(每一行包含一个标签)。读取所有标签,并将每行的开头和结尾的空白字符(如空格、换行符、制表符等)移除。最后,函数以元组形式返回两个列表:一个是 digitsData,包含所有图像的像素值;另一个是 digitsLabel,包含所有图像的标签。

1.  width, height = 30, 60  
2.  def loadDigits(dstDir='datasets'):  
3.      # 获取所有图像文件名  
4.      digitsFile = [dstDir+'\\'+fn for fn in listdir(dstDir)  
5.                     if fn.endswith('.jpg')]  
6.      # 按编号排序  
7.      digitsFile.sort(key=lambda fn: int(basename(fn)[:-4]))  
8.      # digitsData用于存放读取的图片中数字信息  
9.      # 每个图片中所有像素值存放于digitsData中的一行数据  
10.     digitsData = []  
11.     for fn in digitsFile:  
12.         with Image.open(fn) as im:  
13.             ##计算图像中每个像素的平均颜色值  
14.             data = [sum(im.getpixel((w,h)))/len(im.getpixel((w,h)))  
15.                      for w in range(width)  
16.                      for h in range(height)]  
17.             digitsData.append(data)  
18.     # digitsLabel用于存放图片中数字的标准分类  
19.     with open(dstDir+'\\digits.txt') as fp:  
20.         digitsLabel = fp.readlines()  
21.     # 移除字符串开头和结尾的空白字符,包括空格、换行符(\n)、制表符(\t)等  
22.     digitsLabel = [label.strip() for label in digitsLabel]  
23.     return (digitsData, digitsLabel)  
24.   
25. # 加载数据  
26. data = loadDigits('D:\\研\\附件2')  
27. print('数据加载完成。')

5.3 模型构建

  以data元组中的数字图像像素值情况和图像标签分别作为模型训练集的X和Y,首先建立支持向量机模型,设置参数网格中,各参数设置范围见表1所示。

表1 各参数选择范围

  然后使用GridSearchCV进行参数寻优,网格搜索过程中,最佳参数组合为:Kernel=‘linear’,C=0.001,gamma=0.001,最佳得分为0.9870,耗时341.0738s。接着在此参数设置下建立支持向量机模型。

1.  svcClassifier = svm.SVC()  
2.  # 待测试的参数  
3.  parameters = {'kernel': ('linear', 'rbf'),  
4.                 'C': (0.001, 1, 10, 100, 1000),  
5.                 'gamma':(0.001, 0.1, 0.5, 1, 10)}  
6.    
7.  # 网格搜索  
8.  start = time()  
9.  clf = GridSearchCV(svcClassifier, parameters)  
10. clf.fit(data[0], data[1])  
11. # 解除注释可以查看详细结果  
12. # print(clf.cv_results_)  
13. print(clf.best_params_)  
14. print('得分:', clf.score(data[0], data[1]))  
15. print('用时(秒):', np.round(time()-start,4))  
16.   
17. # 确定模型  
18. svcClassifier = svm.SVC(kernel="linear", C=0.001, gamma=0.001)

5.4 模型评估

  1.简单交叉验证过程中,将训练集以7:3的比例随机切分10次,以最佳模型进行训练和预测,10次得分分别为:0.5185、0.5206、0.5185、0.4856、0.4835、0.4609、0.535、0.5123、0.4774、0.5206,平均得分为0.5033,耗时9.9045秒。

1.  start = time()  
2.  scores1 = cross_val_score(svcClassifier, data[0], data[1],  
3.                             cv=ShuffleSplit(test_size=0.3,  
4.                                               train_size=0.7,  
5.                                               n_splits=10))  
6.  print('交叉验证(随机拆分)得分情况:\n', np.round(scores1,4))  
7.  print('平均分:\n', np.round(scores1.mean(),4))  
8.  print('用时(秒):', np.round(time()-start,4))  
9.  print('='*20)

  2.K折交叉验证过程中,设置K=10,以最佳模型进行训练和预测,10次得分分别为:0.3272、0.3827、0.4136、0.5679、0.4074、0.4444、0.4877、0.5155、0.3913、0.3975,平均得分为0.4335,耗时10.5548秒。

1.  start = time()  
2.  scores2= cross_val_score(svcClassifier, data[0], data[1], cv=10)  
3.  print('交叉验证(k折叠)得分情况\n', np.round(scores2,4))  
4.  print('平均分:\n', np.round(scores2.mean(),4))  
5.  print('用时(秒):', np.round(time()-start,4))  
6.  print('='*20)

  3.留一交叉验证过程中,能获取交叉验证(逐个测试)得分情况,前十个结果分别为0、1、0、1、1、0、0、1、 0、0。平均得分为0.5455,耗时1533.2085秒。

1.  start = time()  
2.  scores3 = cross_val_score(svcClassifier, data[0], data[1],  
3.                             cv=LeaveOneOut())  
4.    
5.  print('交叉验证(逐个测试)得分情况:\n', np.round(scores3,4))  
6.  print('平均分:\n', np.round(scores3.mean(),4))  
7.  print('用时(秒):', np.round(time()-start,4))  
8.  print('='*20)

5 总结

  本文建立了支持向量机模型对手写数字进行识别,并在实验过程中经过了数据预处理、模型构建、模型评估步骤。在数据预处理过程,提取了图像的像素特征和对应标签信息;在模型构建过程中使用网格寻优的方式获取多项式朴素贝叶斯模型的最优参数;在模型评估过程中使用了三种交叉验证方式进行模型的泛化能力评估。

6 完整代码

8.  # 1.**导入所需的库**  
9.  from time import time  
10. from os import listdir  
11. from os.path import basename  
12. from PIL import Image  
13. from sklearn import svm  
14. from sklearn.model_selection import cross_val_score,\  
15.      ShuffleSplit, LeaveOneOut  
16. from sklearn.model_selection import GridSearchCV  
17. import numpy as np  
18.   
19.   
20. # 2.**数据预处理**  
21.   
22. # 图像尺寸  
23. width, height = 30, 60  
24. def loadDigits(dstDir='datasets'):  
25.     # 获取所有图像文件名  
26.     digitsFile = [dstDir+'\\'+fn for fn in listdir(dstDir)  
27.                    if fn.endswith('.jpg')]  
28.     # 按编号排序  
29.     digitsFile.sort(key=lambda fn: int(basename(fn)[:-4]))  
30.     # digitsData用于存放读取的图片中数字信息  
31.     # 每个图片中所有像素值存放于digitsData中的一行数据  
32.     digitsData = []  
33.     for fn in digitsFile:  
34.         with Image.open(fn) as im:  
35.             # 计算图像中每个像素的平均颜色值  
36.             data = [sum(im.getpixel((w,h)))/len(im.getpixel((w,h)))  
37.                      for w in range(width)  
38.                      for h in range(height)]  
39.             digitsData.append(data)  
40.     # digitsLabel用于存放图片中数字的标准分类  
41.     with open(dstDir+'\\digits.txt') as fp:  
42.         digitsLabel = fp.readlines()  
43.     # 移除字符串开头和结尾的空白字符,包括空格、换行符(\n)、制表符(\t)等  
44.     digitsLabel = [label.strip() for label in digitsLabel]  
45.     return (digitsData, digitsLabel)  
46.   
47. # 加载数据  
48. data = loadDigits('D:\\研\\Python期末\\2023期末考试\\附件2')  
49. print('数据加载完成。')  
50.   
51. # 3.**模型建立**  
52. # 建立支持向量机模型  
53. svcClassifier = svm.SVC()  
54. # 待测试的参数  
55. parameters = {'kernel': ('linear', 'rbf'),  
56.                'C': (0.001, 1, 10, 100, 1000),  
57.                'gamma':(0.001, 0.1, 0.5, 1, 10)}  
58.   
59. # 网格搜索  
60. start = time()  
61. clf = GridSearchCV(svcClassifier, parameters)  
62. clf.fit(data[0], data[1])  
63. # 解除注释可以查看详细结果  
64. # print(clf.cv_results_)  
65. print(clf.best_params_)  
66. print('得分:',np.round(clf.score(data[0], data[1]),4) )  
67. print('用时(秒):', np.round(time()-start,4))  
68.   
69. # 确定模型  
70. svcClassifier = svm.SVC(kernel="linear", C=0.001, gamma=0.001)  
71.   
72. # 4.**模型评估**  
73. #简单交叉验证  
74. start = time()  
75. scores1 = cross_val_score(svcClassifier, data[0], data[1],  
76.                            cv=ShuffleSplit(test_size=0.3,  
77.                                              train_size=0.7,  
78.                                              n_splits=10))  
79. print('交叉验证(随机拆分)得分情况:\n', np.round(scores1,4))  
80. print('平均分:\n', np.round(scores1.mean(),4))  
81. print('用时(秒):', np.round(time()-start,4))  
82. print('='*20)  
83.   
84. # K折交叉验证  
85. start = time()  
86. scores2= cross_val_score(svcClassifier, data[0], data[1], cv=10)  
87. print('交叉验证(k折叠)得分情况\n', np.round(scores2,4))  
88. print('平均分:\n', np.round(scores2.mean(),4))  
89. print('用时(秒):', np.round(time()-start,4))  
90. print('='*20)  
91.   
92.   
93. ## 留一交叉验证  
94. start = time()  
95. scores3 = cross_val_score(svcClassifier, data[0], data[1],  
96.                            cv=LeaveOneOut())  
97. print('交叉验证(逐个测试)得分情况:\n', np.round(scores3,4))  
98. print('平均分:\n', np.round(scores3.mean(),4))  
99. print('用时(秒):', np.round(time()-start,4))  
100.print('='*20)


相关文章
|
1月前
|
机器学习/深度学习 算法 Serverless
什么是支持向量机(SVM)
支持向量机(Support Vector Machine,SVM)是一种用于分类问题的监督算法。主要用于二分类和多分类问题。其基本思想是找到一个超平面,能够将不同类别的样本点尽可能地分开,并使得离超平面最近的样本点尽可能远离超平面,从而实现较好的分类效果。 SVM的关键是找到一个最优的超平面,这个超平面可以通过使得最靠近超平面的样本点之间的间隔最大化来定义。这些最靠近超平面的样本点被称为支持向量。SVM的优化目标可以表示为一个凸二次规划问题,可以通过求解对应的拉格朗日函数来得到最优解。
|
1月前
|
机器学习/深度学习 算法 Serverless
支持向量机(SVM)
支持向量机(Support Vector Machine,SVM)是一种用于分类问题的监督算法。主要用于二分类和多分类问题。其基本思想是找到一个超平面,能够将不同类别的样本点尽可能地分开,并使得离超平面最近的样本点尽可能远离超平面,从而实现较好的分类效果。 SVM的关键是找到一个最优的超平面,这个超平面可以通过使得最靠近超平面的样本点之间的间隔最大化来定义。这些最靠近超平面的样本点被称为支持向量。SVM的优化目标可以表示为一个凸二次规划问题,可以通过求解对应的拉格朗日函数来得到最优解。 SVM除了能够处理线性可分离的问题外,还可以通过核函数的引入处理线性不可分的问题,将样本映射到高维空间,从而
|
1月前
|
机器学习/深度学习 数据采集 算法
深入理解并应用机器学习算法:支持向量机(SVM)
【5月更文挑战第13天】支持向量机(SVM)是监督学习中的强分类算法,用于文本分类、图像识别等领域。它寻找超平面最大化间隔,支持向量是离超平面最近的样本点。SVM通过核函数处理非线性数据,软间隔和正则化避免过拟合。应用步骤包括数据预处理、选择核函数、训练模型、评估性能及应用预测。优点是高效、鲁棒和泛化能力强,但对参数敏感、不适合大规模数据集且对缺失数据敏感。理解SVM原理有助于优化实际问题的解决方案。
|
7月前
|
机器学习/深度学习 数据可视化 算法
图像识别5:LDA 与 SVM+神经网络+支持向量机实验
图像识别5:LDA 与 SVM+神经网络+支持向量机实验
77 0
|
8月前
|
机器学习/深度学习 数据采集 算法
支持向量机SVM:从数学原理到实际应用
支持向量机SVM:从数学原理到实际应用
380 0
|
10月前
|
机器学习/深度学习 算法 Python
2022-11-10-支持向量机SVM
2022-11-10-支持向量机SVM
94 0
|
机器学习/深度学习 数据采集 并行计算
基于卷积神经网络的分类算法
基于卷积神经网络的分类算法
71 0
|
机器学习/深度学习 存储 算法
【机器学习】支持向量机 SVM(非常详细)
SVM 想要的就是找到各类样本点到超平面的距离最远,也就是找到最大间隔超平面。
【机器学习】支持向量机 SVM(非常详细)
|
机器学习/深度学习
支持向量机(SVM)公式推导
支持向量机(SVM)公式推导
134 0
|
机器学习/深度学习
SVM支持向量机公式推导
简单方法:样本、分类器的定义;求解距离最大值;目标函数;拉格朗日乘子法优化目标函数;求解参数W;计算截距
2183 0