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的效果也对优化参数和核函数中的参数敏感。