📅  最后修改于: 2023-12-03 15:26:08.222000             🧑  作者: Mango
贝叶斯分类(Naive Bayes Classification)是一种基于贝叶斯定理的分类算法。它被广泛应用于文本分类和垃圾邮件过滤等领域。该算法基于条件概率和独立性假设,实现简单但是效果不错。
贝叶斯分类基于贝叶斯定理,即:
$$ P(A|B) = \frac{P(B|A)P(A)}{P(B)} $$
在分类问题中,我们需要知道给定某个属性值 $x$,它属于某个分类 $C_k$ 的概率 $P(C_k|x)$。根据贝叶斯定理可以将其表示为:
$$ P(C_k|x) = \frac{P(x|C_k)P(C_k)}{P(x)} $$
其中,$P(C_k|x)$ 表示当属性值为 $x$ 时,样本属于 $C_k$ 的概率;$P(C_k)$ 表示先验概率,即在没有任何样本属性信息的情况下,样本属于 $C_k$ 的概率;$P(x|C_k)$ 表示似然概率,即在已知样本属于 $C_k$ 的情况下,属性值为 $x$ 的概率;$P(x)$ 表示归一化因子,其值为所有分类的 $P(x|C_k)P(C_k)$ 之和。
在实际应用中,为了避免过多的计算,我们通常将上式写成下面的形式:
$$ P(C_k|x) \propto P(x|C_k)P(C_k) $$
由于我们只需要找到 $P(C_k|x)$ 最大的类别 $C_k$,因此可以忽略掉归一化因子 $P(x)$。此外,在实际应用中,我们经常对似然概率进行对数转换,避免计算过程中数值下溢。
贝叶斯分类中的“朴素”指的是条件独立性假设。即认为各个属性之间是独立的,不存在相互影响的情况。这个假设虽然在现实中并不成立,但是在大多数情况下效果还是很不错的。
贝叶斯分类在文本分类等问题中应用广泛。下面我们以电子邮件分类为例,介绍使用 Python 实现贝叶斯分类的过程。
首先,我们需要准备两个目录。其中一个目录下保存着已经分类好的正常邮件,另一个目录下保存着已经分类好的垃圾邮件。将邮件内容转换为词向量并计算每个单词在不同类别下的条件概率。得到了这些概率后,对于新的邮件,根据条件概率估计该邮件属于某个类别的概率,最终选择概率最大的类别作为分类结果。
import os
import math
# 读取文件内容为词向量,返回单词列表和单词出现次数字典
def get_words_vector(path):
words = []
word_count = {}
with open(path, 'r', encoding='utf-8') as f:
for line in f:
for word in line.split():
if word not in words:
words.append(word)
word_count[word] = 1
else:
word_count[word] += 1
return words, word_count
# 计算单词在给定类别下的条件概率
def conditional_prob(word, word_count, num_words):
return (word_count.get(word, 0) + 1) / (num_words + len(word_count))
# 计算测试邮件属于各个类别的条件概率
def calculate_prob(test_words, normal_words, spam_words, normal_count, spam_count):
normal_prob, spam_prob = 0, 0
for word in test_words:
normal_prob += math.log(conditional_prob(word, normal_words, normal_count))
spam_prob += math.log(conditional_prob(word, spam_words, spam_count))
return normal_prob, spam_prob
# 对测试邮件进行分类
def classify(test_words, normal_words, spam_words, normal_count, spam_count):
normal_prob, spam_prob = calculate_prob(test_words, normal_words, spam_words, normal_count, spam_count)
if normal_prob > spam_prob:
return "normal"
return "spam"
# 计算正常邮件和垃圾邮件的属性概率
def train(normal_dir, spam_dir):
normal_count = 0
spam_count = 0
normal_words = {}
spam_words = {}
for root, dirs, files in os.walk(normal_dir):
for file in files:
path = os.path.join(root, file)
words, word_count = get_words_vector(path)
normal_count += 1
for word in words:
if word not in normal_words:
normal_words[word] = word_count[word]
else:
normal_words[word] += word_count[word]
for root, dirs, files in os.walk(spam_dir):
for file in files:
path = os.path.join(root, file)
words, word_count = get_words_vector(path)
spam_count += 1
for word in words:
if word not in spam_words:
spam_words[word] = word_count[word]
else:
spam_words[word] += word_count[word]
return normal_words, spam_words, normal_count, spam_count
# 测试
def test(normal_dir, spam_dir, test_dir):
normal_words, spam_words, normal_count, spam_count = train(normal_dir, spam_dir)
with open(test_dir, 'r', encoding='utf-8') as f:
for line in f:
words = line.split()
print(classify(words, normal_words, spam_words, normal_count, spam_count), line)
贝叶斯分类是一种简单且有效的分类算法,适用于许多分类问题。尽管其基于独立性假设,但仍然在实际应用中表现出色。在文本分类等领域中,已经有大量的应用案例。