📜  数据挖掘-贝叶斯分类(1)

📅  最后修改于: 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)
总结

贝叶斯分类是一种简单且有效的分类算法,适用于许多分类问题。尽管其基于独立性假设,但仍然在实际应用中表现出色。在文本分类等领域中,已经有大量的应用案例。