Python 数据科学手册 5.5 朴素贝叶斯分类

5.5 朴素贝叶斯分类

原文:In Depth: Naive Bayes Classification

译者:飞龙

协议:CC BY-NC-SA 4.0

译文没有得到原作者授权,不保证与原文的意思严格一致。

前四节对机器学习概念进行了总体概述。 在本节和随后的一节中,我们将仔细研究几种具体的监督和无监督学习算法,从这里以朴素贝叶斯分类开始。

朴素贝叶斯模型是一组非常快速和简单的分类算法,通常适用于非常高维的数据集。 因为它们非常快,并且具有如此少的可调参数,所以它们最终适合作为分类问题的快速而粗略的基准。 本节专注于直观的说明,关于贝叶斯分类器的工作原理,其次是一些数据集上的实例。

贝叶斯分类

朴素贝叶斯分类器建立在贝叶斯分类方法上。 它们依赖于贝叶斯定理,一个描述统计量条件概率关系的方程式。 在贝叶斯分类中,给定一些观察特征,我们的兴趣是求出的标签的概率,我们可以将其写为P(L | features)。 贝叶斯定理告诉我们,如何用更直接的计算量来表达这一点:

如果我们试图在两个标签之间作出决定 - 让我们称之为L1L2,那么作出这一决定的一个方法是,计算每个标签的后验概率的比率:

我们现在需要一些模型,我们可以通过它来计算每个标签的P(features | Li)。 这种模型称为生成模型,因为它指定了生成数据的假设随机过程。 为每个标签指定这个生成模型是这种贝叶斯分类器的训练的主要部分。 这种训练步骤的一般版本是一项非常困难的任务,但是我们可以通过使用关于该模型形式的一些简化假设来使其更简单。

这就是“朴素贝叶斯”中的“朴素”:如果我们对每个标签的生成模型做出非常朴素的假设,我们可以找到每个分类的生成模型的粗略近似,然后进行贝叶斯分类。 不同类型的朴素贝叶斯分类器依赖于数据的不同朴素假设,我们将在以下部分中对其中的几个进行研究。

我们以标准导入来开始:

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns; sns.set()

高斯朴素贝叶斯

也许最简单的朴素贝叶斯分类器,是高斯朴素贝叶斯。 在这个分类器中,假设来自每个标签的数据,是从简单的高斯分布中得出的。 假设您有以下数据:

from sklearn.datasets import make_blobs
X, y = make_blobs(100, 2, centers=2, random_state=2, cluster_std=1.5)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='RdBu');

创建简单模型的一个非常快捷的方法是,假设数据服从维度之间没有协方差(独立)的高斯分布。 通过简单地找出每个标签内的点的平均值和标准差,可以得到该模型,这就是您需要定义的分布。 这个朴素高斯假设的结果如下图所示:

这里的椭圆形代表每个标签的高斯生成模型,椭圆的中心具有较大的概率。 对于每个分类,通过这个生成模型,我们有一个简单的秘籍,用于计算任何数据点的可能性P(features | L1),因此我们可以快速计算后验比率,并确定对于给定点,哪个标签是最可能的。

Sklearn 的sklearn.naive_bayes.GaussianNB实现了这个过程。

from sklearn.naive_bayes import GaussianNB
model = GaussianNB()
model.fit(X, y);

现在让我们生成一些新的数据,并预测标签。

rng = np.random.RandomState(0)
Xnew = [-6, -14] + [14, 18] * rng.rand(2000, 2)
ynew = model.predict(Xnew)

现在我们可以绘制新的数据,来了解决策边界在哪里。

plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='RdBu')
lim = plt.axis()
plt.scatter(Xnew[:, 0], Xnew[:, 1], c=ynew, s=20, cmap='RdBu', alpha=0.1)
plt.axis(lim);

我们在分类中看到一个略微弯曲的边界 - 一般来说,高斯朴素贝叶斯的边界是二次的。

这个贝叶斯形式的一个好处是,它自然支持概率分类,我们可以使用predict_proba方法计算:

yprob = model.predict_proba(Xnew)
yprob[-8:].round(2)
array([[ 0.89,  0.11],
       [ 1.  ,  0.  ],
       [ 1.  ,  0.  ],
       [ 1.  ,  0.  ],
       [ 1.  ,  0.  ],
       [ 1.  ,  0.  ],
       [ 0.  ,  1.  ],
       [ 0.15,  0.85]])

这些列分别提供了第一个和第二个标签的后验概率。 如果您正在寻找分类中的不确定性估计,这样的贝叶斯方法可能是有用的方法。

当然,最终的分类只会与产生它的模型假设一样好,这就是高斯朴素的贝叶斯经常不会产生优秀结果的原因。 然而,在许多情况下,特别是随着特征数量的增加,这一假设并不足以阻止高斯朴素贝叶斯成为有用的方法。

多项式朴素贝叶斯

刚刚描述的高斯假设,绝不是唯一的简单假设,可以用于指定每个标签的生成分布。 另一个有用的例子是多项式朴素贝叶斯,其中假设特征从简单的多项式分布生成。 多项式分布描述了在多个类别中观察计数的概率,因此多项朴素贝叶斯最适合于表示计数或计数率的特征。

这个想法与以前一样,除了我们不用最佳拟合高斯模型,而用最合适的多项式分布,对数据分布建模。

示例:文本分类

经常使用多项朴素贝叶斯的一个地方是文本分类,其特征与要分类的文档中的字数或频率有关。 我们在特征工程中讨论了这些特征的提取; 在这里,我们将使用 20 个新闻组语料库中的稀疏字数特征,来展示我们如何将这些简短文档分类。

让我们下载数据并查看目标名称:

from sklearn.datasets import fetch_20newsgroups

data = fetch_20newsgroups()
data.target_names
['alt.atheism',
 'comp.graphics',
 'comp.os.ms-windows.misc',
 'comp.sys.ibm.pc.hardware',
 'comp.sys.mac.hardware',
 'comp.windows.x',
 'misc.forsale',
 'rec.autos',
 'rec.motorcycles',
 'rec.sport.baseball',
 'rec.sport.hockey',
 'sci.crypt',
 'sci.electronics',
 'sci.med',
 'sci.space',
 'soc.religion.christian',
 'talk.politics.guns',
 'talk.politics.mideast',
 'talk.politics.misc',
 'talk.religion.misc']

为了简化,我们选择这些分类中的一些,之后下载测试集。

categories = ['talk.religion.misc', 'soc.religion.christian',
              'sci.space', 'comp.graphics']
train = fetch_20newsgroups(subset='train', categories=categories)
test = fetch_20newsgroups(subset='test', categories=categories)

这里是数据的一个简单展示:

print(train.data[5])
From: dmcgee@uluhe.soest.hawaii.edu (Don McGee)
Subject: Federal Hearing
Originator: dmcgee@uluhe
Organization: School of Ocean and Earth Science and Technology
Distribution: usa
Lines: 10


Fact or rumor....?  Madalyn Murray O'Hare an atheist who eliminated the
use of the bible reading and prayer in public schools 15 years ago is now
going to appear before the FCC with a petition to stop the reading of the
Gospel on the airways of America.  And she is also campaigning to remove
Christmas programs, songs, etc from the public schools.  If it is true
then mail to Federal Communications Commission 1919 H Street Washington DC
20054 expressing your opposition to her request.  Reference Petition number

2493.

为了将这些数据用于机器学习,我们需要将每个字符串的内容转换为数值向量。 为此,我们将使用 TF-IDF 向量化器(在特征工程中讨论),并创建一个流水线,将其附加到多项朴素贝叶斯分类器:

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import make_pipeline

model = make_pipeline(TfidfVectorizer(), MultinomialNB())

使用这个流水签,我们可以将模型用于训练数据,并测试数据的预测标签。

model.fit(train.data, train.target)
labels = model.predict(test.data)

现在我们已经预测了测试数据的标签,我们可以评估它们来了解估计器的性能。 例如,这里是测试数据的真实和预测标签之间的混淆矩阵:

from sklearn.metrics import confusion_matrix
mat = confusion_matrix(test.target, labels)
sns.heatmap(mat.T, square=True, annot=True, fmt='d', cbar=False,
            xticklabels=train.target_names, yticklabels=train.target_names)
plt.xlabel('true label')
plt.ylabel('predicted label');

显然,即使这个非常简单的分类器,也可以成功将空间话题与电脑话题分开,但是在宗教话题和基督教话题之间会混淆。 这是预期的混乱。

这里非常酷,我们现在有了工具,用于确定任何字符串的分类,使用这个流水线的predict()方法。 这是一个简便的工具函数,它返回单个字符串的预测:

def predict_category(s, train=train, model=model):
    pred = model.predict([s])
    return train.target_names[pred[0]]

让我们试试看:

predict_category('sending a payload to the ISS')
'sci.space'
predict_category('discussing islam vs atheism')
'soc.religion.christian'
predict_category('determining the screen resolution')
'comp.graphics'

记住,这并不比字符串中每个单词的(加权)频率的简单概率模型复杂得多; 然而,结果是惊人的。 即使是非常匍匐的算法,当仔细使用并对大量高维数据进行训练时,会有效得令人惊奇。

何时使用朴素贝叶斯

因为朴素的贝叶斯分类器对数据做出了如此严格的假设,所以它们通常不会和更复杂的模型一样好。 也就是说,它们有几个优点:

  • 训练和预测都非常快
  • 提供简单的概率预测
  • 经常很容易解释
  • 具有很少的(如果存在)可调参数

这些优点意味着,朴素的贝叶斯分类器通常是初始基本分类的不错选择。 如果适当使用,那么恭喜:对于你的问题,你有一个非常快速,可解释的分类器。 如果表现不佳,那么您可以开始探索更复杂的模型,使用一些基本知识,了解应该如何进行。

朴素贝叶斯分类器在以下情况之一中往往表现得特别好:

  • 朴素的假设实际匹配数据时(在实践中非常罕见)
  • 对于分隔良好的分类,当模型复杂性不太重要时
  • 对于非常高维的数据,当模型复杂度不太重要时

最后两点看起来是截然不同的,但它们实际上是相关的:随着数据集的维度越来越大,任何两点不可能更接近(毕竟,它们必须在每一个维度上都接近)。 这意味着,如果新维度添加了实际的信息,平均来讲,高维度的簇比低维度更加分散。 因此,随着维度增加,像朴素贝叶斯这样的简单分类器,往往比复杂分类器有效:一旦你拥有足够的数据,即使一个简单的模型也是非常强大的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容