数据集
- 本质上,支持向量机是一个二类分类器,其分类结果不是
+1
就是 -1
。
- 而手写数字识别有
0 ~ 9
共计 10
个分类结果,数据集看似不符合分类要求,所以我们对数据集做出限制仅仅有 1
和 9
两类数字数据。
- 在处理数据时,碰到数字
9
,输出类别标签为 -1
,否则输出 +1
。
- 数据集分为训练集
trainingDigits
和测试集 testDigits
。
- 训练集中有
198
个数字 1
文件,204
个数字 9
文件。
- 训练集中有
97
个数字 1
文件,89
个数字 9
文件。
- 命名规则:如
1_16.txt
即表明此为数字 1
编号为 16
的文件。(数字 1
文件共计 198
个,标号为 1_0.txt
~ 1_197.txt
)
- 每个文件内部为 32x32 的矩阵。如下图所示:
-
训练集
-
1_0.txt
基于 SVM 的手写数字识别
# 该函数创建 1x1024 的 NumPy 数组,然后打开给定的文件,循环读出文件的前 32 行,
# 并将每行的前 32 个字符值存储在 NumPy 数组中,最后返回数组
def img2vector(filename):
# 创建 1x1024 的 NumPy 数组
returnVect = np.zeros((1, 1024))
# 打开文件
fr = open(filename)
# 读取 32 行(每个文件中都为32行)
for i in np.arange(32):
# 读取一行
lineStr = fr.readline()
# 每一行有 32 个数字,循环读取
for j in np.arange(32):
# 将每一行读取的字符转化为 int 类型,然后存放到 returnVect 中
returnVect[0, 32 * i + j] = int(lineStr[j])
# 返回 1x1024 的 NumPy 数组,即把 32x32 的图片压缩成 1x1024
return returnVect
- 为了简便,数字为 32x32 向量存放在 .txt 文件中,此为迭代取出每一个文件,然后通过 img2vector 将图片数据存储为一个 1x1024 向量存放到 trainingMat 中的一行。
def loadImages(dirName):
from os import listdir
hwLabels = []
trainingFileList = listdir(dirName)
m = len(trainingFileList)
trainingMat = np.zeros((m, 1024))
for i in range(m):
fileNameStr = trainingFileList[i]
fileStr = fileNameStr.split('.')[0]
classNumStr = int(fileStr.split('_'))[0]
if classNumStr == 9:
hwLabels.append(-1)
else:
hwLabels.append(1)
trainingMat[i,:] = img2vector('%s/%s' % (dirName, fileNameStr))
return trainingMat, hwLabels
def testDigits(kTup = ('rbf', 10)):
# 用训练集(trainingDigits)进行训练
dataArr, labelArr = loadImages('trainingDigits')
b, alphas = smoP(dataArr, labelArr, 200, 0.0001, 10000, kTup)
dataMat = np.mat(dataArr)
labelMat = np.mat(labelArr).transpose()
svInd = np.nonzero(alphas.A > 0)[0]
sVs = dataMat[svInd]
labelSV = labelMat[svInd]
print('there are %d Support vectors' % np.shape(sVs)[0])
m, n = np.shape(dataMat)
errorCount = 0
for i in range(m):
kernelEval = kernelTrans(sVs, dataMat[i,:], kTup)
predict = kernelEval.T * np.multiply(labelSV, alphas[svInd]) + b
if sign(predict) != sign(labelArr[i]):
errorCount += 1
print('the training error rate is: %f' % (float(errorCount) / m))
# 用训练好的模型在测试集(testDigits)上计算错误率
dataArr, labelArr = loadImages('testDigits')
errorCount = 0
dataMat = np.mat(dataArr)
labelMat = np.mat(labelArr).transpose()
m, n = np.shape(dataMat)
for i in range(m):
kernelEval = kernelTrans(sVs, dataMat[i,:], kTup)
predict = kernelEval.T * np.multiply(labelSV, alphas[svInd]) + b
if sign(predict) != sign(labelArr[i]):
errorCount += 1
print('the best error rate is: %f' %(float(errorCount) / m))
if __name__ == '__main__':
testDigits(('rbf', 20))
- 注意,代码不可能这么少的啦,主体代码大部分还是要用上一讲的,只不过读取数据部分还有最后训练测试部分进行稍微改动而已,这里仅仅列出关键代码模块!
参考