本文目录导读:

模糊分类器,这是一个完整的Python实现:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""模糊朴素贝叶斯分类器
用于对文本文件内容进行分类
"""
import os
import re
import math
import pickle
from collections import defaultdict, Counter
from typing import Dict, List, Tuple, Optional
import chardet
class FuzzyNaiveBayesClassifier:
"""模糊朴素贝叶斯分类器"""
def __init__(self, alpha: float = 1.0):
"""
初始化分类器
Args:
alpha: 拉普拉斯平滑参数,控制模糊程度
"""
self.alpha = alpha # 模糊程度参数
self.classes = [] # 类别列表
self.class_prior = {} # 类别先验概率
self.word_counts = defaultdict(lambda: defaultdict(float)) # 词频统计
self.class_word_counts = defaultdict(float) # 每个类别的总词数
self.vocabulary = set() # 词汇表
self.word_weights = {} # 词权重(用于模糊处理)
def _preprocess_text(self, text: str) -> List[str]:
"""
文本预处理:分词并清洗
Args:
text: 原始文本
Returns:
分词后的词列表
"""
# 转换为小写
text = text.lower()
# 去除特殊字符,保留中英文和数字
text = re.sub(r'[^\w\u4e00-\u9fff\s]', ' ', text)
# 简单分词(按空格分割)
words = text.split()
# 过滤短词和数字
words = [word for word in words if len(word) > 1 or word.isalpha()]
return words
def _fuzzy_tokenize(self, words: List[str], fuzziness: float = 0.3) -> List[Tuple[str, float]]:
"""
模糊分词:为每个词添加模糊权重
Args:
words: 原始词列表
fuzziness: 模糊程度 (0-1)
Returns:
(词, 权重) 元组列表
"""
from random import random, uniform
fuzzy_words = []
for word in words:
# 基础权重为1.0
base_weight = 1.0
# 添加模糊扰动
noise = uniform(-fuzziness, fuzziness)
weight = max(0.1, base_weight + noise) # 确保权重不为负
# 对长词给予更高的权重(启发式)
if len(word) > 4:
weight *= 1.2
elif len(word) < 3:
weight *= 0.8
fuzzy_words.append((word, weight))
return fuzzy_words
def _calculate_word_entropy(self, word: str) -> float:
"""
计算词的信息熵(用于模糊处理)
Args:
word: 词
Returns:
信息熵值
"""
if word not in self.word_counts:
return 0.0
total = sum(self.word_counts[word].values())
if total == 0:
return 0.0
entropy = 0.0
for count in self.word_counts[word].values():
if count > 0:
prob = count / total
entropy -= prob * math.log2(prob + 1e-10)
return entropy
def train(self, file_paths: Dict[str, List[str]]) -> None:
"""
训练分类器
Args:
file_paths: 类别到文件路径列表的映射
{'类别1': ['file1.txt', 'file2.txt'],
'类别2': ['file3.txt', 'file4.txt']}
"""
self.classes = list(file_paths.keys())
# 计算每个类别的文档数量
class_doc_counts = {cls: len(paths) for cls, paths in file_paths.items()}
total_docs = sum(class_doc_counts.values())
# 计算先验概率
for cls in self.classes:
self.class_prior[cls] = math.log(class_doc_counts[cls] / total_docs)
# 统计词频
for cls, paths in file_paths.items():
for file_path in paths:
try:
text = self._read_file(file_path)
words = self._preprocess_text(text)
fuzzy_words = self._fuzzy_tokenize(words)
for word, weight in fuzzy_words:
self.word_counts[cls][word] += weight
self.class_word_counts[cls] += weight
self.vocabulary.add(word)
except Exception as e:
print(f"读取文件 {file_path} 时出错: {e}")
# 计算词权重(基于信息熵)
for word in self.vocabulary:
entropy = self._calculate_word_entropy(word)
# 权重与信息熵成反比(熵高的词包含信息少)
self.word_weights[word] = 1.0 / (1.0 + entropy)
def _read_file(self, file_path: str) -> str:
"""
读取文件内容,自动检测编码
Args:
file_path: 文件路径
Returns:
文件内容字符串
"""
with open(file_path, 'rb') as f:
raw_data = f.read()
# 检测编码
result = chardet.detect(raw_data)
encoding = result['encoding'] if result['encoding'] else 'utf-8'
try:
return raw_data.decode(encoding, errors='replace')
except:
return raw_data.decode('utf-8', errors='replace')
def predict(self, file_path: str, top_n: int = 3) -> List[Tuple[str, float]]:
"""
预测文件类别
Args:
file_path: 待分类的文件路径
top_n: 返回前N个可能的类别
Returns:
(类别, 概率) 元组列表,按概率降序排列
"""
text = self._read_file(file_path)
return self.predict_text(text, top_n)
def predict_text(self, text: str, top_n: int = 3) -> List[Tuple[str, float]]:
"""
预测文本类别
Args:
text: 待分类的文本
top_n: 返回前N个可能的类别
Returns:
(类别, 概率) 元组列表
"""
words = self._preprocess_text(text)
fuzzy_words = self._fuzzy_tokenize(words)
# 计算每个类别的后验概率
scores = {}
for cls in self.classes:
# 先验概率
score = self.class_prior[cls]
# 条件概率
class_total = self.class_word_counts[cls]
vocab_size = len(self.vocabulary)
for word, weight in fuzzy_words:
# 添加模糊因子
fuzzy_alpha = self.alpha * self.word_weights.get(word, 1.0)
# 计算条件概率(使用拉普拉斯平滑)
word_count = self.word_counts[cls].get(word, 0)
conditional_prob = (word_count + fuzzy_alpha) / (class_total + fuzzy_alpha * vocab_size)
# 应用词权重
weighted_prob = conditional_prob ** weight
score += math.log(weighted_prob + 1e-10)
scores[cls] = score
# 转换为概率
total = sum(math.exp(s) for s in scores.values())
probabilities = {cls: math.exp(s) / total for cls, s in scores.items()}
# 排序并返回Top N
sorted_probs = sorted(probabilities.items(), key=lambda x: x[1], reverse=True)
return sorted_probs[:top_n]
def save_model(self, filepath: str) -> None:
"""
保存模型到文件
Args:
filepath: 模型文件路径
"""
model_data = {
'classes': self.classes,
'class_prior': self.class_prior,
'word_counts': dict(self.word_counts),
'class_word_counts': dict(self.class_word_counts),
'vocabulary': self.vocabulary,
'word_weights': self.word_weights,
'alpha': self.alpha
}
with open(filepath, 'wb') as f:
pickle.dump(model_data, f)
def load_model(self, filepath: str) -> None:
"""
从文件加载模型
Args:
filepath: 模型文件路径
"""
with open(filepath, 'rb') as f:
model_data = pickle.load(f)
self.classes = model_data['classes']
self.class_prior = model_data['class_prior']
self.word_counts = defaultdict(lambda: defaultdict(float), model_data['word_counts'])
self.class_word_counts = defaultdict(float, model_data['class_word_counts'])
self.vocabulary = model_data['vocabulary']
self.word_weights = model_data['word_weights']
self.alpha = model_data['alpha']
# 使用示例
def create_demo_data():
"""创建演示数据"""
import tempfile
demo_files = {
'技术': [],
'体育': [],
'娱乐': []
}
# 创建临时文件
for category, texts in [
('技术', [
'人工智能和机器学习正在改变世界,深度学习算法可以处理大量数据',
'计算机编程需要掌握多种语言和框架,算法和数据结构很重要',
'云计算和大数据技术正在推动数字化转型,网络安全不容忽视'
]),
('体育', [
'足球比赛中有11名球员,篮球是5对5的团队运动',
'奥运会上有各种体育项目,运动员们为金牌而努力拼搏',
'健身和运动对健康很重要,训练需要持之以恒'
]),
('娱乐', [
'电影和音乐是人们喜爱的娱乐方式,新的作品不断涌现',
'游戏产业正在快速发展,电子竞技吸引了大量观众',
'综艺节目和电视剧丰富了人们的休闲生活'
])
]:
for i, text in enumerate(texts):
# 创建临时文件
with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f:
f.write(text)
file_path = f.name
demo_files[category].append(file_path)
return demo_files
def main():
"""主函数"""
print("=" * 60)
print("模糊朴素贝叶斯分类器示例")
print("=" * 60)
# 创建演示数据
print("\n[1] 创建演示数据...")
train_files = create_demo_data()
# 初始化分类器
print("[2] 初始化分类器...")
classifier = FuzzyNaiveBayesClassifier(alpha=0.5) # 较低的alpha值表示较少的模糊
# 训练模型
print("[3] 训练模型...")
classifier.train(train_files)
print(f" 类别: {classifier.classes}")
print(f" 词汇表大小: {len(classifier.vocabulary)}")
# 测试分类
print("\n[4] 测试分类...")
test_texts = [
"Python编程语言有很多应用,包括数据分析",
"足球明星C罗再次打破纪录",
"最新上映的电影票房很高",
"人工智能在医疗领域的应用"
]
for text in test_texts:
print(f"\n 文本: '{text}'")
results = classifier.predict_text(text, top_n=3)
print(f" 分类结果:")
for category, prob in results:
print(f" - {category}: {prob:.2%}")
# 保存和加载模型
print("\n[5] 保存模型...")
classifier.save_model("fuzzy_bayes_model.pkl")
print("[6] 加载模型...")
new_classifier = FuzzyNaiveBayesClassifier()
new_classifier.load_model("fuzzy_bayes_model.pkl")
# 验证加载的模型
print("[7] 验证加载的模型...")
test_text = "云计算技术不断发展"
results = new_classifier.predict_text(test_text)
print(f" 文本: '{test_text}'")
for category, prob in results:
print(f" - {category}: {prob:.2%}")
print("\n" + "=" * 60)
print("分类器使用完毕!")
print("=" * 60)
if __name__ == "__main__":
main()
安装依赖
pip install chardet
核心特性
模糊处理机制
alpha参数控制平滑程度_fuzzy_tokenize()为词添加随机权重- 基于信息熵的动态词权重
文件处理
- 自动检测文件编码
- 中英文混合文本支持
- 批量文件训练
高级功能
- 模型保存/加载
- 概率输出
- Top-N 分类结果
使用方法
# 基本使用
classifier = FuzzyNaiveBayesClassifier(alpha=0.5)
# 训练数据(文件路径)
train_data = {
'类别1': ['file1.txt', 'file2.txt'],
'类别2': ['file3.txt', 'file4.txt']
}
classifier.train(train_data)
# 分类新文件
result = classifier.predict('new_file.txt')
for category, prob in result:
print(f"{category}: {prob:.2%}")
参数调优建议
- alpha (0.1-1.0): 控制模糊程度,值越小分类越严格
- fuzziness (0.1-0.5): 词权重扰动范围
- top_n: 返回结果数量
这个分类器实现了文件内容的模糊分类,特别适合处理噪声较大的文本数据。