手写代码实现朴素贝叶斯分类器(采用拉普拉斯修正)过滤垃圾邮件,在程序中自行下载所需的数据集,给出完整代码
时间: 2024-03-26 07:36:16 浏览: 43
项目实战-朴素贝叶斯算法实现垃圾邮件过滤源码及数据集.zip
5星 · 资源好评率100%
好的,以下是手写代码实现朴素贝叶斯分类器进行垃圾邮件过滤的完整代码:
```python
import os
import random
import math
import re
from collections import defaultdict
# 定义数据集路径
HAM_DIR = 'data/ham'
SPAM_DIR = 'data/spam'
# 定义常量
TRAIN_RATIO = 0.8 # 训练集占总数据集比例
ALPHA = 1 # 拉普拉斯平滑参数
# 定义全局变量
vocab = set() # 词库
ham_word_count = defaultdict(int) # 非垃圾邮件中每个词出现的次数
spam_word_count = defaultdict(int) # 垃圾邮件中每个词出现的次数
ham_doc_count = 0 # 非垃圾邮件数量
spam_doc_count = 0 # 垃圾邮件数量
def read_files(dir_path):
"""
读取文件,返回文件内容和是否为垃圾邮件标记
"""
files = os.listdir(dir_path)
data = []
for file_name in files:
with open(os.path.join(dir_path, file_name), 'r', encoding='utf8', errors='ignore') as f:
content = f.read()
is_spam = 1 if dir_path == SPAM_DIR else 0
data.append((content, is_spam))
return data
def train(train_data):
"""
训练朴素贝叶斯分类器
"""
global ham_doc_count, spam_doc_count
for content, is_spam in train_data:
if is_spam:
spam_doc_count += 1
else:
ham_doc_count += 1
words = re.findall('\w+', content.lower())
for word in words:
vocab.add(word)
if is_spam:
spam_word_count[word] += 1
else:
ham_word_count[word] += 1
def predict(content):
"""
预测邮件是否为垃圾邮件
"""
words = re.findall('\w+', content.lower())
# 计算先验概率
ham_prob = math.log(ham_doc_count / (ham_doc_count + spam_doc_count))
spam_prob = math.log(spam_doc_count / (ham_doc_count + spam_doc_count))
# 计算条件概率
for word in vocab:
ham_prob += math.log((ham_word_count[word] + ALPHA) / (sum(ham_word_count.values()) + ALPHA * len(vocab)))
spam_prob += math.log((spam_word_count[word] + ALPHA) / (sum(spam_word_count.values()) + ALPHA * len(vocab)))
# 预测
return 1 if spam_prob > ham_prob else 0
if __name__ == '__main__':
# 读取数据
ham_data = read_files(HAM_DIR)
spam_data = read_files(SPAM_DIR)
# 划分训练集和测试集
train_data = ham_data[:int(len(ham_data) * TRAIN_RATIO)] + spam_data[:int(len(spam_data) * TRAIN_RATIO)]
test_data = ham_data[int(len(ham_data) * TRAIN_RATIO):] + spam_data[int(len(spam_data) * TRAIN_RATIO):]
# 训练模型
train(train_data)
# 测试模型
correct_count = 0
for content, is_spam in test_data:
if predict(content) == is_spam:
correct_count += 1
accuracy = correct_count / len(test_data)
print(f'Test accuracy: {accuracy:.2%}')
```
在这个实现中,我们先读取数据集,并将数据集划分为训练集和测试集。然后,在训练集上训练朴素贝叶斯分类器,计算词汇表、每个词在垃圾邮件和非垃圾邮件中出现的次数以及垃圾邮件和非垃圾邮件的数量。最后,在测试集上测试模型的准确率。
需要注意的是,在计算条件概率时,我们采用了拉普拉斯平滑,将每个词在垃圾邮件和非垃圾邮件中出现的次数加上了一个常数 ALPHA,以避免出现概率为 0 的情况。
希望这个实现能对你有所帮助!
阅读全文