精华内容
下载资源
问答
  • 之前在博客中分享了个生成从1到n的连续数字的transform或map方法,最近研究了一下UDTF,发现用UDTF出来的函数用起来更方便,语法更接近于普通的函数。而且在JAVA中对参数的个数、类型等进行校验也更容易。   ...

    之前在博客中分享了个生成从1到n的连续数字的transform或map方法,最近研究了一下UDTF,发现用UDTF写出来的函数用起来更方便,语法更接近于普通的函数。而且在JAVA中对参数的个数、类型等进行校验也更容易。

     

    ORACLE中生成从1到n的连续数字的方法很多,最简单的一种是:

    select level from dual connect by level<=5;

            LEVEL
    ----------
                      1
                  2
                  3
                  4
                  5
     
    使用UDTF写出来的函数进行查询:
    hive> select serial(5) as col1 from dual;
    OK
    1
    2
    3
    4
    5
     
    或者使用lateral view进行查询:
    hive> select T.col1 from dual lateral view serial(5) T as col1;
    OK
    1
    2
    3
    4
    5
     
    提供一下java代码,仅供参考:
     
    package com.hadoopbook.hive;
    import java.util.ArrayList;
    import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
    import org.apache.hadoop.hive.ql.metadata.HiveException;
    import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthExcepti on;
    import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
    import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
    import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
    import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
    import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspector Factory;
    public class UDTFSerial extends GenericUDTF {
     
       Object[] result = new Object[1];
     
       @Override
       public void close() throws HiveException {
       }
     
       @Override
       public StructObjectInspector initialize(ObjectInspector[] args)
                       throws UDFArgumentException {
               if (args.length != 1) {
                       throw new UDFArgumentLengthExcepti on("UDTFSerial takes only one argument");
               }
               if (!args[0].getTypeName().equals("int")) {
                throw new UDFArgumentException("UDTFSerial only takes an integer as a parameter");
                   }
               ArrayList<String> fieldNames = new ArrayList<String>();
               ArrayList<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>();
               fieldNames.add("col1");
               fieldOIs.add(PrimitiveObjectInspector Factory.javaIntObjectInspector);
             
               return ObjectInspectorFactory.getStandardStructObjectI nspector(fieldNames,fieldOIs);
       }
     
       @Override
       public void process(Object[] args) throws HiveException {
         try
         {
           int n = Integer.parseInt(args[0].toString());
           for (int i=0;i<n;i++)
           {
             result[0] = i+1;
             forward(result);
           }
         }
         catch (Exception e) { 
           throw new HiveException("UDTFSerial has an exception");
         }
       }
    }
    展开全文
  • 基于SVM技术的手写数字识别

    万次阅读 多人点赞 2019-07-29 22:51:39
    老师常说,在人工智能未发展起来之前,SVM技术是一统江湖的...1.手写数字识别技术的含义 2.手写数字识别技术的理论价值 3.数字识别技术的难点 二、SVM技术 1.SVM方法简介 2.线性可划分问题 3.近似线性可分问题...

    老师常说,在人工智能未发展起来之前,SVM技术是一统江湖的,SVM常常听到,但究竟是什么呢?最近研究了一下基于SVM技术的手写数字识别。你没有看错,又是手写数字识别,就是喜欢这个手写数字识别,没办法(¬∀¬)σ

    一、背景

    1.手写数字识别技术的含义

    2.手写数字识别技术的理论价值

    3.数字识别技术的难点

    二、SVM技术

    1.SVM方法简介

     2.线性可划分问题

    3.近似线性可分问题的线性划分

    4.非线性划分

    5.SVM方法

    6.SVM的性能

    三、实验

    1.数据集介绍

    2.实验步骤

    3.实验代码

    4.实验结果

    四、附录

    1.参考

    2.需要安装的包

    一、背景

    1.手写数字识别技术的含义

    手写数字识别(Handwritten Digit Recognition)是光学字符识别技术的一个分支,是模式识别学科的一个传统研究领域。主要研究如何利用电子计算机自动辨认手写在纸张上的阿拉伯数字。手写数字识别分为脱机手写数字识别和联机手写数字识别。本文主要讨论脱机手写数字的识别。 随着信息化的发展,手写数字识别的应用日益广泛,研究高识别率、零误识率和低拒识率的高速识别算法具有重要意义。

    2.手写数字识别技术的理论价值

    由于手写数字识别本身的特点,对它的研究有重要的理论价值:

     ⑴阿拉伯数字是唯一被世界各国通用的符号,对手写体数字识别的研究基本上与文化背景无关,各地的研究工作者基于同一平台开展工作,有利于研究的比较和探讨。

     ⑵手写数字识别应用广泛,如邮政编码自动识别,税表系统和银行支票自动处理等。这些工作以前需要大量的手工录入,投入的人力物力较多,劳动强度较大。手写数字识别的研究适应了无纸化办公的需要,能大大提高工作效率。

    ⑶由于数字类别只有 10 个,较其他字符识别率较高,可用于验证新的理论和做深入的分析研究。许多机器学习和模式识别领域的新理论和算法都是先用手写数字识别进行检验,验证理论的有效性,然后才应用到更复杂的领域当中。这方面的典型例子就是人工神经网络和支持向量机(Support Vector Machine)。

     ⑷手写数字的识别方法很容易推广到其它一些相关问题,如对英文之类拼音文字的识别。事实上,很多学者就是把数字和英文字母的识别放在一起研究的。

    3.数字识别技术的难点

    数字的类别只有 10 种,笔划简单,其识别问题似乎不是很困难。但事实上,一些测试结果表明,数字的正确识别率并不如印刷体汉字识别率高,甚至也不如联机手写体汉字识别率高,而只仅仅优于脱机手写体汉字识别。这其中的主要原因是:

    ⑴数字笔划简单,其笔划差别相对较小,字形相差不大,使得准确区分某些数字相当困难;

    ⑵数字虽然只有 10 种,且笔划简单,但同一数字写法千差万别,全世界各个国家各个地区的人都在用,其书写上带有明显的区域特性,很难做出可以兼顾世界各种写法的、识别率极高的通用性数字识别系统。

    虽然目前国内外对脱机手写数字识别的研究已经取得了很大的成就,但是仍然存在两大难点:

    一是识别精度需要达到更高的水平。手写数字识别没有上下文,数据中的每一个数据都至关重要。而数字识别经常涉及金融、财会领域,其严格性更是不言而喻。因此,国内外众多的学者都在为提高手写数字的识别率,降低误识率而努力。

    二是识别的速度要达到很高的水平。数字识别的输入通常是很大量的数据,而高精度与高速度是相互矛盾的,因此对识别算法提出了更高的要求。

    二、SVM技术

    1.SVM方法简介

    统计学习理论是建立在一套较坚实的理论基础之上的,为解决有限样本学习问题提供了一个统一的框架。它能将很多现有方法纳入其中,有望解决许多原来难以解决的问题比如神经网络结构选择问题、局部极小点问题等同时,在该理论基础上发展了一种新的通用学习方法——支持向量机(SupportVectorMachine,简称SVM),已初步表现出很多优于己有方法的性能。一些学者认为正在成为继神经网络研究之后新的研究热点,并将推动机器学习理论和技术有重大的发展。

    SVM方法是建立在统计学习理论的维理论和结构风险最小化原理基础上的,根据有限的样本信息在模型的复杂性即对特定训练样本的学习精度和学习能力即无误识别任意样本的能力之间寻求最佳折衷,以期获得最好的推广能力。

     2.线性可划分问题

                                                                                                       图1最大间隔法

    3.近似线性可分问题的线性划分

    4.非线性划分

    讲到这里,做个思路整理:首先,面对线性可划分问题,我们可以很容易利用最大间隔法,找到最优分类面,将数据分成两类。面对有些线性不可分问题,我们找不到这样一个最优分类面,但是在我们允许很小程度上的错分后,我们可以找到一个最优分类面。这时我们寻找的依据处理要求间隔最大,还要错分的程度最小,这个要求统称为惩罚参数。最后,面对其他线性不可分问题,我们实在找不到一个最优分类面的情况下,我们需要先做一些非线性变换,将非线性问题转化为线性问题,然后再进行处理。

    5.SVM方法

     

    SVM的基本思想可以概括为首先通过非线性变换将输入空间变换到一个高维空间,然后在这个新空间中求取最优线性分类面,而这种非线性变换是通过定义适当的内积函数实现的。

    SVM求得的分类函数形式上类似于一个神经网络,其输出的若干中间层节点的线性组合,而每一个中间层节点对应于输入样本与一个支持向量机的内积,因此也被称为支持向量网络。

    由于最终判决函数中实际只包含与支持向量的内积和求和,因此识别时的计算复杂度取决于支持向量的个数。

    另一个问题的关键是,由于变换空间的维数可能很高,在这个空间中的线性判别函数的VC维因此也可能很大,将导致分类器的效果不理想。而只要在高维空间中能够构造一个具有较小的VC维,从而得到较好的推广能力。

    进一步,关于最优分类面和广义最优分类面的推广能力,有下面的结论:

    如果一组训练样本能够被一个最优分类面或广义最优分类面分开,对于测试样本分类错误率的期望的上界是训练样本中平均的支持向量占总训练样本数的比例,即

    SVM推广性也是与变换空间的维数无关的,只要能够适当地选择一种内积定义,构造一个支持向量数相对较少的最优或广义最优分类器,则就可以得到较好的推广性。

    在这里,统计学习理论使用了与传统方法完全不同的思路,即不是像传统方法那样首先试图将原输入空间降维即特征选择和特征变换,而是设法将输入空间升维,以求在高维空间中问题变得线性可分或接近线性可分因为升维后只是改变了内积运算,并没有使算法复杂性随着维数的增加而增加,而且在高维空间中的推广能力并不受维数影响,因此这种方法才是可行的。

    6.SVM的性能

    使用SVM方法,需要做特征空间的内积运算,而核函数就是內积。SVM核函数的选择对于其性能的表现有至关重要的作用,尤其是针对那些线性不可分的数据,因此核函数的选择在SVM算法中就显得至关重要。常用如下几种常用的核函数来代替自己构造核函数:

    (1)线性核函数 

    线性核主要用于线性可分的情况,我们可以看到特征空间到输入空间的维度是一样的,其参数少速度快,对于线性可分数据,其分类效果很理想。

    (2)多项式核函数 

    多项式核函数可以实现将低维的输入空间映射到高纬的特征空间,但是多项式核函数的参数多,当多项式的阶数比较高的时候,核矩阵的元素值将趋于无穷大或者无穷小,计算复杂度会大到无法计算。

    (3)高斯(RBF)核函数

    高斯径向基函数是一种局部性强的核函数,其可以将一个样本映射到一个更高维的空间内,该核函数是应用最广的一个,无论大样本还是小样本都有比较好的性能,而且其相对于多项式核函数参数要少,因此大多数情况下在不知道用什么核函数的时候,优先使用高斯核函数。

    (4)sigmoid核函数

    采用sigmoid核函数,支持向量机实现的就是一种多层神经网络。

    除了核函数的选取,SVM的策略对SVM的性能也十分重要。手写数字字体识别,显然是个多类别分类问题。对于多分类问题,解决的基本思路是“拆分法”,即将多个二分类问题拆分为若干个十分类任务进行求解。具体来讲,先对问题进行拆分,然后为拆出的每个十分类任务训练一个分类器,在测试时,对这些二分类器的结果进行集成以获得最终的多分类结果。拆分的策略主要有以下几种:

    (1)OvO(one-vs-one)

    这种解决方法的思路是:对于有N个类别的分类任任务,将这N个类别两两配对,从而产生N(N-1)/2个二分类任务。在测试阶段,新样本同时提交给所有分类器,这样可以得到N(N-1)/2个分类结果,最终的结果可以通过投票产生:即把预测的最多的类别作为最终的分类结果。

    (2)OvR(one-vs-rest)

    这种解决方法的思路是:每次将一个类的样例作为正例,所有其他类的样例作为负例来训练N个分类器。在测试时,若仅有一个分类器预测为正类,则对应的类别标记为最终分类结果。

    三、实验

    1.数据集介绍

    本文采用MNIST-image手写数字集进行训练和测试。MNIST数据集是机器学习领域中非常经典的一个数据集,由60000个训练样本和10000个测试样本组成,每个样本都是一张20 * 20像素的灰度手写数字图片。数字已经过尺寸标准化,并以固定尺寸的图像为中心。数据如图2:

                                                                                    图2 MNIST-image数据集

    2.实验步骤

    (1)对数据格式转换
    (2)使用核函数和训练策略对训练集进行训练
    (3)使用训练后得到的模型对测试集进行测试
    (4)选择最佳核函数和训练策略为模型
    (5)用此模型进行可视化识别

    3.实验代码

    (1)训练svm模型并保存

    from PIL import Image
    import os
    import sys
    import numpy as np
    import time
    from sklearn import svm
    from sklearn.externals import joblib
    
    # 获取指定路径下的所有 .png 文件
    def get_file_list(path):
        # file_list = []
        # for filename in os.listdir(path):
        #     ele_path = os.path.join(path, filename)
        #     for imgname in os.listdir(ele_path):
        #         subele_path = os.path.join(ele_path, imgname)
        #         if (subele_path.endswith(".png")):
        #             file_list.append(subele_path)
        # return file_list
        return [os.path.join(path, f) for f in os.listdir(path) if f.endswith(".png")]
    
    
    
    # 解析出 .png 图件文件的名称
    def get_img_name_str(imgPath):
        return imgPath.split(os.path.sep)[-1]
    
    
    # 将 20px * 20px 的图像数据转换成 1*400 的 numpy 向量
    # 参数:imgFile--图像名  如:0_1.png
    # 返回:1*400 的 numpy 向量
    def img2vector(imgFile):
        # print("in img2vector func--para:{}".format(imgFile))
        img = Image.open(imgFile).convert('L')
        img_arr = np.array(img, 'i')  # 20px * 20px 灰度图像
        img_normalization = np.round(img_arr / 255)  # 对灰度值进行归一化
        img_arr2 = np.reshape(img_normalization, (1, -1))  # 1 * 400 矩阵
        return img_arr2
    
    
    # 读取一个类别的所有数据并转换成矩阵
    # 参数:
    #    basePath: 图像数据所在的基本路径
    #       Mnist-image/train/
    #       Mnist-image/test/
    #    cla:类别名称
    #       0,1,2,...,9
    # 返回:某一类别的所有数据----[样本数量*(图像宽x图像高)] 矩阵
    def read_and_convert(imgFileList):
        dataLabel = []  # 存放类标签
        dataNum = len(imgFileList)
        dataMat = np.zeros((dataNum, 400))  # dataNum * 400 的矩阵
        for i in range(dataNum):
            imgNameStr = imgFileList[i]
            imgName = get_img_name_str(imgNameStr)  # 得到 数字_实例编号.png
            # print("imgName: {}".format(imgName))
            classTag = imgName.split(".")[0].split("_")[0]  # 得到 类标签(数字)
            # print("classTag: {}".format(classTag))
            dataLabel.append(classTag)
            dataMat[i, :] = img2vector(imgNameStr)
        return dataMat, dataLabel
    
    
    # 读取训练数据
    def read_all_data():
        cName = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
        path = sys.path[1]
        train_data_path = os.path.join(path, 'data\\Mnist-image\\train\\0')
        #print(train_data_path)
        #train_data_path = "Mnist-image\\train\\0"
        print('0')
        flist = get_file_list(train_data_path)
        dataMat, dataLabel = read_and_convert(flist)
        for c in cName:
            print(c)
            train_data_path = os.path.join(path, 'data\\Mnist-image\\train\\') + c
            flist_ = get_file_list(train_data_path)
            dataMat_, dataLabel_ = read_and_convert(flist_)
            dataMat = np.concatenate((dataMat, dataMat_), axis=0)
            dataLabel = np.concatenate((dataLabel, dataLabel_), axis=0)
        # print(dataMat.shape)
        # print(len(dataLabel))
        return dataMat, dataLabel
    
    
    # create model
    def create_svm(dataMat, dataLabel,path,decision='ovr'):
        clf = svm.SVC(C=1.0,kernel='rbf',decision_function_shape=decision)
        rf =clf.fit(dataMat, dataLabel)
        joblib.dump(rf, path)
        return clf
    '''
    SVC参数
    svm.SVC(C=1.0,kernel='rbf',degree=3,gamma='auto',coef0=0.0,shrinking=True,probability=False,
    tol=0.001,cache_size=200,class_weight=None,verbose=False,max_iter=-1,decision_function_shape='ovr',random_state=None)
    
    C:C-SVC的惩罚参数C?默认值是1.0
    C越大,相当于惩罚松弛变量,希望松弛变量接近0,即对误分类的惩罚增大,趋向于对训练集全分对的情况,这样对训练集测试时
    准确率很高,但泛化能力弱。C值小,对误分类的惩罚减小,允许容错,将他们当成噪声点,泛化能力较强。
    kernel :核函数,默认是rbf,可以是‘linear’, ‘poly’, ‘rbf’, ‘sigmoid’, ‘precomputed’ 
           0 – 线性:u'v
        1 – 多项式:(gamma*u'*v + coef0)^degree
        2 – RBF函数:exp(-gamma|u-v|^2)
        3 –sigmoid:tanh(gamma*u'*v + coef0)
    degree :多项式poly函数的维度,默认是3,选择其他核函数时会被忽略。(没用)
    gamma : ‘rbf’,‘poly’ 和‘sigmoid’的核函数参数。默认是’auto’,则会选择1/n_features
    coef0 :核函数的常数项。对于‘poly’和 ‘sigmoid’有用。(没用)
    probability :是否采用概率估计?.默认为False
    shrinking :是否采用shrinking heuristic方法,默认为true
    tol :停止训练的误差值大小,默认为1e-3
    cache_size :核函数cache缓存大小,默认为200
    class_weight :类别的权重,字典形式传递。设置第几类的参数C为weight*C(C-SVC中的C)
    verbose :允许冗余输出?
    max_iter :最大迭代次数。-1为无限制。
    decision_function_shape :‘ovo’, ‘ovr’ or None, default=None3(选用ovr,一对多)
    random_state :数据洗牌时的种子值,int值
    主要调节的参数有:C、kernel、degree、gamma、coef0
    
    '''
    
    if __name__ == '__main__':
        # clf = svm.SVC(decision_function_shape='ovr')
        st = time.clock()
        dataMat, dataLabel = read_all_data()
        path = sys.path[1]
        model_path=os.path.join(path,'model\\svm.model')
        create_svm(dataMat, dataLabel,model_path, decision='ovr')
        et = time.clock()
        print("Training spent {:.4f}s.".format((et - st)))
    
    

    (2)测试模型效果

    import sys
    import time
    import svm
    import os
    from sklearn.externals import joblib
    import numpy as np
    import matplotlib.pyplot as plt
    
    
    def svmtest(model_path):
        path = sys.path[1]
        tbasePath = os.path.join(path, "data\\Mnist-image\\test\\")
        tcName = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
        tst = time.clock()
        allErrCount = 0
        allErrorRate = 0.0
        allScore = 0.0
        ErrCount=np.zeros(10,int)
        TrueCount=np.zeros(10,int)
        #加载模型
        clf = joblib.load(model_path)
        for tcn in tcName:
            testPath = tbasePath + tcn
            # print("class " + tcn + " path is: {}.".format(testPath))
            tflist = svm.get_file_list(testPath)
            # tflist
            tdataMat, tdataLabel = svm.read_and_convert(tflist)
            print("test dataMat shape: {0}, test dataLabel len: {1} ".format(tdataMat.shape, len(tdataLabel)))
            # print("test dataLabel: {}".format(len(tdataLabel)))
            pre_st = time.clock()
            preResult = clf.predict(tdataMat)
            pre_et = time.clock()
            print("Recognition  " + tcn + " spent {:.4f}s.".format((pre_et - pre_st)))
            # print("predict result: {}".format(len(preResult)))
            errCount = len([x for x in preResult if x != tcn])
            ErrCount[int(tcn)]=errCount
            TrueCount[int(tcn)]= len(tdataLabel)-errCount
            print("errorCount: {}.".format(errCount))
            allErrCount += errCount
            score_st = time.clock()
            score = clf.score(tdataMat, tdataLabel)
            score_et = time.clock()
            print("computing score spent {:.6f}s.".format(score_et - score_st))
            allScore += score
            print("score: {:.6f}.".format(score))
            print("error rate is {:.6f}.".format((1 - score)))
    
        tet = time.clock()
        print("Testing All class total spent {:.6f}s.".format(tet - tst))
        print("All error Count is: {}.".format(allErrCount))
        avgAccuracy = allScore / 10.0
        print("Average accuracy is: {:.6f}.".format(avgAccuracy))
        print("Average error rate is: {:.6f}.".format(1 - avgAccuracy))
        print("number"," TrueCount"," ErrCount")
        for tcn in tcName:
            tcn=int(tcn)
            print(tcn,"     ",TrueCount[tcn],"      ",ErrCount[tcn])
        plt.figure(figsize=(12, 6))
        x=list(range(10))
        plt.plot(x,TrueCount, color='blue', label="TrueCount")  # 将正确的数量设置为蓝色
        plt.plot(x,ErrCount, color='red', label="ErrCount")  # 将错误的数量为红色
        plt.legend(loc='best')  # 显示图例的位置,这里为右下方
        plt.title('Projects')
        plt.xlabel('number')  # x轴标签
        plt.ylabel('count')  # y轴标签
        plt.xticks(np.arange(10), ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'])
        plt.show()
    
    
    if __name__ == '__main__':
        path = sys.path[1]
        model_path=os.path.join(path,'model\\svm.model')
        svmtest(model_path)
    
    
    

    (3)可视化

    # -*- coding: utf-8 -*-
    
    # Form implementation generated from reading ui file 'test2.ui'
    #
    # Created by: PyQt5 UI code generator 5.11.3
    #
    # WARNING! All changes made in this file will be lost!
    
    import sys
    from PyQt5.QtWidgets import QApplication, QMainWindow,QFileDialog
    from PyQt5 import QtCore, QtGui, QtWidgets
    from PyQt5.QtGui import *
    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import *
    import os
    from sklearn.externals import joblib
    import svm
    class Ui_Dialog(object):
        def setupUi(self, Dialog):
            Dialog.setObjectName("Dialog")
            Dialog.resize(645, 475)
            self.pushButton = QtWidgets.QPushButton(Dialog)
            self.pushButton.setGeometry(QtCore.QRect(230, 340, 141, 41))
            self.pushButton.setAutoDefault(False)
            self.pushButton.setObjectName("pushButton")
            self.label = QtWidgets.QLabel(Dialog)
            self.label.setGeometry(QtCore.QRect(220, 50, 191, 221))
            self.label.setWordWrap(False)
            self.label.setObjectName("label")
            self.textEdit = QtWidgets.QTextEdit(Dialog)
            self.textEdit.setGeometry(QtCore.QRect(220, 280, 191, 41))
            self.textEdit.setObjectName("textEdit")
    
            self.retranslateUi(Dialog)
            QtCore.QMetaObject.connectSlotsByName(Dialog)
    
        def retranslateUi(self, Dialog):
            _translate = QtCore.QCoreApplication.translate
            Dialog.setWindowTitle(_translate("Dialog", "手写体识别"))
            self.pushButton.setText(_translate("Dialog", "打开图片"))
            self.label.setText(_translate("Dialog", "显示图片"))
    
    class MyWindow(QMainWindow, Ui_Dialog):
        def __init__(self, parent=None):
            super(MyWindow, self).__init__(parent)
            self.setupUi(self)
            self.pushButton.clicked.connect(self.openImage)
    
        def openImage(self):
            imgName, imgType = QFileDialog.getOpenFileName(self, "打开图片", "../data/Mnist-image/test")
            png = QtGui.QPixmap(imgName).scaled(self.label.width(), self.label.height())
            self.label.setPixmap(png)
            self.textEdit.setText(imgName)
    
            path = sys.path[1]
            model_path = os.path.join(path, 'model\\svm.model')
            clf = joblib.load(model_path)
            dataMat=svm.img2vector(imgName)
            preResult = clf.predict(dataMat)
            self.textEdit.setReadOnly(True)
            self.textEdit.setStyleSheet("color:red")
            self.textEdit.setAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignVCenter)
            self.textEdit.setFontPointSize(9)
            self.textEdit.setText("预测的结果是:")
            self.textEdit.append(preResult[0])
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        myWin = MyWindow()
        myWin.show()
        sys.exit(app.exec_())
    

    4.实验结果

    将MNIST-image数据集运用SVM进行识别,我们选择以线性核函数、RBF核函数、Sigmoid核函数为核函数,以OVO和OVR为策略,两两搭配,共有六种组合,以这六种组合分别训练和测试数据集,并记录其训练时间、测试时间、准确率和平均准确率,得到如下两表:

    从表1可以看出,三种核函数的训练时间和测试时间排序是:线性核函数<RBF核函数<Sigmoid核函数;OVO策略的训练时间小于OVR的训练时间,而OVR的测试时间小于OVO的测试时间。

    从表2可以看出,三种核函数的准确率排序是:RBF核函数>线性核函数>Sigmoid核函数。三种核函数的平均准确率排序是:RBF核函数>线性核函数>Sigmoid核函数.OVO和OVR的准确率和错误率一样。

    造成核函数和策略组合性能不同的原因如下:

    (1)线性核函数、RBF核函数和Sigmoid核函数公式的复杂度不同,导致训练时间和测试时间出现差异。

    (2)理论上,OVR只需要训练N个分类器,而OVO需要训练N(N-1)/2个分类器,因此OVO的存储开销和测试时间开销通常比OVR更大。而在训练时,OVR的每个分类器均使用全部训练样例,而OVO的每个分类器仅用到两个类的样例。因此,在类别很多的时候,OVO的训练时间开销通常比OVR更小。

    (3)手写数字识别中,各种数字写法复杂,这明显是线性不可分的情景,所以线性核函数的准确率较低。

    可视化结果如图3所示:

    最优模型的各个数字情况如图4、表3所示:

    从表3中我们可以看出,各数字整体的错误率都不高,但数字9、8、5、4的错误率是最高的四个,错误率达3%以上,原因是以为这些数字写法相对灵活多变,书写不规范,造成识别率低,这也是今后要加强的地方。

    四、附录

    1.参考

    https://blog.csdn.net/ni_guang2010/article/details/53069579

    https://blog.csdn.net/w5688414/article/details/79343542

    https://blog.csdn.net/rozol/article/details/87705426

    基于SVM技术的手写数字识别的研究_吴琳琳

    SVM在手写数字识别中的应用研究_李雅琴

    2.需要安装的包

    博主的电脑是win10系统,python版本是3.6

    (1)pip install numpy

    (2)pip install Pillow

    (3)python -m pip install --upgrade pip

    (4)pip install scipy

    (5)pip3 install sklearn

    (6)pip install PyQt5

    (7)pip3.6 install PyQt5-tools

    (8)pip install matplotlib

    安装教程

    (1)python3.6+pyQt5+QtDesigner简易安装教程 - Rocket_J的博客 - CSDN博客

                 https://blog.csdn.net/Rocket_J/article/details/80897367

    (2)python3+PyQt5+Qt designer+pycharm安装及配置+将ui文件转py文件 - lyzwjaa的博客 - CSDN博客 

                 https://blog.csdn.net/lyzwjaa/article/details/79429901

    展开全文
  • MATLAB手写数字识别

    千次阅读 多人点赞 2020-01-02 16:58:38
    处理图片,拿到数字区域并分割保存 clc,clear,close all; f=imread('num.jpg'); bw=~im2bw(f); se=strel('line',200,0); bw_dilate=imdilate(bw,se); bw_dilate_erode=imerode(bw_dilate,strel(...

    MATLAB基于svm的手写数字识别

    使用svm进行手写字体识别

    测试图片

    在这里插入图片描述

    处理图片,拿到数字区域并分割保存

    clc,clear,close all;
    f=imread('num.jpg');
    bw=~im2bw(f);
    
    se=strel('line',200,0);
    bw_dilate=imdilate(bw,se);
    
    
    bw_dilate_erode=imerode(bw_dilate,strel('line',1000,0));
    
    bw_re=imreconstruct(bw_dilate_erode,bw_dilate);
    
    result=imreconstruct(bw_re,bw);[r,c]=find(result);
    nextresult=result(min(r) :max(r),min(c):max(c));
    
    [h,w]=size(nextresult);
    hs=sum(nextresult);
    
    a=1;b=1;i=1;
    splitfs={};points=[];
    figure
    while(a<w)
        while(hs(a)==0&&a<w)
            a=a+1;
        end
        b=a;
        while(hs(b)>0&&b<w)
            b=b+1;
        end
        
        if(b-a>2)
            hresult=nextresult(:,a:b);
            [r,c]=find(hresult);
            result2=hresult(min(r):max(r),:);
            m=min(r);n=max(r);
            xi=hresult(m:n,:);
            splitfs{i}=xi;
            points=[points;m,n,a,b];
            subplot(3,6,i),imshow(result2);
            i=i+1;
        end
        a=b;
    end
    

    在这里插入图片描述

    格式化图片

    function x=picPretreatment(im)
    bw=im2bw(im);
    [r,c]=find(bw);
    x=bw(min(r):max(r),min(c):max(c));
    x=imresize(x,[16,16]);
    

    训练数据集,得到 mynet.mat

    clear,clc,close all;
    k=1;
    for m=0:9
        for n=1:15
            f=imread(strcat('nums\',int2str(m),'\',int2str(n),'.bmp'));
            f=picPretreatment(f);
            xx=double(f(:));
            P(k,:)=xx';
            T(k,1)=m;
            k=k+1;
        end
    end
    net=fitcecoc(P,T);
    save mynet net;
    
    

    结果

    注意将图片转化为double

    xs=[splitfs,points];
    fonts='0123456789';
    endresult='手写数字为:';
    load mynet;
    for m_18=1:size(xs,2)-1
        g=xs{m_18};
        g=double(picPretreatment(g));
        lastresult=predict(net,g(:)');
        endresult=strcat(endresult,string(lastresult));
    end
    endresult
    

    在这里插入图片描述

    项目源码

    链接:https://pan.baidu.com/s/1PcWrdyP41BGWuEu4TyWIvQ
    提取码:lnke

    展开全文
  • 手写数字识别(三)

    千次阅读 2018-07-18 16:38:31
    1. 数字分割 一个比较简单的方法是通过统计图像的灰度进行划分。先统计每一行的灰度值,对于遇到的空白区间作为划分行,然后以同样方法划分列,以此确定分区。但是很显然这样的方法对于数字密集或者是轻微的倾斜...

    手写数字识别(三)

    数字分割、识别

    1. 数字分割

    一个比较简单的方法是通过统计图像的灰度进行划分。先统计每一行的灰度值,对于遇到的空白区间作为划分行,然后以同样方法划分列,以此确定分区。但是很显然这样的方法对于数字密集或者是轻微的倾斜都会有问题。
    我写的是通过bfs来划分,首先是通过膨胀处理,然后对于所有未标记的黑点走一次bfs,把同一个联通块看做是一个数字,并且在bfs的同时打上标记,以此划分为一个box,包含唯一的标记以及box长宽等。同时注意到数字 “5” 的一横可能会与本体分离,对于这种情况考虑所有宽比长大数倍的box(因为正常数字都是长比宽大),找一个最近的box进行合并,如果最近的box距离过远,那么判断这个box是一个废弃的噪音。通过这个方法可以很好地分割出数字
    效果:
    这里写图片描述

    2. 数字识别

    最基本的就是SVM,但是普通SVM效果并不好,需要使用hog做特征工程才能使得效果更好。
    一个比较方便的方法是使用 Keras 构建神经网络,对 MNIST数据集进行训练。网上也有很多教程,这里用的是CNN。

    # load data
    (X_train, y_train), (X_test, y_test) = mnist.load_data()
    # reshape to be [samples][pixels][width][height]
    X_train = X_train.reshape(X_train.shape[0], 1, 28, 28).astype('float32')
    X_test = X_test.reshape(X_test.shape[0], 1, 28, 28).astype('float32')
    
    X_train = X_train / 255
    X_test = X_test / 255
    X_train = numpy.round(X_train)*1.0
    X_test = numpy.round(X_test)*1.0
    # one hot encode outputs
    y_train = np_utils.to_categorical(y_train)
    y_test = np_utils.to_categorical(y_test)
    num_classes = y_test.shape[1]
    def baseline_model():
        # create model
        model = Sequential()
        model.add(Conv2D(32, (5, 5), input_shape=(1, 28, 28), activation='relu'))
        model.add(MaxPooling2D(pool_size=(2, 2)))
        model.add(Dropout(0.2))
        model.add(Flatten())
        model.add(Dense(128, activation='relu'))
        model.add(Dense(num_classes, activation='softmax'))
        # Compile model
        model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
        return model
    # build the model
    model = baseline_model()
    # Fit the model
    model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=1, batch_size=200)
    # Final evaluation of the model
    scores = model.evaluate(X_test, y_test, verbose=0)
    print("Baseline Error: %.2f%%" % (100-scores[1]*100))
    model.save('cnn_model.h5') 

    由于前期是使用 C++ 做的分割,后面用python识别,在Ubuntu下采取的是先把数字切割下来保存起来,再通过c++调用python运行识别

    char command[1000];
    FILE *fp;
    /*将要执行的命令写入buf*/
    string python_order = "python digit_rec.py "+file_name;
    snprintf(command, sizeof(command), python_order.c_str());
    /*执行预先设定的命令,并读出该命令的标准输出*/
    fp = popen(command, "r");
    if(NULL == fp) {
        perror("popen执行失败!");
        exit(1);
    }
    printf("DONE");

    另外数字图像保存是默认 28*28 的(训练集的原因),对图像保存是找到对应的box,采用比box稍大的正方形矩阵,把box的内容(即数字)复制到矩形中,由于box中的黑色像素打了标记的,就算两个box有重叠区域也不会有关系。再把这个矩形resize为 28*28 的进行保存
    这里写图片描述

    3. 最终结果

    包含原图的四个角点以及识别后的数字
    这里写图片描述

    展开全文
  • 基于Keras:手写数字识别

    千次阅读 2018-10-05 02:21:12
    手写数字识别通常作为第一个深度学习在计算机视觉方面应用的示例,Mnist数据集在这当中也被广泛采用,可用于进行训练及模型性能测试; 模型的输入为: 32*32的手写字体图片,这些手写字体包含0~9数字,也就是相当于...
  • 手写数字识别问题实战

    千次阅读 2020-04-02 11:04:46
    1、何为手写数字识别问题? 手写数字识别即将如下图所示的各种各样的手写体阿拉伯数字识别出来的一个过程,这个问题已经被研究的很成熟了,也有人搜集和整理了手写数字的数据集-mnist。 2、如何解决手写数字...
  • Python SVM 手写数字识别 流程

    千次阅读 2019-08-29 10:16:54
    Python SVM 手写数字识别 流程 数据采集和标志 scikit-learn 自带了一些数据集,其中一个是数字识别图片的数据。 %matplotlib inline import matplotlib.pyplot as plt import numpy as np from sklearn import ...
  • 神经网络实现Mnist手写数字识别笔记

    千次阅读 2018-10-20 21:31:24
    1.Mnist手写数字识别介绍 2.神经网络架构介绍 3.代码实现 4.运行结果 5.代码中部分方法介绍 1.Mnist手写数字识别介绍  Mnist手写数字识别是Kaggle上一个很经典的机器学习数据集,里边包括55000张训练数据和...
  • 1、输入:有一张数字的A4纸的图片(如下) 2、A4纸矫正 3、数字字符切割 4、用Adaboost或SVM训练一个手写数字分类器 5、识别并输出:连串数字,如“13924579693”与“02087836761”等 实现环境: Windows10 + ...
  • 手写数字的分割和识别

    千次阅读 多人点赞 2019-04-08 11:41:23
    在机器学习领域,手写数字数据集MNIST之于机器学习几乎相当于HelloWorld之于编程语言,其重要地位不言而已。但是,然后呢?给你一张如下所示的图片,你的模型能否也预测出结果?(其实下面这个应用就是OCR领域的内容...
  • 前言前两天利用kNN实现了手写数字的识别,数据不是很多,训练数据1934个,测试数据946个。...Mnist-image的手写数字数据有7万的图像数据(6万训练数据+1万测试数据),每个图像数据为 20px * 20px。
  • KNN实现手写数字识别

    千次阅读 2018-03-28 19:27:43
    KNN简介 物以类聚,人以群分就是KNN的算法的宗旨,要辨识一个人大概是社么样的人,可以他的朋友圈入手,看他的盆友圈属于哪种类型(和哪种类型的盆友圈最接近,比如经常去夜店的二代、老实的码农、像我这样帅的人...
  • 利用Tensorflow实现手写数字识别(附python代码)

    千次阅读 多人点赞 2019-08-22 16:00:22
    手写识别的应用场景有很多,智能手机、掌上电脑的信息工具的普及,手写文字输入,机器识别...我们来尝试搭建下手识别中最基础的手写数字识别,与手写识别的不同是数字识别只需要识别0-9的数字,样本数据集也只需...
  • python 手写数字识别知识不用多说,本文只要讲解在手写数字识别开发过程中所遇到的坑。 1、训练模型 通过keras训练模型,并保存该模型 import numpy from keras.datasets import mnist from keras.models ...
  • k-近邻算法实现手写数字识别系统

    千次阅读 2017-03-26 15:48:41
    本实验将会电影题材分类的例子入手,详细讲述k-近邻算法的原理。在这之后,我们将会使用该算法实现手写数字识别系统。 1.2 课程来源 本课程源自 图灵教育 的 《机器学习实战》 书籍第2章,感谢 图灵教育 ...
  • Pytorch+CNN 识别自己手写的数字

    千次阅读 热门讨论 2019-07-26 13:56:35
    Pytorch+CNN 识别自己...如果想看原理的话,可以网上查,有很多讲解手写数字识别原理的博客都很不错。 训练和测试数据集使用MNIST,在代码中可以下载。事先在电脑自带的画图软件上画出几个数字,尽量的小一点...
  • 1、数学基础:矩阵乘法、高数、不多做赘述直接上公式 2、推倒过程如下图片所示: 二、BP神经网络基于python的实现 代码: 可以直接使用,需要下载手写数字识别图像的文件,训练集:...
  • 1、Sklearn.svm学习  数据集下载:trainingDigits训练集下载 , testDigits测试集下载  详细数据介绍参看:KNN算法实现手写数字识别 2、代码实现  # -*- coding: UTF-8 -*- import numpy as np from os ...
  • 编写一个程序,求出200到300之间的数,且满足条件:它们三个数字之积为42,三个数字之和为12。 任务 1.循环遍历200到300之间的整数 2.分别取出个位、十位和百位上的数 3.求三个数字的和与积 4。判断三个数字的...
  • 本文由@星沉阁冰不语出品,转载请注明作者和出处。文章链接:http://blog.csdn.net/xingchenbingbuyu/article/details/53704085微博:http://weibo.com/xingchenbing 之前...试试出来的神经网络怎么样吧。一、数据准
  • 基于K近邻法的手写数字图像识别

    千次阅读 2017-05-29 17:53:32
     数字图像处理课程论文  题目:数字图像识别   摘要  模式识别(PatternRecognition)是一项借助计算机,就人类对外部世界某一特定环境中的客体、过程和现象的识别功能(包括视觉、听觉、触觉、判断等)进行...
  • keras入门实战:手写数字识别

    万次阅读 2017-06-30 14:58:38
    【声明】本文是blog的翻译和个人的学习笔记导读近些年由于理论知识的硬件的快速发展,使得深度学习达到了空前的火热。...mnist手写数字识别是机器学习和深度学习领域的“hello world”,MNIST数据集是手写数字
  • 目录 目录 数据集的介绍 定义神经网络 开始训练模型 导入依赖包 初始化Paddle ...如题目所示,本次训练使用的是MNIST数据库的手写数字,这个数据集包含60,000个示例的训练集以及10,000个示例的测试集....
  • keras实现mnist数据集手写数字识别

    万次阅读 多人点赞 2018-07-16 20:42:21
    关于keras识别手写数字的入门准备: 1.Keras是一个高层神经网络API,Keras由纯Python编写而成并基Tensorflow、Theano以及CNTK后端。所以在安装keras的前面,要先搭建tensorflow环境和安装...
  • 用Python数字小游戏

    千次阅读 2020-03-21 18:45:26
    1、程序随机生成一个100以内(含100)的正整数 2、将用户输入的答案与随机生成的整数进行比较,给出提示“猜大了”、“猜小了”或者“猜对了” 3、用户可重复输入,直到猜对为止。 4、该游戏可反复执行多次,每次游戏...
  • BP神经网络实现手写数字输入python 首先,我们需要引入下面两个库 import numpy import scipy.special 然后创建一个神经网络类,类里有三个函数:初始化函数、训练函数和查询函数。 初始化函数 1、引入输入层、隐藏...
  • 自动生成1到100的数字自增序列的几种方法 ==之所以这个题目,是原于一道笔试题,加上自己喜欢用的一些小方法,汇总如下: 1.编程语言,此方法由于语言的不同而存在语法上的差异,在此仅简单举例如下python脚本:...
  • 机器学习之手写数字识别大作业报告

    千次阅读 多人点赞 2020-05-03 19:21:57
    在前面 在选择特征的时候,曾纠结过是用颜色矩、像素值还是图片卷积过后的值作为特征,我选择了后者,因为个人觉得手写数字识别相对于水质颜色识别来说,更关注图片的二维结构信息,如果用颜色矩或者像素值作为...
  • 3,用for循环打印出所有在100至200之间的数字。 4,在for循环中,判断每当循环执行一次,就判断循环变量的值是否为素数,如果是,就把循环变量的当前值大于出来。 5,比如一个数为n,就用2至n-1来除n,以此来判断...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 222,953
精华内容 89,181
关键字:

从1写到200的数字