python实现基于SVM算法的手写数字识别系统 非常详细!!!!

一家懂得用细节留住客户的3年潮牌老店我必须支持!➕🛰:luyao1931

在这里插入图片描述

实验知识点:

1、支持向量机SVM相关知识
2、从文本文件中解析和导入数据
3、SMO分类算法
4、归一化数值

SVM算法概述:

支持向量机(Support Vector Machine, SVM)是一类按监督学习(supervised learning)方式对数据进行二元分类(binary classification)的广义线性分类器(generalized linear classifier),其决策边界是对学习样本求解的最大边距超平面。
优点:泛化错误率低,计算开销不大,结果易解释
缺点:对参数调节和核函数的选择敏感,原始分类器不加修改仅适用于处理二类问题。
适用数据类型:数值型和标称型数据。

SVM的一般流程:

1、 收集数据:提供文本文件
2、 准备数据:基于二值图像构造向量
3、 分析数据:对图像进行目测
4、 训练算法:采用两种不同的核函数,并对径向基核函数采用不同的设置来运行SMO算法
5、 测试算法:编写一个函数来测试不同核函数并计算错误率
6、 使用算法:几乎所有分类问题都可以使用SVM,SVM本身是一个二类分类器,对多类问题应用SVM需要对代码做一些修改

实验步骤:

1、 SOM算法中的辅助函数:

#SNMO算法中的辅助函数
def loadDataSet(fileName):

    """
    loadDataSet(对文件进行逐行解析,从而得到每行的类标签和整个数据矩阵)

    Args:
        fileName 文件名
    Returns:
        dataMat  数据矩阵
        labelMat 类标签
    """

    dataMat = []
    labelMat = []
    fr = open(fileName)
    for line in fr.readlines():
        lineArr = line.strip().split('\t')
        dataMat.append([float(lineArr[0]), float(lineArr[1])])
        labelMat.append(float(lineArr[2]))
    return dataMat, labelMat

def selectJrand(i, m):
    """
    随机选择一个整数
    Args:
        i  第一个alpha的下标
        m  所有alpha的数目
    Returns:
        j  返回一个不为i的随机数,在0~m之间的整数值
    """
    j = i
    while (j == i):
        j = int(random.uniform(0, m))
    return j

# 调整alpha值
def clipAlpha(aj, H, L):
    """clipAlpha(调整aj的值,使aj处于 L<=aj<=H)
    Args:
        aj  目标值
        H   最大值
        L   最小值
    Returns:
        aj  目标值
    """
    if aj > H:
        aj = H
    if L > aj:
        aj = L
return aj

2、完整的Platt SMO的支持函数:

# begin 完整版Platt SMO支持函数
class optStruct:
    def __init__(self, dataMatIn, classLabels, C, toler):
        self.X = dataMatIn
        self.labelMat = classLabels
        self.C = C
        self.tol = toler
        self.m = shape(dataMatIn)[0]
        self.alphas = mat(zeros((self.m, 1)))
        self.b = 0
        self.eCache = mat(zeros((self.m, 2)))# 第一列是有效标志位,第二列是E值

#EK计算较多,所以单独拎出来
def calcEk(oS, k):
    """calcEk(求 Ek误差:预测值-真实值的差)

    该过程在完整版的SMO算法中陪出现次数较多,因此将其单独作为一个方法
    Args:
        oS  optStruct对象
        k   具体的某一行

    Returns:
        Ek  预测结果与真实结果比对,计算误差Ek
    """
    # fXk = float(multiply(oS.alphas, oS.labelMat).T * (oS.X * oS.X[k, :].T)) + oS.b
    fXk = float(multiply(oS.alphas, oS.labelMat).T * oS.K[:, k] + oS.b)
    Ek = fXk - float(oS.labelMat[k])
    return Ek

#在选择第2个alphas参数时(也就是进行SMO的内循环时),不再是随机选择,而是选择最长步长的那个(就是选择|E_i-Ej|最大的)
def selectJ(i, oS, Ei):
    """selectJ(返回最优的j和Ej)

       内循环的启发式方法。
       选择第二个(内循环)alpha的alpha值
       这里的目标是选择合适的第二个alpha值以保证每次优化中采用最大步长。
       该函数的误差与第一个alpha值Ei和下标i有关。
       Args:
           i   具体的第i一行
           oS  optStruct对象
           Ei  预测结果与真实结果比对,计算误差Ei

       Returns:
           j  随机选出的第j一行
           Ej 预测结果与真实结果比对
           ,计算误差Ej
       """

    maxK = -1
    maxDeltaE = 0
    Ej = 0
    # 首先将输入值Ei在缓存中设置成为有效的。这里的有效意味着它已经计算好了。
    oS.eCache[i] = [1, Ei]
    # 非零E值的行的list列表,所对应的alpha值
    validEcacheList = nonzero(oS.eCache[:, 0].A)[0]
    if (len(validEcacheList)) > 1:
        for k in validEcacheList:   # 在所有的值上进行循环,并选择其中使得改变最大的那个值
            if k == i: continue  # don't calc for i, waste of time如果j=i直接跳过
            Ek = calcEk(oS, k)  # 求 Ek误差:预测值-真实值的差
            deltaE = abs(Ei - Ek)
            if (deltaE > maxDeltaE):
                maxK = k    #get max j下标
                maxDeltaE = deltaE  #get max j's deltaE
                Ej 
  • 8
    点赞
  • 144
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值