SVM实战,手写识别问题
之前使用KNN算法进行手写体的识别,需要保存全部的向量,使用SVM只需要保存支持向量即可,可以减少内存的占用。
def img2vector(filename):
returnVect = zeros((1,1024))
fr = open(filename)
for i in range(32):
lineStr = fr.readline()
for j in range(32):
returnVect[0,i*32+j] = int(lineStr[j])
return returnVect
#二分类,数字9标签为-1 其他的标签为+1
def loadImages(dirName):
from os import listdir
hwLabels = []
trainingFileList = listdir(dirName) #load the training set
m = len(trainingFileList)
trainingMat = zeros((m,1024))
for i in range(m):
fileNameStr = trainingFileList[i]
fileStr = fileNameStr.split('.')[0] #take off .txt
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)):
#获取类别标签及数据
dataArr,labelArr = loadImages('trainingDigits')
b,alphas = smoP(dataArr, labelArr, 200, 0.0001, 10000, kTup)
datMat=mat(dataArr); labelMat = mat(labelArr).transpose()
svInd=nonzero(alphas.A>0)[0]
sVs=datMat[svInd]
labelSV = labelMat[svInd];
print ("there are %d Support Vectors" % shape(sVs)[0])
m,n = shape(datMat)
errorCount = 0
for i in range(m):
kernelEval = kernelTrans(sVs,datMat[i,:],kTup)
predict=kernelEval.T * multiply(labelSV,alphas[svInd]) + b
if sign(predict)!=sign(labelArr[i]): errorCount += 1
print ("the training error rate is: %f" % (float(errorCount)/m))
dataArr,labelArr = loadImages('testDigits')
errorCount = 0
datMat=mat(dataArr); labelMat = mat(labelArr).transpose()
m,n = shape(datMat)
for i in range(m):
kernelEval = kernelTrans(sVs,datMat[i,:],kTup)
predict=kernelEval.T * multiply(labelSV,alphas[svInd]) + b
if sign(predict)!=sign(labelArr[i]): errorCount += 1
print ("the test error rate is: %f" % (float(errorCount)/m))
训练结果如上图所示。
参数取在10左右时,可以得到最小的测试错误率。该参数的比值比前面的取值大的多,而前面的测试错误率在1.3左右。为什么差距如此之大呢?就是因为数据集不同。在手写识别的数据中有1024个特征,而这些特征的值有可能高达1.0。而在我我们之前的例子中特征就1,-1 两个。还有一个发现是最小训练错误率并不对应与最小支持向量的数目。另外,使用线性核函数的效果并不是特别糟糕,可以牺牲线性函数的错误率来换取分类速度。
本章小结:
支持向量机是一种二分类的决策机。泛化错误率比较低,具有良好的学习能力,且学习算法具有很好的推广性。
支持向量机通过求解一个二次优化问题来最大化分类间隔。通过完整版的platt smo算法大大提高了优化的速度,还使其存在进一步提高运行速度的空间。
SVM的效果也对优化参数和核函数中的参数敏感。