• 基于朴素贝叶斯识别简单验证码


    朴素贝叶斯定理

    原理请参考:
    http://www.ruanyifeng.com/blog/2011/08/bayesian_inference_part_one.html
    https://www.cnblogs.com/TimVerion/p/11197043.html

    即 后验概率 = 先验概率 * 调整因子

    在分类中,先验概率指样本中该类别占所有类别的概率,调整因子则是每个样本特征的概率乘积,举个例子。

    帅不帅 性格 上进不 值不值得交朋友
    不上进 不值得
    不帅 不好 不上进 不值得
    上进 值得
    不帅 上进 值得

    这里的先验概率就是指:值得交朋友(1/2) , 不值得交朋友(1/2)

    调整因子是指你要预测的样本的特征概率,如果有一个样本是不帅|好|不上进(例子特征不分散,因为只有两个值,我们先不管这个)

    那么值得交的后验概率= 1/2 * 调整因子 = 0, 调整因子 = 不帅在值得交的数据中占(1/2) * 好在值得占(1) * 不上进在值得占(0)
    不值得交的后验概率 = 1/2* 1/2 * 1/2 * 1 = 1/8

    所以这个人值不值得交呢,根据数据是1/8>0,那就是不值得交了。不过因为样本数据较少,出现某个为0的概率,这就有点问题了,因为实际不可能概率为0的。

    平滑参数

    所以我们需要引入一个平滑参数,来使这个值不为0

    那么我们计算概率时不是直接使用:符合要求的样本/总样本,而是 符合要求的样本 + alpha/(总样本+标签类别数或特征类别数 * alpha),alpha一般取1.0

    即先验概率:值得交朋友(2 + 1/(4+2 * 1))=1/3 , 不值得交朋友(2 + 1/(4+2 * 1)) = 1/3

    而特征概率的计算需要这样计算:其他先不看,我们直接看值得交中不上进的概率(也就是先前为0的概率)= 0+1/(2 + 2*1) = 1/4, 注意这里的类别数是指len(上进,不上进)
    值得交的后验概率:1/3 * 1/2 * 3/4 * 1/4 = 1/32
    不值得交的后验概率: 1/3 * 1/2 * 1/2 * 3/4 = 1/16

    虽然还是不值得交,但至少值得交的概率不为0了。如果你还不懂的话,直接看验证码的识别,然后在回来看这个。

    sklearn中的api

    sklearn.naive_bayes.MultinomialNB(alpha=1.0, fit_prior=True, class_prior=None)
    参数

    • alpha:上面说的平滑参数
    • fit_prior: 是否考虑先验概率,也就是每个类别所占的比例
    • class_prior: 给定的先验概率数组
      属性
    • class_log_prior_ : 数组, 维度(n_classes, ),每个类别的对数概率。n_classes为类别数量,比如有10个类别,每个类别样本都是100个,则数组为(In 1/10, In 1/10,...)
    • intercept_ : 同class_log_prior_
    • feature_log_prob_ : 数组,维度(n_classes,n_features)给定一类特征的经验对数概率P(x_i|y)。没看懂
    • coef_ : 同feature_log_prob_
    • class_count_ : 数组,维度(n_classes, )每个类别的样本个数
    • classes_ : 数组,维度(n_classes,)每个类别的标签
    • feature_count_ : 数组,形状(n_classes,n_features)拟合期间每个(类,特征)遇到的样本数。没看懂
      方法
    • fit(x, y[, sample_weight]): 使用样本x和标签y作训练
    • get_params(deep=True): 获取模型的所有参数,deep不知道有什么用
    • partial_fit(x, y[, classes, sample_weight]): 一批一批的训练样本(当样本足够大时)
    • predict(test_x): 根据样本test_x,返回预测y
    • predict_proba(test_x): 返回样本test_x属于每个类别的概率,也就是说返回的是维度为(样本数, k)的二维数组,每行一维数组的所有元素和为1,数组长度为k。
    • score(test_x, y, sample_weight =None): 根据样本test_x预测test_y, 然后对比实际的y返回的正确分数,sample_weight为权重
    • set_params(**args): 重新设置模型参数

    当然还有其他朴素贝叶斯分类或回归器,区别如下:
    特征是离散变量时,使用多项式模型(MultinomialNB)
    当特征是连续变量时,使用高斯模型(GaussianNB)
    伯努利模型(BernoulliNB)和多项式模型是一致的,但要求特征是二值化的(1,0)

    生成模型

    根据上面的描述可知,像这种简单验证码,可以使用多项式模型,也可以使用伯努利模型,因为图片已经被二值化。

    已知图片是18x10的二维数组,数组的每个元素都是0,1之间的数。我们可以组成180个特征,而验证码都是0-9的数字,所以分类是这样来计算的

    假设180个特征分别为x1, x2,...,x180,标签为0-9,每个标签的样本个数都是120个
    某个样本属于0的概率:P(0) = P0(x1)P0(x2)....P0(x180)P总(0), P0(x1)表示x1在0类别样本中所占的比例(概率),P总(0)表示0占总样本的比例(概率)即1/10, 这些值都是可以从训练样本求得。

    代码和KNN的基本一样,如下:

    from sklearn import naive_bayes
    import os
    from PIL import Image
    import numpy as np
    
    
    def func():
        x = []
        y = []
        for label in os.listdir('train'):
            for file in os.listdir(f'train/{label}'):
                im = Image.open(f'train/{label}/{file}')
                pix = np.array(im)
                pix = (pix > 180) * 1
                pix = pix.ravel()
                x.append(list(pix))
                y.append(int(label))
    
        train_x = np.array(x)
        train_y = np.array(y)
    
    
        model = naive_bayes.MultinomialNB(alpha=1)
    
        model.fit(train_x, train_y)
    
        x = []
        y = []
        for label in os.listdir('test'):
            for file in os.listdir(f'test/{label}'):
                im = Image.open(f'test/{label}/{file}')
                pix = np.array(im)
                pix = (pix > 180) * 1
                pix = pix.ravel()
                x.append(list(pix))
                y.append(int(label))
    
        test_x = np.array(x)
        test_y = np.array(y)
        score = model.score(test_x, test_y)
    
        return score
    
    if __name__ == "__main__":
        score = func()
        print(score)
    
    
    

    在这种简单验证码识别上,朴素贝叶斯也可以达到100%的正确率。如果将样本特征改成16个的话,你会发现朴素贝叶斯和KNN错误的地方都是一样的,都是同一个验证码识别成了同一个错误。

    最后,我正在学习一些机器学习的算法,对于一些我需要记录的内容我都会分享到博客和微信公众号,欢迎关注。平时的话一般分享一些爬虫或者Python的内容。另外,如果博客有错误的话,还请指出。

    这是已标注的数据:https://www.lanzous.com/i8epywd

    最后,我正在学习一些机器学习的算法,对于一些我需要记录的内容我都会分享到博客和微信公众号(python成长路),欢迎关注。平时的话一般分享一些爬虫或者Python的内容。
    lUE1wd.jpg

  • 相关阅读:
    IOS学习计划
    IOS学习计划
    Android 多线程注意事项
    Android BroadcastReceiver 的简单实现
    新书《iOS编程(第6版)》抢鲜试读
    Apple Watch 2.0 数据通讯
    iOS 9 新特性
    Apple Watch 1.0 开发介绍 2.1 WatchKit Apps UI要点
    Apple Watch 1.0 开发介绍 1.4 简介 使用iOS技术
    Apple Watch 1.0 开发介绍 1.3 简介 WatchKit App 架构
  • 原文地址:https://www.cnblogs.com/kanadeblisst/p/12167477.html
Copyright © 2020-2023  润新知