贝叶斯分类算法实例 --根据姓名推测男女

简介:

一.从贝叶斯公式开始

贝叶斯分类其实是利用用贝叶斯公式,算出每种情况下发生的概率,再取概率较大的一个分类作为结果。我们先来看看贝叶斯公式:

P(A|B) = P(B|A) P(A) / P(B)

其中P(A|B)是指在事件B发生的情况下事件A发生的概率。

在贝叶斯定理中,每个名词都有约定俗成的名称:

  • P(A|B)是已知B发生后A的条件概率,也由于得自B的取值而被称作A的后验概率。
  • P(A)是A的先验概率(或边缘概率)。之所以称为"先验"是因为它不考虑任何B方面的因素。
  • P(B|A)是已知A发生后B的条件概率,也由于得自A的取值而被称作B的后验概率。
  • P(B)是B的先验概率或边缘概率。

这里可以用一个例子来说明这个公式。

看一个简单的小例子来展示贝叶斯定理

病人的例子:
某个医院早上收了八个门诊病人,如下表。

症状 职业 疾病
打喷嚏 护士   感冒
打喷嚏 农夫   过敏
头痛  建筑工人 脑震荡
头痛  建筑工人 感冒
打喷嚏  建筑工人 过敏
打喷嚏 教师   感冒
头痛  教师   脑震荡
打喷嚏 教师   过敏

现在又来了第九个病人,是一个打喷嚏的建筑工人。请问他患上感冒的概率有多大?

根据贝叶斯定理:

P(A|B) = P(B|A) P(A) / P(B)

可得满足“打喷嚏”和“建筑工人”两个条件下,感冒的概率如下:

 P(感冒|打喷嚏x建筑工人)
= P(打喷嚏x建筑工人|感冒) x P(感冒) / P(打喷嚏x建筑工人)

假定"打喷嚏"和"建筑工人"这两个特征是独立的(即这两个条件没有相关性,比如不存在说他是建筑工人他打喷嚏的概率比较大或者比较小这种关系),因此,上面的等式就变成了。

 P(感冒|打喷嚏x建筑工人) 
 = P(打喷嚏|感冒) x P(建筑工人|感冒) x P(感冒) /  P(打喷嚏) x P(建筑工人)

通过统计可得:

 P(感冒|打喷嚏x建筑工人) 
 = (2/3) x (1/3) x (3/8) / (5/8) x (3/8) 
 = (16/45)

通过贝叶斯公式算出了满足条件下感冒的概率,那么现在贝叶斯分类器如何实现呢?

接上面的例子,从上面我们得出了 P(感冒|打喷嚏x建筑工人) 的值,那么我们可以再算出
P(不感冒|打喷嚏x建筑工人) 的值,计算结果如下:

 P(不感冒|打喷嚏x建筑工人) 

 = P(打喷嚏|不感冒) x P(建筑工人|不感冒) x P(不感冒)  /  P(打喷嚏) x P(建筑工人)
 = (3/5) x (2/5) x (5/8) / (5/8) x (3/8) 
 = (16/25)

OK,现在我们知道来一个打喷嚏的建筑工人,他感冒的几率是P(感冒|打喷嚏x建筑工人)= (16/45)。不感冒的几率是P(不感冒|打喷嚏x建筑工人)= (16/45)。

通过对概率的比较,我们就可以将打喷嚏的建筑工人分类到“不感冒”人群中(不感冒的概率比较大)。 这就是朴素贝叶斯分类器的最简单的应用了。当然你也看到了,贝叶斯分类器需要我们应用到统计所得的结果,这需要数据量比较大,大到能满足大数定理(大数定理这里就不多解释啦,自行百度即可),以及样本数据足够客观。

接下来我们看一个实际的例子,是我在 github 上看到的一个项目例子,根据姓名来对性别进行分类。看上去觉得很不可思议吧,其实也是用了上述说的贝叶斯分类的方法。

二.贝叶斯分类器根据姓名判别男女 -python

项目github地址:https://github.com/observerss/ngender

先说一下主要思路,我们日常从一个人的名字中,基本上能大致判断这个名字的主人是男是女。比如李大志,这个名字一听就很男性。为什么呢?因为字和字男性名字用得比较多。虽然机器一眼看不出来,但它可以通过统计信息来判断。如果有足够多的数据,我们就可以统计出字和字用作男性名字的比例,计算概率信息。然后就可以用这些概率,运用上述的贝叶斯公式来进行计算,判定性别。

代码其实不难,各个字的统计数据已经计算好,在项目中给出。我们只需要读取文件数据,存储到 python 的字典中,计算出概率,然后预测的时候进行计算即可。我们先看核心代码,稍后会有例子说明。

里面核心代码文件为:

这里主要讲一下核心代码的内容:https://github.com/observerss/ngender/blob/master/ngender/ngender.py

class Guesser(object):

    //初始化函数,调用下面的_load_model()函数
    def __init__(self):
        self._load_model()

    //初始化一些参数
    def _load_model(self):
        self.male_total = 0
        self.female_total = 0
        self.freq = {}

        //这里加载charfreq.csv文件,这个文件存放的是一些汉字是男女的统计信息
        with open(os.path.join(os.path.dirname(__file__),
                               'charfreq.csv'),
                  'rb') as f:
            # skip first line
            next(f)
            //将文件中的信息存储,累加,以便稍后计算概率
            for line in f:
                line = line.decode('utf-8')
                char, male, female = line.split(',')
                char = py2compat(char)
                //计算男性总数
                self.male_total += int(male)
                //计算女性总数
                self.female_total += int(female)
                //一个汉字对应的那女数量
                self.freq[char] = (int(female), int(male))

        self.total = self.male_total + self.female_total

        //一个汉字是男女概率
        for char in self.freq:
            female, male = self.freq[char]
            self.freq[char] = (1. * female / self.female_total,
                               1. * male / self.male_total)

    def guess(self, name):
        name = py2compat(name)
         //去掉姓氏
        firstname = name[1:]
        //过滤掉不在这个unicode编码范围内的字符
        for char in firstname:
            assert u'\u4e00' <= char <= u'\u9fa0', u'姓名必须为中文'

         //贝叶斯分类器,分别计算出男的概率和女的概率
        pf = self.prob_for_gender(firstname, 0)
        pm = self.prob_for_gender(firstname, 1)

        //若名字为男的概率较大,则分类为男,反之则为女
        if pm  pf:
            return ('male', 1. * pm / (pm + pf))
        elif pm < pf:
            return ('female', 1. * pf / (pm + pf))
        else:
            return ('unknown', 0)

    //贝叶斯公式的应用
    def prob_for_gender(self, firstname, gender=0):
        p = 1. * self.female_total / self.total \
            if gender == 0 \
            else 1. * self.male_total / self.total

        for char in firstname:
            p *= self.freq.get(char, (0, 0))[gender]

        return p


guesser = Guesser()

上述代码还是比较简单的,首先在初始化的时候会调用 _load_model() 函数,这个函数完成的是一些概率计算工作,比如先将每个字对应是男是女的概率计算好存储在字典中。

然后在计算的时候,先过滤掉姓氏。然后分别计算出这个名字是男是女的概率,比如计算 P(男|李大志)和P(女|李大志),,对比哪个概率大一些,然后进行男女分类。

这里放上一个例子:判断

P(gender=男|name=本山) 
= P(name=本山|gender=男) * P(gender=男) / P(name=本山)
= P(name has 本|gender=男) * P(name has 山|gender=男) * P(gender=男) / P(name=本山)
  • 公式原理为贝叶斯公式,下面对公式中中各个项进行解答,首先明确我们已经统计得到P(gender=男),P(gender=女)的概率。

怎么算 P(name has 本|gender=男)?

  • “本”在男性名字中出现的次数 / 男性字出现的总次数

怎么算 P(gender=男)?

  • 男性名出现的次数 / 总次数

怎么算 P(name=本山)?

这个概率对男女来说都是一样的,所以没必要算出来,即我们只需要比较P(name=本山|gender=男) P(gender=男)和P(name=本山|gender=女) P(gender=女)两部分谁比较大即可做出判断。

以上就是贝叶斯分类器介绍的全部内容啦。

参考文章:
http://www.ruanyifeng.com/blog/2013/12/naive_bayes_classifier.html

相关文章
|
1月前
|
存储 算法 测试技术
ArrayList集合的两个实例应用,有趣的洗牌算法与杨辉三角
ArrayList集合的两个实例应用,有趣的洗牌算法与杨辉三角
23 1
|
2月前
|
机器学习/深度学习 监控 算法
yolov8+多算法多目标追踪+实例分割+目标检测+姿态估计(代码+教程)
yolov8+多算法多目标追踪+实例分割+目标检测+姿态估计(代码+教程)
124 1
|
6月前
|
算法 Python
k-近邻算法介绍及实例
欢迎关注我的微信公众号:Python学习杂记
k-近邻算法介绍及实例
|
6月前
|
机器学习/深度学习 算法 Python
逻辑回归模型及算法实例
欢迎关注我的微信公众号:Python学习杂记
|
7月前
|
算法
数据结构与算法1.3 算法实例算法1、2、3、4
数据结构与算法1.3 算法实例算法1、2、3、4
41 0
|
7天前
|
算法 数据可视化 Python
Python贝叶斯推断Metropolis-Hastings(M-H)MCMC采样算法的实现
Python贝叶斯推断Metropolis-Hastings(M-H)MCMC采样算法的实现
11 0
|
8天前
|
机器学习/深度学习 算法 C++
R语言贝叶斯MCMC:GLM逻辑回归、Rstan线性回归、Metropolis Hastings与Gibbs采样算法实例
R语言贝叶斯MCMC:GLM逻辑回归、Rstan线性回归、Metropolis Hastings与Gibbs采样算法实例
38 0
|
8天前
|
算法 数据可视化 Python
Python中LARS和Lasso回归之最小角算法Lars分析波士顿住房数据实例
Python中LARS和Lasso回归之最小角算法Lars分析波士顿住房数据实例
13 0
|
8天前
|
数据采集 算法 数据可视化
R语言聚类算法的应用实例
R语言聚类算法的应用实例
85 18
R语言聚类算法的应用实例
|
1月前
|
XML 机器学习/深度学习 算法
目标检测算法训练数据准备——Penn-Fudan数据集预处理实例说明(附代码)
目标检测算法训练数据准备——Penn-Fudan数据集预处理实例说明(附代码)
33 1