贝叶斯分类器是一种基于贝叶斯定理的强大工具,它能够理解和模仿复杂的数据结构。近年来,它常被用于自然语言处理(NLP)任务,例如文本分类。本文将介绍如何构建一个用于主题分类的朴素贝叶斯文本分类器。
在深入解释之前,需要强调的是,朴素贝叶斯并非传统的主题分类方法。实际上,还有其他模型专为分类主题而发明,例如Blei的标志性的潜在狄利克雷分配(LDA)。尽管朴素贝叶斯将进入竞争激烈的主题分类市场,但其简单性和易于理解的数学基础使其成为开发者的独特工具。
接下来,将需要使用两个包:pandas和textmining。前者将帮助输入数据,后者将数据格式化为文本-文档矩阵。以下是输入数据并将数据分为训练和评估的代码示例。
import textmining
import pandas as pd
df = pd.read_csv("my_data.csv")
train_df = df.iloc[1:1500]
eval_df = df.iloc[1501:2000]
注意到有2000行数据——这是一个相对较小的数据集大小——但仍然保留了25%的样本用于验证。这是许多自然语言处理形式的行业标准,因此鼓励也这样做。
现在,让使用导入的textmining包!textmining包非常简单易用,只需要3行代码就可以创建第一个词-文档矩阵。
# 创建文档词矩阵
tdm = textmining.TermDocumentMatrix()
for ele in train_df["text"]:
tdm.add_doc(ele)
词-文档矩阵是一个文档,其中每一列代表语料库中的一个词,每一行包含文档中每个词的出现次数。接下来,需要一个针对数据集中每个主题的特定词-文档矩阵。这将帮助获得在给定主题下看到词的概率。
topicSpecTDM = {} # 标签:TDM条目的数组
list_of_labels = ["动物","太空","体育"]
for ele in list_of_labels:
sdf = train_df.loc[ele == train_df["labels"]] # 该标签的所有文档
stdm = textmining.TermDocumentMatrix()
for row in sdf["text"]:
stdm.add_doc(row) # 将所有文档添加到TDM
topicSpecTDM[ele] = stdm
topicSpecTDM是一个字典,其中每个键是一个主题,每个值是该主题的特定TDM。接下来,将尝试找到每个主题中每个词的相对频率。将创建的数据结构将被索引,以找到在给定主题下看到词的概率。
topic_term_freq = {} # 主题_name:term_frequency_dictionary条目的字典
for ele in list(topicSpecTDM.keys()):
topic_tdm = topicSpecTDM[ele] # 获取该主题的特定TDM
topic_spec_term_count = {} # 实例化一个字典用于词频率(不是一个列表)
flag = 1
for row in topic_tdm.rows(cutoff=1):
if flag == 1:
for word in row:
topic_spec_term_count[word]=0 # 为所有词实例化0
flag=0
else:
ordered_keys = list(topic_spec_term_count.keys()) # 获取词的列表
for count in range(len(row)):
key = ordered_keys[count]
topic_spec_term_count[key]+=row[count] # 增加词计数
topicSum = sum(list(topic_spec_term_count.values()))
# 从计数转换为频率
for item in list(topic_spec_term_count.keys()):
topic_spec_term_count[item]/=float(topicSum)
topic_term_freq[ele]=topic_spec_term_count
这是一个查看贝叶斯定理将如何帮助实现目标的好时机。贝叶斯定理本身如下,以防忘记了。表示为p(topic)的值是先验,等式的左侧是试图最大化的后验可能性。
现在,可能会问:如何得到p(sentence|topic)?这似乎是一个关键且无法解决的问题!说得对。要做到这一点,必须假设统计学家可能不会太兴奋。
在给定主题下看到句子的概率是聚合句子中所有词在给定主题下看到词的概率的乘积。但这很可怕,对吧?这个方案完全忽略了每个词的位置和每个词的相对重要性。
首先,这就是为什么它被称为朴素贝叶斯而不是细致贝叶斯。其次,结果表明,像相对重要性这样的因素并不是这个模型成功的障碍,主要是因为频率的强大作用。朴素贝叶斯是许多应用的强大工具,其朴素性并没有阻止其发展。
在最后一步中,将最大化右侧(可以计算的)的分子,以最大化左侧(无法计算的)。注意,右侧的分母是一个常数,因此可以忽略它。
最大似然估计。以下是最大化给定句子中词的主题的后验可能性的代码。享受吧!
Bayesian Maximum Likelihood Estimation
乘以看到主题的概率和该主题生成特定词的概率
选择最大化后验概率的主题
返回最佳主题和最佳概率
def MLE(tweet):
best_topic = "None Found"
best_prob = 0
for topic in list_of_labels:
spec_df = train_df.loc[train_df["labels"]==topic]
prior = float(spec_df.shape[0])/train_df.shape[0] # 看到主题的先验概率
prob_of_words = 1.0
for word in tweet.split():
prob_of_words = prob_of_words * topic_term_freq[topic][word] # 乘以新的概率
if prob_of_words*prior > best_prob:
best_topic=topic
best_prob=prob_of_words*prior
return best_topic, best_prob