文本分类:让AI给文章贴标签

🎯 前言:从图书管理员到AI分类专家

想象一下,你是一个古老图书馆的管理员📚,面前堆满了成千上万的书籍和文档。有小说、科技论文、新闻报道、诗歌集…如果没有分类系统,读者想找一本书就像大海捞针!

传统的图书管理员需要一本一本地阅读,然后根据内容给书籍贴上标签:文学、科学、历史、艺术…这个过程既耗时又耗力。

现在,AI时代来了!我们可以训练一个"数字图书管理员",它能够快速阅读文章内容,自动识别主题,并给每篇文章贴上合适的标签。这就是文本分类的魔法!🪄

文本分类就像是给AI装上了一双"火眼金睛",让它能够从海量的文本中快速识别出:

  • 这是一篇科技新闻还是娱乐八卦?
  • 这条评论是正面的还是负面的?
  • 这封邮件是垃圾邮件还是重要邮件?
  • 这篇文章属于哪个类别?

今天,我们就来学习如何训练一个AI分类专家,让它成为你的得力助手!

📚 目录

🧠 什么是文本分类?

生活中的分类无处不在

在日常生活中,我们时刻在进行分类:

  • 整理衣柜:春装、夏装、秋装、冬装 👗
  • 分类垃圾:可回收、不可回收、有害垃圾 🗑️
  • 邮件管理:工作邮件、个人邮件、广告邮件 📧
  • 音乐分类:流行、古典、摇滚、民谣 🎵

文本分类的定义

文本分类是机器学习的一个重要分支,它的目标是:

  • 输入:一段文本内容
  • 输出:预定义的类别标签
  • 过程:通过学习大量已标记的文本数据,让AI掌握不同类别文本的特征
# 文本分类的基本流程
text = "今天股市大涨,科技股表现亮眼"
classifier = TextClassifier()
category = classifier.predict(text)
print(f"文本类别:{category}")  # 输出:财经

分类任务的类型

1. 二分类任务

只有两个类别,像开关一样:

# 垃圾邮件检测
email = "恭喜您中奖了!点击链接领取奖品..."
result = spam_classifier.predict(email)
print(result)  # 输出:垃圾邮件 or 正常邮件
2. 多分类任务

有多个类别,但每个文本只属于一个类别:

# 新闻分类
news = "科学家发现新的系外行星,距离地球100光年"
category = news_classifier.predict(news)
print(category)  # 输出:科技、体育、财经、娱乐等其中一个
3. 多标签分类

每个文本可以属于多个类别:

# 电影标签
movie_desc = "一部关于太空探索的科幻爱情片"
labels = movie_classifier.predict(movie_desc)
print(labels)  # 输出:['科幻', '爱情', '冒险']

🌟 文本分类的应用场景

1. 新闻媒体领域

# 新闻自动分类系统
class NewsClassifier:
    def __init__(self):
        self.categories = [
            "政治", "经济", "科技", "体育", 
            "娱乐", "社会", "国际", "军事"
        ]
    
    def classify_news(self, headline, content):
        # 模拟分类过程
        if "股市" in content or "GDP" in content:
            return "经济"
        elif "科学" in content or "技术" in content:
            return "科技"
        elif "比赛" in content or "运动员" in content:
            return "体育"
        else:
            return "社会"

# 使用示例
classifier = NewsClassifier()
result = classifier.classify_news(
    "人工智能助力医疗诊断",
    "研究人员开发了一种新的AI算法,能够快速准确地诊断疾病"
)
print(f"新闻分类:{result}")

2. 社交媒体情感分析

# 社交媒体情感分类
class SentimentClassifier:
    def analyze_sentiment(self, text):
        positive_words = ["喜欢", "好", "棒", "赞", "优秀", "满意"]
        negative_words = ["讨厌", "差", "糟", "烂", "失望", "愤怒"]
        
        positive_count = sum(1 for word in positive_words if word in text)
        negative_count = sum(1 for word in negative_words if word in text)
        
        if positive_count > negative_count:
            return "积极"
        elif negative_count > positive_count:
            return "消极"
        else:
            return "中性"

# 使用示例
sentiment_analyzer = SentimentClassifier()
comments = [
    "这个产品真的很棒,强烈推荐!",
    "质量太差了,完全不值这个价格",
    "还行吧,没有特别的感觉"
]

for comment in comments:
    sentiment = sentiment_analyzer.analyze_sentiment(comment)
    print(f"评论:{comment}")
    print(f"情感:{sentiment}\n")

3. 客户服务自动化

# 客户问题分类系统
class CustomerServiceClassifier:
    def __init__(self):
        self.categories = {
            "技术支持": ["不能用", "故障", "报错", "bug", "问题"],
            "账户问题": ["密码", "登录", "账号", "注册", "忘记"],
            "订单查询": ["订单", "发货", "物流", "快递", "配送"],
            "退换货": ["退货", "换货", "退款", "不满意", "损坏"],
            "投诉建议": ["投诉", "建议", "意见", "改进", "不满"]
        }
    
    def classify_inquiry(self, message):
        scores = {}
        for category, keywords in self.categories.items():
            score = sum(1 for keyword in keywords if keyword in message)
            scores[category] = score
        
        # 找到得分最高的类别
        best_category = max(scores, key=scores.get)
        return best_category if scores[best_category] > 0 else "其他"

# 使用示例
cs_classifier = CustomerServiceClassifier()
inquiries = [
    "我的账号密码忘记了,怎么找回?",
    "订单什么时候能发货?",
    "产品有问题,想要退货",
    "软件一直报错,无法正常使用"
]

for inquiry in inquiries:
    category = cs_classifier.classify_inquiry(inquiry)
    print(f"客户问题:{inquiry}")
    print(f"分类结果:{category}\n")

4. 学术论文分类

# 学术论文领域分类
class AcademicClassifier:
    def __init__(self):
        self.field_keywords = {
            "人工智能": ["机器学习", "深度学习", "神经网络", "AI", "算法"],
            "生物医学": ["基因", "蛋白质", "细胞", "DNA", "医学"],
            "物理学": ["量子", "粒子", "能量", "物理", "力学"],
            "化学": ["分子", "化学反应", "催化", "化合物", "元素"],
            "数学": ["定理", "证明", "函数", "微积分", "统计"]
        }
    
    def classify_paper(self, title, abstract):
        text = (title + " " + abstract).lower()
        scores = {}
        
        for field, keywords in self.field_keywords.items():
            score = sum(1 for keyword in keywords if keyword in text)
            scores[field] = score
        
        return max(scores, key=scores.get) if max(scores.values()) > 0 else "其他"

# 使用示例
academic_classifier = AcademicClassifier()
paper = {
    "title": "基于深度学习的图像识别算法研究",
    "abstract": "本文提出了一种新的神经网络架构,用于提高图像识别的准确性..."
}

field = academic_classifier.classify_paper(paper["title"], paper["abstract"])
print(f"论文领域:{field}")

🛠️ 分类算法大家族

1. 朴素贝叶斯:概率论的应用

朴素贝叶斯就像一个"统计学专家",它通过计算概率来做决策:

from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import CountVectorizer
import numpy as np

# 朴素贝叶斯分类器示例
class NaiveBayesClassifier:
    def __init__(self):
        self.vectorizer = CountVectorizer()
        self.classifier = MultinomialNB()
    
    def train(self, texts, labels):
        """训练分类器"""
        # 将文本转换为数值特征
        X = self.vectorizer.fit_transform(texts)
        # 训练模型
        self.classifier.fit(X, labels)
    
    def predict(self, text):
        """预测文本类别"""
        X = self.vectorizer.transform([text])
        return self.classifier.predict(X)[0]
    
    def predict_proba(self, text):
        """预测概率"""
        X = self.vectorizer.transform([text])
        return self.classifier.predict_proba(X)[0]

# 使用示例
nb_classifier = NaiveBayesClassifier()

# 训练数据
train_texts = [
    "股市今日大涨,投资者信心增强",
    "新的药物试验取得突破性进展",
    "足球比赛精彩纷呈,观众热情高涨",
    "科技公司发布最新AI产品",
    "医院引进先进医疗设备",
    "篮球明星签约新球队"
]

train_labels = ["财经", "医疗", "体育", "科技", "医疗", "体育"]

# 训练模型
nb_classifier.train(train_texts, train_labels)

# 测试
test_text = "研究人员开发了新的治疗方法"
result = nb_classifier.predict(test_text)
probabilities = nb_classifier.predict_proba(test_text)

print(f"文本:{test_text}")
print(f"预测类别:{result}")
print(f"各类别概率:{probabilities}")

2. 支持向量机:寻找最优边界

SVM就像一个"边界专家",它能找到最好的分类边界:

from sklearn.svm import SVC
from sklearn.feature_extraction.text import TfidfVectorizer

class SVMClassifier:
    def __init__(self):
        self.vectorizer = TfidfVectorizer(max_features=5000)
        self.classifier = SVC(kernel='linear', probability=True)
    
    def train(self, texts, labels):
        X = self.vectorizer.fit_transform(texts)
        self.classifier.fit(X, labels)
    
    def predict(self, text):
        X = self.vectorizer.transform([text])
        return self.classifier.predict(X)[0]
    
    def get_confidence(self, text):
        X = self.vectorizer.transform([text])
        return self.classifier.predict_proba(X)[0].max()

# 使用示例
svm_classifier = SVMClassifier()
svm_classifier.train(train_texts, train_labels)

test_text = "新的投资策略带来丰厚回报"
result = svm_classifier.predict(test_text)
confidence = svm_classifier.get_confidence(test_text)

print(f"SVM预测:{result},置信度:{confidence:.2f}")

3. 随机森林:集体智慧的力量

随机森林就像一个"专家委员会",多个决策树投票决定:

from sklearn.ensemble import RandomForestClassifier

class RandomForestTextClassifier:
    def __init__(self):
        self.vectorizer = TfidfVectorizer(max_features=3000)
        self.classifier = RandomForestClassifier(n_estimators=100, random_state=42)
    
    def train(self, texts, labels):
        X = self.vectorizer.fit_transform(texts)
        self.classifier.fit(X, labels)
    
    def predict(self, text):
        X = self.vectorizer.transform([text])
        return self.classifier.predict(X)[0]
    
    def get_feature_importance(self):
        """获取特征重要性"""
        feature_names = self.vectorizer.get_feature_names_out()
        importance = self.classifier.feature_importances_
        
        # 获取最重要的10个特征
        top_indices = np.argsort(importance)[-10:]
        return [(feature_names[i], importance[i]) for i in top_indices]

# 使用示例
rf_classifier = RandomForestTextClassifier()
rf_classifier.train(train_texts, train_labels)

# 查看重要特征
important_features = rf_classifier.get_feature_importance()
print("最重要的特征词:")
for feature, importance in important_features:
    print(f"  {feature}: {importance:.4f}")

📊 数据准备:给AI准备"教材"

数据收集策略

就像老师需要准备教材一样,训练分类器需要大量标记好的数据:

import pandas as pd
import numpy as np
from collections import Counter
import matplotlib.pyplot as plt

# 数据收集和管理类
class DataManager:
    def __init__(self):
        self.data = []
        self.labels = []
        self.label_counts = {}
    
    def add_sample(self, text, label):
        """添加训练样本"""
        self.data.append(text)
        self.labels.append(label)
        self.label_counts[label] = self.label_counts.get(label, 0) + 1
    
    def load_from_csv(self, file_path):
        """从CSV文件加载数据"""
        df = pd.read_csv(file_path)
        self.data = df['text'].tolist()
        self.labels = df['label'].tolist()
        self.label_counts = Counter(self.labels)
    
    def get_data_info(self):
        """获取数据统计信息"""
        total_samples = len(self.data)
        unique_labels = len(set(self.labels))
        
        print(f"📊 数据集统计信息:")
        print(f"  总样本数:{total_samples}")
        print(f"  类别数:{unique_labels}")
        print(f"  平均文本长度:{np.mean([len(text) for text in self.data]):.1f}字符")
        
        print(f"\n📋 类别分布:")
        for label, count in self.label_counts.items():
            percentage = count / total_samples * 100
            print(f"  {label}: {count} ({percentage:.1f}%)")
    
    def check_data_balance(self):
        """检查数据平衡性"""
        counts = list(self.label_counts.values())
        max_count = max(counts)
        min_count = min(counts)
        
        imbalance_ratio = max_count / min_count
        
        if imbalance_ratio > 3:
            print(f"⚠️  数据不平衡!最大类别样本数是最小类别的{imbalance_ratio:.1f}倍")
            print("建议:考虑使用数据增强或重采样技术")
        else:
            print("✅ 数据相对平衡")
    
    def visualize_distribution(self):
        """可视化类别分布"""
        plt.figure(figsize=(10, 6))
        labels = list(self.label_counts.keys())
        counts = list(self.label_counts.values())
        
        plt.bar(labels, counts, color='skyblue')
        plt.title('类别分布')
        plt.xlabel('类别')
        plt.ylabel('样本数量')
        plt.xticks(rotation=45)
        plt.tight_layout()
        plt.show()

# 使用示例
data_manager = DataManager()

# 模拟添加数据
sample_data = [
    ("苹果公司发布新iPhone,股价上涨5%", "科技"),
    ("央行降准释放流动性,刺激经济增长", "财经"),
    ("世界杯足球赛今晚开幕,全球瞩目", "体育"),
    ("新冠疫苗研发取得重大突破", "医疗"),
    ("著名导演新片获得金棕榈奖", "娱乐"),
    ("人工智能技术在医疗领域应用广泛", "科技"),
    ("股指期货大幅波动,投资者需谨慎", "财经"),
    ("奥运会游泳比赛刷新多项纪录", "体育")
]

for text, label in sample_data:
    data_manager.add_sample(text, label)

data_manager.get_data_info()
data_manager.check_data_balance()

数据预处理管道

import re
import jieba
from sklearn.model_selection import train_test_split

class TextPreprocessor:
    def __init__(self):
        self.stop_words = set([
            '的', '了', '在', '是', '我', '你', '他', '她', '它', '我们', '你们', '他们',
            '这', '那', '这个', '那个', '这些', '那些', '和', '或', '但', '因为', '所以',
            '如果', '虽然', '然而', '但是', '而且', '因此', '于是', '之后', '之前'
        ])
    
    def clean_text(self, text):
        """清洗文本"""
        # 移除特殊字符,保留中文、英文和数字
        text = re.sub(r'[^\u4e00-\u9fa5a-zA-Z0-9\s]', '', text)
        # 移除多余空格
        text = re.sub(r'\s+', ' ', text).strip()
        return text
    
    def tokenize(self, text):
        """分词"""
        # 使用jieba分词
        tokens = jieba.lcut(text)
        # 移除停用词和单字符词
        tokens = [token for token in tokens if token not in self.stop_words and len(token) > 1]
        return tokens
    
    def preprocess(self, text):
        """完整预处理流程"""
        # 清洗文本
        text = self.clean_text(text)
        # 分词
        tokens = self.tokenize(text)
        # 返回分词后的字符串
        return ' '.join(tokens)
    
    def preprocess_dataset(self, texts):
        """批量预处理"""
        return [self.preprocess(text) for text in texts]

# 使用示例
preprocessor = TextPreprocessor()

# 预处理数据
processed_texts = preprocessor.preprocess_dataset(data_manager.data)

# 分割训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
    processed_texts, 
    data_manager.labels, 
    test_size=0.2, 
    random_state=42,
    stratify=data_manager.labels  # 保持类别分布
)

print(f"训练集大小:{len(X_train)}")
print(f"测试集大小:{len(X_test)}")
print(f"预处理后的文本示例:{processed_texts[0]}")

数据增强技术

import random

class DataAugmentation:
    def __init__(self):
        self.synonyms = {
            "公司": ["企业", "集团", "公司", "机构"],
            "发布": ["推出", "公布", "发表", "宣布"],
            "技术": ["科技", "技术", "工艺", "方法"],
            "增长": ["上涨", "提升", "增加", "改善"],
            "研发": ["开发", "研究", "创新", "设计"]
        }
    
    def synonym_replacement(self, text, n=1):
        """同义词替换"""
        words = text.split()
        new_words = words.copy()
        
        for _ in range(n):
            # 随机选择一个词进行替换
            if words:
                idx = random.randint(0, len(words) - 1)
                word = words[idx]
                if word in self.synonyms:
                    synonym = random.choice(self.synonyms[word])
                    new_words[idx] = synonym
        
        return ' '.join(new_words)
    
    def random_insertion(self, text, n=1):
        """随机插入"""
        words = text.split()
        
        for _ in range(n):
            # 随机选择一个同义词插入
            if words:
                synonym_word = random.choice(list(self.synonyms.keys()))
                synonym = random.choice(self.synonyms[synonym_word])
                idx = random.randint(0, len(words))
                words.insert(idx, synonym)
        
        return ' '.join(words)
    
    def random_deletion(self, text, p=0.1):
        """随机删除"""
        words = text.split()
        if len(words) <= 1:
            return text
        
        new_words = []
        for word in words:
            if random.random() > p:
                new_words.append(word)
        
        return ' '.join(new_words) if new_words else text
    
    def augment_data(self, texts, labels, augment_ratio=0.5):
        """数据增强"""
        augmented_texts = []
        augmented_labels = []
        
        for text, label in zip(texts, labels):
            # 原始数据
            augmented_texts.append(text)
            augmented_labels.append(label)
            
            # 生成增强数据
            if random.random() < augment_ratio:
                # 随机选择一种增强方法
                methods = [
                    self.synonym_replacement,
                    self.random_insertion,
                    self.random_deletion
                ]
                method = random.choice(methods)
                aug_text = method(text)
                
                augmented_texts.append(aug_text)
                augmented_labels.append(label)
        
        return augmented_texts, augmented_labels

# 使用示例
augmenter = DataAugmentation()
aug_texts, aug_labels = augmenter.augment_data(X_train, y_train)

print(f"原始训练集大小:{len(X_train)}")
print(f"增强后训练集大小:{len(aug_texts)}")
print(f"增强示例:")
print(f"  原文:{X_train[0]}")
print(f"  增强:{augmenter.synonym_replacement(X_train[0])}")

🔧 特征工程:教AI看懂文字

1. 词袋模型(Bag of Words)

词袋模型就像把文章撕成单词片段,然后数每个词出现了多少次:

from sklearn.feature_extraction.text import CountVectorizer
import pandas as pd

class BagOfWordsFeatureExtractor:
    def __init__(self, max_features=5000, ngram_range=(1, 1)):
        self.vectorizer = CountVectorizer(
            max_features=max_features,
            ngram_range=ngram_range,
            token_pattern=r'\b\w+\b'
        )
    
    def fit_transform(self, texts):
        """训练并转换文本"""
        return self.vectorizer.fit_transform(texts)
    
    def transform(self, texts):
        """转换文本"""
        return self.vectorizer.transform(texts)
    
    def get_feature_names(self):
        """获取特征名称"""
        return self.vectorizer.get_feature_names_out()
    
    def analyze_features(self, texts, labels):
        """分析特征分布"""
        X = self.fit_transform(texts)
        feature_names = self.get_feature_names()
        
        # 计算每个类别的词频
        df = pd.DataFrame(X.toarray(), columns=feature_names)
        df['label'] = labels
        
        # 按类别分组统计
        for label in set(labels):
            label_data = df[df['label'] == label]
            word_freq = label_data.drop('label', axis=1).sum().sort_values(ascending=False)
            
            print(f"\n{label}类别的高频词:")
            print(word_freq.head(10))

# 使用示例
bow_extractor = BagOfWordsFeatureExtractor()
X_bow = bow_extractor.fit_transform(X_train)

print(f"词袋模型特征维度:{X_bow.shape}")
print(f"特征示例:{bow_extractor.get_feature_names()[:20]}")

# 分析特征
bow_extractor.analyze_features(X_train, y_train)

2. TF-IDF特征

TF-IDF就像是给每个词打分,常见词得分低,稀有但重要的词得分高:

from sklearn.feature_extraction.text import TfidfVectorizer

class TfidfFeatureExtractor:
    def __init__(self, max_features=5000, ngram_range=(1, 2)):
        self.vectorizer = TfidfVectorizer(
            max_features=max_features,
            ngram_range=ngram_range,
            token_pattern=r'\b\w+\b',
            sublinear_tf=True,  # 使用对数缩放
            norm='l2'  # L2归一化
        )
    
    def fit_transform(self, texts):
        return self.vectorizer.fit_transform(texts)
    
    def transform(self, texts):
        return self.vectorizer.transform(texts)
    
    def get_top_features_by_class(self, texts, labels, top_n=10):
        """获取每个类别的顶级特征"""
        X = self.fit_transform(texts)
        feature_names = self.vectorizer.get_feature_names_out()
        
        # 计算每个类别的平均TF-IDF分数
        results = {}
        for label in set(labels):
            # 获取该类别的所有文档
            label_indices = [i for i, l in enumerate(labels) if l == label]
            label_tfidf = X[label_indices].mean(axis=0).A1  # 平均TF-IDF
            
            # 获取顶级特征
            top_indices = label_tfidf.argsort()[-top_n:][::-1]
            top_features = [(feature_names[i], label_tfidf[i]) for i in top_indices]
            
            results[label] = top_features
        
        return results

# 使用示例
tfidf_extractor = TfidfFeatureExtractor()
X_tfidf = tfidf_extractor.fit_transform(X_train)

print(f"TF-IDF特征维度:{X_tfidf.shape}")

# 分析每个类别的顶级特征
top_features = tfidf_extractor.get_top_features_by_class(X_train, y_train)
for label, features in top_features.items():
    print(f"\n{label}类别的顶级特征:")
    for feature, score in features:
        print(f"  {feature}: {score:.4f}")

3. N-gram特征

N-gram考虑词的顺序信息,比如"人工智能"比单独的"人工"和"智能"更有意义:

class NgramFeatureExtractor:
    def __init__(self, n=2):
        self.n = n
        self.vectorizer = CountVectorizer(
            ngram_range=(1, n),
            max_features=10000,
            token_pattern=r'\b\w+\b'
        )
    
    def fit_transform(self, texts):
        return self.vectorizer.fit_transform(texts)
    
    def analyze_ngrams(self, texts, labels):
        """分析n-gram特征"""
        X = self.fit_transform(texts)
        feature_names = self.vectorizer.get_feature_names_out()
        
        # 分析不同长度的n-gram
        for n in range(1, self.n + 1):
            ngram_features = [f for f in feature_names if len(f.split()) == n]
            print(f"\n{n}-gram特征数量:{len(ngram_features)}")
            if ngram_features:
                print(f"示例:{ngram_features[:10]}")

# 使用示例
ngram_extractor = NgramFeatureExtractor(n=3)
X_ngram = ngram_extractor.fit_transform(X_train)

print(f"N-gram特征维度:{X_ngram.shape}")
ngram_extractor.analyze_ngrams(X_train, y_train)

4. 自定义特征工程

import re
from collections import Counter

class CustomFeatureExtractor:
    def __init__(self):
        self.feature_functions = [
            self.get_length_features,
            self.get_punctuation_features,
            self.get_keyword_features,
            self.get_pattern_features
        ]
    
    def get_length_features(self, text):
        """长度特征"""
        return {
            'char_count': len(text),
            'word_count': len(text.split()),
            'sentence_count': len(text.split('。')),
            'avg_word_length': np.mean([len(word) for word in text.split()]) if text.split() else 0
        }
    
    def get_punctuation_features(self, text):
        """标点符号特征"""
        return {
            'exclamation_count': text.count('!'),
            'question_count': text.count('?'),
            'comma_count': text.count(','),
            'period_count': text.count('。')
        }
    
    def get_keyword_features(self, text):
        """关键词特征"""
        keywords = {
            'financial': ['股市', '投资', '金融', '经济', '银行', '贷款'],
            'technology': ['技术', '科技', '人工智能', '算法', '软件'],
            'sports': ['比赛', '运动', '球员', '教练', '冠军'],
            'medical': ['医疗', '药物', '治疗', '医生', '病人', '疾病']
        }
        
        features = {}
        for category, words in keywords.items():
            count = sum(1 for word in words if word in text)
            features[f'{category}_keywords'] = count
        
        return features
    
    def get_pattern_features(self, text):
        """模式特征"""
        return {
            'has_numbers': int(bool(re.search(r'\d', text))),
            'has_english': int(bool(re.search(r'[a-zA-Z]', text))),
            'has_percentage': int(bool(re.search(r'\d+%', text))),
            'has_date': int(bool(re.search(r'\d{4}年|\d{1,2}月|\d{1,2}日', text)))
        }
    
    def extract_features(self, texts):
        """提取所有自定义特征"""
        all_features = []
        
        for text in texts:
            features = {}
            for func in self.feature_functions:
                features.update(func(text))
            all_features.append(features)
        
        return pd.DataFrame(all_features)

# 使用示例
custom_extractor = CustomFeatureExtractor()
custom_features = custom_extractor.extract_features(X_train)

print("自定义特征:")
print(custom_features.head())
print(f"\n特征统计:")
print(custom_features.describe())

🎯 模型训练:让AI学会分类

模型选择与训练

from sklearn.ensemble import RandomForestClassifier, VotingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import classification_report, confusion_matrix
import seaborn as sns

class TextClassificationPipeline:
    def __init__(self):
        self.models = {
            'naive_bayes': MultinomialNB(),
            'logistic_regression': LogisticRegression(random_state=42),
            'svm': SVC(random_state=42, probability=True),
            'random_forest': RandomForestClassifier(random_state=42),
        }
        self.feature_extractor = TfidfVectorizer(max_features=5000, ngram_range=(1, 2))
        self.trained_models = {}
    
    def train_single_model(self, X_train, y_train, model_name):
        """训练单个模型"""
        print(f"正在训练{model_name}...")
        
        # 提取特征
        X_train_features = self.feature_extractor.fit_transform(X_train)
        
        # 训练模型
        model = self.models[model_name]
        model.fit(X_train_features, y_train)
        
        # 保存训练好的模型
        self.trained_models[model_name] = model
        
        print(f"{model_name}训练完成!")
        return model
    
    def train_all_models(self, X_train, y_train):
        """训练所有模型"""
        # 提取特征
        X_train_features = self.feature_extractor.fit_transform(X_train)
        
        for name, model in self.models.items():
            print(f"正在训练{name}...")
            model.fit(X_train_features, y_train)
            self.trained_models[name] = model
    
    def evaluate_model(self, X_test, y_test, model_name):
        """评估单个模型"""
        if model_name not in self.trained_models:
            raise ValueError(f"模型{model_name}尚未训练")
        
        # 提取测试特征
        X_test_features = self.feature_extractor.transform(X_test)
        
        # 预测
        model = self.trained_models[model_name]
        y_pred = model.predict(X_test_features)
        
        # 评估
        print(f"\n{model_name}评估结果:")
        print(classification_report(y_test, y_pred))
        
        return y_pred
    
    def create_ensemble_model(self, X_train, y_train):
        """创建集成模型"""
        # 提取特征
        X_train_features = self.feature_extractor.fit_transform(X_train)
        
        # 创建投票分类器
        ensemble_model = VotingClassifier(
            estimators=[
                ('nb', MultinomialNB()),
                ('lr', LogisticRegression(random_state=42)),
                ('svm', SVC(random_state=42, probability=True))
            ],
            voting='soft'  # 软投票
        )
        
        # 训练集成模型
        ensemble_model.fit(X_train_features, y_train)
        self.trained_models['ensemble'] = ensemble_model
        
        return ensemble_model
    
    def predict(self, text, model_name='ensemble'):
        """预测文本类别"""
        if model_name not in self.trained_models:
            raise ValueError(f"模型{model_name}尚未训练")
        
        # 提取特征
        text_features = self.feature_extractor.transform([text])
        
        # 预测
        model = self.trained_models[model_name]
        prediction = model.predict(text_features)[0]
        
        # 获取概率(如果支持)
        if hasattr(model, 'predict_proba'):
            probabilities = model.predict_proba(text_features)[0]
            return prediction, probabilities
        else:
            return prediction, None

# 使用示例
pipeline = TextClassificationPipeline()

# 训练所有模型
pipeline.train_all_models(X_train, y_train)

# 创建集成模型
pipeline.create_ensemble_model(X_train, y_train)

# 评估所有模型
for model_name in pipeline.trained_models.keys():
    pipeline.evaluate_model(X_test, y_test, model_name)

# 测试预测
test_text = "科技公司发布了最新的人工智能产品"
prediction, probabilities = pipeline.predict(test_text, 'ensemble')
print(f"\n测试文本:{test_text}")
print(f"预测结果:{prediction}")
if probabilities is not None:
    print(f"预测概率:{probabilities}")

🎬 下集预告

恭喜你!🎉 你已经掌握了文本分类的完整流程,从数据预处理到模型部署,从传统机器学习到深度学习,从单模型到集成学习。你现在可以:

  • 构建自己的文本分类系统
  • 处理各种文本分类任务
  • 优化模型性能
  • 部署分类服务

在下一课《聊天机器人:打造你的AI助手》中,我们将进入更有趣的NLP应用领域!我们将探索:

🤖 对话系统基础:理解人机对话的本质
🤖 意图识别:让AI理解用户真正想要什么
🤖 槽位填充:提取对话中的关键信息
🤖 上下文理解:让AI记住对话历史
🤖 多轮对话管理:处理复杂的对话流程
🤖 个性化回复:打造有温度的AI助手
🤖 实战项目:从零开始构建智能客服

想象一下,你将学会创建一个能够:

  • 理解用户的各种提问方式
  • 记住之前的对话内容
  • 提供个性化的回答
  • 处理复杂的业务查询
  • 像真人一样自然对话

的智能聊天机器人!这将是你AI助手开发之旅的精彩开始!

📝 课后作业

基础练习

  1. 邮件分类器:构建一个能够识别工作邮件、个人邮件和垃圾邮件的分类器
  2. 商品评论分析:分析淘宝或京东的商品评论,自动分类为好评、中评、差评
  3. 新闻标题分类:收集不同类别的新闻标题,训练一个标题分类器

进阶练习

  1. 多标签文本分类:构建一个能够给文章打多个标签的系统(如:科技+商业+创新)
  2. 层次化文本分类:实现一个具有类别层次结构的分类系统(如:体育->足球->中超)
  3. 增量学习分类器:设计一个能够持续学习新类别的动态分类系统

挑战练习

  1. 实时社交媒体监控:构建一个实时监控微博/推特情感的系统
  2. 智能文档管理:开发一个能够自动整理和分类文档的智能系统
  3. 多语言文本分类:实现一个支持中英文混合文本分类的系统

项目实战

  1. 新闻推荐系统:结合文本分类和用户画像,构建个性化新闻推荐系统
  2. 智能客服分流:开发一个能够自动将用户问题分配给合适部门的系统
  3. 学术论文分类平台:构建一个帮助研究者快速找到相关论文的分类系统

🎉 总结

今天我们完成了文本分类的完整学习之旅:

核心概念:深入理解文本分类的原理和应用场景
数据准备:掌握数据收集、清洗、预处理和增强技术
特征工程:学会词袋模型、TF-IDF、N-gram等特征提取方法
经典算法:熟练使用朴素贝叶斯、SVM、随机森林等算法
深度学习:掌握CNN、BERT等先进的文本分类技术
模型评估:学会全面评估和优化模型性能
实战项目:构建完整的新闻分类系统
部署应用:将分类器部署为API服务
问题解决:处理数据不平衡、过拟合等常见问题

记住:文本分类是NLP的基础技能,就像学会了AI的"阅读理解"能力。无论是情感分析、垃圾邮件检测,还是内容推荐,都离不开文本分类的支持。

现在你已经具备了:

  • 🎯 理论基础:深入理解分类算法的原理
  • 🛠️ 实践技能:能够独立构建分类系统
  • 🚀 工程能力:可以部署和优化分类服务
  • 🔧 问题解决:处理各种实际应用中的挑战

继续加油,下一课我们将学习更有趣的聊天机器人技术,让AI真正成为你的智能助手!🚀


💡 AI开发小贴士:好的分类器不仅要准确,还要快速、稳定、可解释。在实际应用中,往往需要在性能和效率之间找到平衡点。记住:理解业务需求比追求最高准确率更重要!

🎯 学习建议:文本分类是一个非常实用的技能,建议你选择一个自己感兴趣的领域(如电影评论、新闻分类、商品评价等),从数据收集开始,完整地做一个项目。只有在实践中,你才能真正掌握这项技能!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐