《机器学习实战笔记--第一部分 分类算法:支持向量机 4》

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

    

猜你喜欢

转载自blog.csdn.net/qq_41635352/article/details/80291599