中文NLP实战:从分词到文本分类的完整技术指南

自然语言处理(NLP)作为人工智能领域的重要分支,正在深刻改变我们与机器交互的方式。但很多开发者在实际应用中常常陷入困境:为什么理论上完美的算法在实际项目中表现不佳?为什么同样的模型在不同场景下效果差异巨大?本文将从代码理论和实战两个维度,深入剖析NLP模型的核心原理和实际应用,帮助开发者避开常见陷阱,构建真正可用的NLP系统。

1. 这篇文章真正要解决的问题

在实际NLP项目开发中,开发者经常面临几个核心痛点:首先是文本预处理环节的复杂性,中文分词的质量直接影响后续模型效果;其次是特征表示的选择困难,one-hot、TF-IDF、词嵌入各有优劣但适用场景不同;最后是语义理解的实际效果与理论预期的差距。

本文要解决的核心问题是:如何将NLP理论知识转化为可落地的代码实现,特别是在中文场景下的特殊处理。我们将通过完整的代码示例展示从文本预处理到语义分析的完整流程,重点解决实际开发中的三个关键问题:分词准确性、特征表示有效性和语义理解实用性。

通过本文,你将掌握构建生产级NLP系统所需的核心技术栈,包括jieba分词、TF-IDF向量化、主题模型和词嵌入应用,并了解如何根据具体业务场景选择合适的技术方案。

2. 基础概念与核心原理

2.1 自然语言处理的核心挑战

自然语言处理的核心挑战在于如何让计算机理解人类语言的复杂性和模糊性。与编程语言不同,自然语言充满歧义、上下文依赖和文化差异。例如,"苹果"既可以指水果也可以指公司,而"意思意思"在不同语境下有完全不同的含义。

2.2 文本表示的基本方法

文本表示是NLP的基础,主要分为三种类型:

词袋模型(Bag of Words):将文本视为单词的集合,忽略语法和词序

  • One-Hot编码:每个词用唯一的向量表示
  • TF-IDF:考虑词频和逆文档频率的加权表示

分布式表示(Distributed Representation)

  • 词嵌入(Word Embedding):将词映射到低维稠密向量空间
  • 上下文感知表示:如BERT等预训练模型

序列表示(Sequence Representation)

  • RNN/LSTM:考虑词序信息的序列建模
  • Transformer:自注意力机制的序列建模

2.3 语义分析的核心算法

语义分析旨在理解文本的深层含义,主要方法包括:

  • LSA(隐性语义分析):基于SVD矩阵分解的主题提取
  • LDA(线性判别分析):监督学习的主题分类
  • LDiA(隐性狄利克雷分布):无监督学习的主题建模

3. 环境准备与前置条件

3.1 Python环境配置

# 创建虚拟环境 python -m venv nlp_env source nlp_env/bin/activate # Linux/Mac nlp_env\Scripts\activate # Windows # 安装核心依赖包 pip install jieba scikit-learn pandas numpy tensorflow gensim zhconv

3.2 主要库版本要求

# 检查环境配置 import jieba import sklearn import tensorflow as tf import gensim print(f"jieba版本: {jieba.__version__}") print(f"scikit-learn版本: {sklearn.__version__}") print(f"tensorflow版本: {tf.__version__}") print(f"gensim版本: {gensim.__version__}") # 预期输出(版本可能更新,以实际为准): # jieba版本: 0.42.1 # scikit-learn版本: 1.2.0 # tensorflow版本: 2.12.0 # gensim版本: 4.3.0

3.3 数据准备

准备测试数据文件结构:

project/ ├── data/ │ ├── stopword.txt # 停用词表 │ ├── news_finance.txt # 金融类文本 │ └── news_entertainment.txt # 娱乐类文本 ├── src/ │ └── nlp_demo.py # 主程序 └── requirements.txt # 依赖列表

4. 中文分词实战:Jieba库深度应用

4.1 Jieba分词基础使用

import jieba import jieba.posseg as pseg def basic_cut_demo(): """基础分词功能演示""" text = "自然语言处理技术正在改变世界" # 精确模式(默认) words_precise = jieba.cut(text, cut_all=False) print("精确模式:", "/".join(words_precise)) # 全模式 words_full = jieba.cut(text, cut_all=True) print("全模式:", "/".join(words_full)) # 搜索引擎模式 words_search = jieba.cut_for_search(text) print("搜索引擎模式:", "/".join(words_search)) # 词性标注 words_pos = pseg.cut(text) for word, flag in words_pos: print(f"{word}({flag})", end=" ") print() if __name__ == "__main__": basic_cut_demo() # 运行结果: # 精确模式: 自然语言/处理/技术/正在/改变/世界 # 全模式: 自然/自然语言/语言/处理/技术/正在/改变/世界 # 搜索引擎模式: 自然/语言/自然语言/处理/技术/正在/改变/世界 # 自然语言(l)/处理(v)/技术(n)/正在(d)/改变(v)/世界(n)

4.2 自定义词典与词频调整

def custom_dictionary_demo(): """自定义词典使用演示""" text = "嫦娥四号着陆器地形地貌相机对玉兔二号巡视器成像" # 默认分词 default_cut = jieba.lcut(text) print("默认分词:", default_cut) # 添加专业术语到词典 jieba.add_word('嫦娥四号') jieba.add_word('玉兔二号') jieba.add_word('地形地貌相机') custom_cut = jieba.lcut(text) print("自定义分词:", custom_cut) # 调整词频 jieba.suggest_freq('着陆器', True) adjusted_cut = jieba.lcut(text) print("调整词频后:", adjusted_cut) # 从文件加载词典 jieba.load_userdict('data/custom_dict.txt') custom_dictionary_demo()

4.3 停用词过滤与文本清洗

import re def text_cleaning_demo(): """文本清洗和停用词过滤""" def load_stopwords(filepath): """加载停用词表""" with open(filepath, 'r', encoding='utf-8') as f: stopwords = [line.strip() for line in f.readlines()] return set(stopwords) def clean_text(text): """文本清洗函数""" # 去除标点符号 text = re.sub(r'[^\w\s]', '', text) # 去除数字 text = re.sub(r'\d+', '', text) # 去除多余空格 text = re.sub(r'\s+', ' ', text).strip() return text # 示例文本 text = "这是一段包含标点,数字123和停用词的测试文本!的、了、呢等词需要过滤。" # 文本清洗 cleaned_text = clean_text(text) print("清洗后文本:", cleaned_text) # 分词 words = jieba.lcut(cleaned_text) print("分词结果:", words) # 加载停用词 stopwords = load_stopwords('data/stopword.txt') # 过滤停用词 filtered_words = [word for word in words if word not in stopwords and len(word) > 1] print("过滤后结果:", filtered_words) text_cleaning_demo()

5. 词向量表示:从One-Hot到TF-IDF

5.1 One-Hot编码实现

import numpy as np from collections import Counter def one_hot_encoding_demo(): """One-Hot编码实现""" def build_vocabulary(texts): """构建词汇表""" words = [] for text in texts: words.extend(jieba.lcut(text)) word_counts = Counter(words) # 过滤单字和停用词 vocabulary = {word: idx for idx, (word, count) in enumerate(word_counts.items()) if len(word) > 1 and count > 1} return vocabulary def text_to_onehot(text, vocabulary): """文本转换为One-Hot向量""" words = jieba.lcut(text) vector = np.zeros(len(vocabulary)) for word in words: if word in vocabulary: vector[vocabulary[word]] = 1 return vector # 示例文本 texts = [ "自然语言处理很重要", "深度学习改变自然语言处理", "自然语言处理应用广泛" ] # 构建词汇表 vocab = build_vocabulary(texts) print("词汇表:", vocab) # 转换为One-Hot向量 for i, text in enumerate(texts): vector = text_to_onehot(text, vocab) print(f"文本{i+1}的One-Hot向量: {vector}") one_hot_encoding_demo()

5.2 TF-IDF向量化实战

from sklearn.feature_extraction.text import TfidfVectorizer import pandas as pd def tfidf_vectorization_demo(): """TF-IDF向量化实战""" # 中文文本数据 corpus = [ "自然语言处理是人工智能的重要分支", "深度学习在自然语言处理中应用广泛", "自然语言处理技术包括文本分类和情感分析", "机器学习算法用于自然语言处理任务" ] # 中文分词处理 def chinese_tokenizer(text): return jieba.lcut(text) # 创建TF-IDF向量化器 vectorizer = TfidfVectorizer( tokenizer=chinese_tokenizer, stop_words=['是', '的', '在', '中', '和', '用于', '包括'], max_features=1000, ngram_range=(1, 2) # 包含1-gram和2-gram ) # 拟合和转换 tfidf_matrix = vectorizer.fit_transform(corpus) # 查看特征词汇 feature_names = vectorizer.get_feature_names_out() print("特征词汇:", feature_names[:20]) # 显示前20个特征 # 转换为DataFrame便于查看 df_tfidf = pd.DataFrame( tfidf_matrix.toarray(), columns=feature_names, index=[f"文档{i+1}" for i in range(len(corpus))] ) print("\nTF-IDF矩阵:") print(df_tfidf.iloc[:, :10]) # 显示前10列 # 查看每个文档的关键词 print("\n各文档关键词:") for i, doc in enumerate(corpus): feature_index = tfidf_matrix[i, :].nonzero()[1] tfidf_scores = zip(feature_index, [tfidf_matrix[i, x] for x in feature_index]) sorted_scores = sorted(tfidf_scores, key=lambda x: x[1], reverse=True) print(f"文档{i+1}: ", end="") for feature_idx, score in sorted_scores[:3]: # 显示前3个关键词 print(f"{feature_names[feature_idx]}({score:.3f})", end=" ") print() tfidf_vectorization_demo()

5.3 手动实现TF-IDF计算

def manual_tfidf_demo(): """手动实现TF-IDF计算,理解原理""" def calculate_tf(documents): """计算词频TF""" tf_dict = {} for doc_id, doc in enumerate(documents): words = jieba.lcut(doc) word_count = len(words) tf_dict[doc_id] = {} for word in words: if len(word) > 1: # 过滤单字 tf_dict[doc_id][word] = tf_dict[doc_id].get(word, 0) + 1 # 归一化 for word in tf_dict[doc_id]: tf_dict[doc_id][word] /= word_count return tf_dict def calculate_idf(documents): """计算逆文档频率IDF""" import math doc_count = len(documents) word_doc_count = {} for doc in documents: words = set(jieba.lcut(doc)) for word in words: if len(word) > 1: word_doc_count[word] = word_doc_count.get(word, 0) + 1 idf_dict = {} for word, count in word_doc_count.items(): idf_dict[word] = math.log(doc_count / (count + 1)) # 平滑处理 return idf_dict def calculate_tfidf(tf_dict, idf_dict): """计算TF-IDF""" tfidf_dict = {} for doc_id, word_tf in tf_dict.items(): tfidf_dict[doc_id] = {} for word, tf_value in word_tf.items(): idf_value = idf_dict.get(word, 0) tfidf_dict[doc_id][word] = tf_value * idf_value return tfidf_dict # 示例文档 documents = [ "自然语言处理是人工智能的重要分支", "深度学习在自然语言处理中应用广泛", "文本分类是自然语言处理的常见任务" ] # 计算TF、IDF、TF-IDF tf_result = calculate_tf(documents) idf_result = calculate_idf(documents) tfidf_result = calculate_tfidf(tf_result, idf_result) print("TF计算结果:") for doc_id, word_tf in tf_result.items(): print(f"文档{doc_id+1}: {dict(list(word_tf.items())[:3])}") # 显示前3个词 print("\nIDF计算结果:") print(dict(list(idf_result.items())[:5])) # 显示前5个词 print("\nTF-IDF计算结果:") for doc_id, word_tfidf in tfidf_result.items(): sorted_words = sorted(word_tfidf.items(), key=lambda x: x[1], reverse=True) print(f"文档{doc_id+1}的关键词: {[word for word, score in sorted_words[:3]]}") manual_tfidf_demo()

6. 文本相似度计算与实战应用

6.1 余弦相似度原理与实现

from sklearn.metrics.pairwise import cosine_similarity from sklearn.feature_extraction.text import TfidfVectorizer def cosine_similarity_demo(): """余弦相似度计算实战""" # 文档集合 documents = [ "机器学习是人工智能的重要分支", "深度学习是机器学习的一个子领域", "自然语言处理使用机器学习技术", "计算机视觉处理图像和视频数据", "强化学习用于决策制定过程" ] # 查询文本 query = "机器学习在人工智能中的应用" # TF-IDF向量化 vectorizer = TfidfVectorizer(tokenizer=jieba.lcut, stop_words=['是', '的', '在', '和']) doc_vectors = vectorizer.fit_transform(documents) query_vector = vectorizer.transform([query]) # 计算余弦相似度 similarities = cosine_similarity(query_vector, doc_vectors) print("查询文本:", query) print("\n相似度结果:") for i, sim in enumerate(similarities[0]): print(f"文档{i+1}: {sim:.4f} - {documents[i]}") # 找到最相似的文档 most_similar_idx = similarities.argmax() print(f"\n最相似文档: 文档{most_similar_idx+1}") print(f"相似度: {similarities[0, most_similar_idx]:.4f}") cosine_similarity_demo()

6.2 智能对话系统实战

def smart_dialog_system(): """基于文本相似度的智能对话系统""" # 对话知识库 qa_pairs = [ {"question": "怎么打开车窗", "answer": "正在为您打开车窗"}, {"question": "播放周杰伦的歌", "answer": "为您播放周杰伦的七里香"}, {"question": "今天天气怎么样", "answer": "今天晴天,气温25度"}, {"question": "导航到火车站", "answer": "已开启导航,目的地火车站"}, {"question": "我有点热", "answer": "已为您调低空调温度"} ] # 准备问题列表用于训练 questions = [pair["question"] for pair in qa_pairs] def preprocess_texts(texts): """文本预处理""" processed = [] for text in texts: # 分词并用空格连接,适应sklearn的默认tokenizer words = jieba.lcut(text) processed.append(' '.join(words)) return processed # 训练TF-IDF模型 processed_questions = preprocess_texts(questions) vectorizer = TfidfVectorizer() question_vectors = vectorizer.fit_transform(processed_questions) def get_response(user_input): """获取回复""" # 预处理用户输入 processed_input = preprocess_texts([user_input])[0] input_vector = vectorizer.transform([processed_input]) # 计算相似度 similarities = cosine_similarity(input_vector, question_vectors) best_match_idx = similarities.argmax() best_similarity = similarities[0, best_match_idx] # 设置相似度阈值 if best_similarity > 0.3: return qa_pairs[best_match_idx]["answer"] else: return "抱歉,我没有理解您的意思" # 测试对话系统 test_queries = [ "打开车窗", "我想听周杰伦", "天气情况", "去火车站", "太热了" ] print("智能对话系统测试:") for query in test_queries: response = get_response(query) print(f"用户: {query}") print(f"系统: {response}\n") smart_dialog_system()

7. 主题模型与语义分析

7.1 LSA隐性语义分析实战

from sklearn.decomposition import TruncatedSVD from sklearn.feature_extraction.text import TfidfVectorizer def lsa_analysis_demo(): """LSA隐性语义分析实战""" # 新闻文本数据 news_corpus = [ "股票市场今日大涨,投资者收益丰厚", "篮球比赛精彩纷呈,明星球员表现突出", "科技公司发布新产品,技术创新引领行业", "电影票房创新高,观众评价很好", "金融市场波动较大,投资需要谨慎", "足球联赛激烈进行,球队竞争白热化", "人工智能技术突破,应用前景广阔", "音乐会演出成功,艺术家表现精彩" ] # TF-IDF向量化 vectorizer = TfidfVectorizer(tokenizer=jieba.lcut, max_features=100) tfidf_matrix = vectorizer.fit_transform(news_corpus) # LSA主题分析 n_topics = 3 lsa = TruncatedSVD(n_components=n_topics, random_state=42) lsa_matrix = lsa.fit_transform(tfidf_matrix) # 查看主题分布 feature_names = vectorizer.get_feature_names_out() print("各主题的关键词:") for topic_idx, topic in enumerate(lsa.components_): print(f"主题{topic_idx + 1}:") # 获取该主题最重要的10个词 top_words_idx = topic.argsort()[-10:][::-1] top_words = [feature_names[i] for i in top_words_idx] print(", ".join(top_words)) print(f"主题强度: {lsa.explained_variance_ratio_[topic_idx]:.3f}\n") # 文档-主题分布 print("文档主题分布:") for i, doc_topics in enumerate(lsa_matrix): dominant_topic = doc_topics.argmax() print(f"文档{i+1}: 主要主题{dominant_topic+1}, 分布{doc_topics}") lsa_analysis_demo()

7.2 LDA主题分类实战

from sklearn.discriminant_analysis import LinearDiscriminantAnalysis from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score def lda_classification_demo(): """LDA主题分类实战""" # 准备数据 - 金融 vs 娱乐新闻分类 def load_text_data(): """加载文本数据""" finance_texts = [ "股票市场今日大涨指数突破新高", "银行利率调整影响经济发展", "投资理财需要谨慎选择产品", "经济增长数据显示向好趋势", "货币政策影响金融市场波动" ] entertainment_texts = [ "电影票房创新高观众评价很好", "明星演唱会门票销售火爆", "电视剧收视率突破历史记录", "音乐节活动吸引大量观众", "娱乐行业发展趋势良好" ] texts = finance_texts + entertainment_texts labels = [0] * len(finance_texts) + [1] * len(entertainment_texts) # 0:金融, 1:娱乐 return texts, labels texts, labels = load_text_data() # TF-IDF特征提取 vectorizer = TfidfVectorizer(tokenizer=jieba.lcut, max_features=50) X = vectorizer.fit_transform(texts) # 划分训练测试集 X_train, X_test, y_train, y_test = train_test_split( X, labels, test_size=0.3, random_state=42 ) # LDA分类 lda = LinearDiscriminantAnalysis() lda.fit(X_train.toarray(), y_train) # 预测和评估 y_pred = lda.predict(X_test.toarray()) accuracy = accuracy_score(y_test, y_pred) print("LDA分类结果:") print(f"准确率: {accuracy:.3f}") print(f"预测结果: {y_pred}") print(f"真实标签: {y_test}") # 查看特征重要性 feature_names = vectorizer.get_feature_names_out() print(f"\n特征数量: {len(feature_names)}") print("前10个特征:", feature_names[:10]) lda_classification_demo()

8. 词嵌入与深度学习应用

8.1 Word2Vec原理与实战

from gensim.models import Word2Vec from gensim.models.word2vec import LineSentence def word2vec_training_demo(): """Word2Vec模型训练实战""" # 准备训练数据 training_sentences = [ ["自然", "语言", "处理", "是", "人工智能", "重要", "分支"], ["深度", "学习", "在", "自然", "语言", "处理", "中", "应用", "广泛"], ["文本", "分类", "是", "自然", "语言", "处理", "常见", "任务"], ["机器", "学习", "算法", "用于", "自然", "语言", "处理", "任务"], ["情感", "分析", "可以", "识别", "文本", "中", "情感", "倾向"] ] # 训练Word2Vec模型 model = Word2Vec( sentences=training_sentences, vector_size=100, # 词向量维度 window=5, # 上下文窗口 min_count=1, # 最小词频 workers=4, # 并行线程数 epochs=100 # 训练轮数 ) # 查看词向量 print("'自然'的词向量维度:", model.wv['自然'].shape) print("'自然'的词向量前10维:", model.wv['自然'][:10]) # 相似词查找 similar_words = model.wv.most_similar('自然', topn=5) print("\n与'自然'最相似的词:") for word, similarity in similar_words: print(f"{word}: {similarity:.3f}") # 词向量运算 result = model.wv.most_similar(positive=['自然', '学习'], negative=['语言'], topn=3) print("\n向量运算结果(自然 + 学习 - 语言):") for word, similarity in result: print(f"{word}: {similarity:.3f}") # 保存模型 model.save("word2vec_model.bin") word2vec_training_demo()

8.2 使用预训练词向量

def pretrained_word2vec_demo(): """使用预训练词向量实战""" # 加载预训练模型(这里演示加载自己训练的模型) try: model = Word2Vec.load("word2vec_model.bin") # 词相似度计算 similarity = model.wv.similarity('自然', '语言') print(f"'自然'和'语言'的相似度: {similarity:.3f}") # 寻找不相关的词 odd_word = model.wv.doesnt_match(['自然', '语言', '处理', '计算机']) print(f"不相关的词: {odd_word}") # 获取词汇表信息 print(f"\n词汇表大小: {len(model.wv.key_to_index)}") print("前10个词汇:", list(model.wv.key_to_index.keys())[:10]) except FileNotFoundError: print("请先运行word2vec_training_demo()生成模型文件") pretrained_word2vec_demo()

9. 完整项目实战:新闻分类系统

9.1 系统架构设计

import os import numpy as np from sklearn.pipeline import Pipeline from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import cross_val_score import joblib class NewsClassifier: """新闻分类系统""" def __init__(self): self.pipeline = None self.classes = None def create_pipeline(self): """创建处理管道""" from sklearn.feature_extraction.text import TfidfVectorizer self.pipeline = Pipeline([ ('tfidf', TfidfVectorizer( tokenizer=jieba.lcut, max_features=1000, stop_words=['的', '是', '在', '了', '和', '有'] )), ('classifier', RandomForestClassifier( n_estimators=100, random_state=42 )) ]) def train(self, texts, labels): """训练模型""" if self.pipeline is None: self.create_pipeline() self.pipeline.fit(texts, labels) self.classes = self.pipeline.classes_ # 交叉验证评估 scores = cross_val_score(self.pipeline, texts, labels, cv=5) print(f"交叉验证准确率: {scores.mean():.3f} (+/- {scores.std() * 2:.3f})") def predict(self, texts): """预测分类""" if self.pipeline is None: raise ValueError("模型未训练") return self.pipeline.predict(texts) def predict_proba(self, texts): """预测概率""" if self.pipeline is None: raise ValueError("模型未训练") return self.pipeline.predict_proba(texts) def save_model(self, filepath): """保存模型""" joblib.dump(self.pipeline, filepath) def load_model(self, filepath): """加载模型""" self.pipeline = joblib.load(filepath) self.classes = self.pipeline.classes_ def news_classification_project(): """新闻分类完整项目""" # 模拟数据 - 实际项目中从文件或数据库读取 def generate_sample_data(): """生成样本数据""" finance_keywords = ['股票', '投资', '银行', '经济', '市场', '金融', '利率', '收益'] tech_keywords = ['科技', '创新', '数字', '智能', '网络', '数据', '系统', '技术'] sports_keywords = ['比赛', '运动员', '球队', '冠军', '体育', '训练', '赛事', '运动'] texts = [] labels = [] # 生成金融类新闻 for i in range(100): content = f"今日{finance_keywords[i%8]}市场表现{['良好','平稳','波动'][i%3]}" + \ f"{finance_keywords[(i+1)%8]}领域有所{['突破','发展','调整'][i%3]}" texts.append(content) labels.append(0) # 金融 # 生成科技类新闻 for i in range(100): content = f"{tech_keywords[i%8]}技术实现{['创新','突破','进步'][i%3]}" + \ f"{tech_keywords[(i+1)%8]}领域应用{['广泛','深入','扩展'][i%3]}" texts.append(content) labels.append(1) # 科技 # 生成体育类新闻 for i in range(100): content = f"{sports_keywords[i%8]}{['比赛','赛事','活动'][i%3]}结果{['精彩','激烈','圆满'][i%3]}" + \ f"{sports_keywords[(i+1)%8]}表现{['出色','优秀','良好'][i%3]}" texts.append(content) labels.append(2) # 体育 return texts, labels # 准备数据 texts, labels = generate_sample_data() # 创建分类器 classifier = NewsClassifier() # 训练模型 print("开始训练模型...") classifier.train(texts, labels) # 测试预测 test_texts = [ "股票市场今日大涨投资者收益丰厚", "人工智能技术取得重大突破", "篮球比赛精彩纷呈球员表现优秀" ] predictions = classifier.predict(test_texts) probabilities = classifier.predict_proba(test_texts) label_names = {0: '金融', 1: '科技', 2: '体育'} print("\n测试结果:") for i, text in enumerate(test_texts): pred_label = predictions[i] pred_prob = probabilities[i][pred_label] print(f"文本: {text}") print(f"预测类别: {label_names[pred_label]} (概率: {pred_prob:.3f})") print(f"各类别概率: {dict(zip([label_names[c] for c in classifier.classes_], probabilities[i]))}") print() # 保存模型 classifier.save_model("news_classifier.pkl") print("模型已保存为 news_classifier.pkl") news_classification_project()

9.2 模型优化与调参

def model_optimization_demo(): """模型优化与超参数调优""" from sklearn.model_selection import GridSearchCV from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.ensemble import RandomForestClassifier from sklearn.pipeline import Pipeline # 生成样本数据 def generate_data(): texts = [ "金融股票市场投资经济银行", "科技人工智能技术数据网络", "体育比赛运动员球队训练", "经济市场投资金融收益", "技术创新人工智能数据智能", "运动比赛体育赛事冠军" ] * 50 # 扩展数据量 labels = [0, 1, 2, 0, 1, 2] * 50 return texts, labels texts, labels = generate_data() # 创建管道 pipeline = Pipeline([ ('tfidf', TfidfVectorizer(tokenizer=jieba.lcut)), ('clf', RandomForestClassifier(random_state=42)) ]) # 参数网格 param_grid = { 'tfidf__max_features': [500, 1000, 2000], 'tfidf__ngram_range': [(1, 1), (1, 2)], 'clf__n_estimators': [50, 100, 200], 'clf__max_depth': [10, 20, None] } # 网格搜索 grid_search = GridSearchCV( pipeline, param_grid, cv=5, scoring='accuracy', n_jobs=-1 ) print("开始网格搜索...") grid_search.fit(texts, labels) print("最优参数:", grid_search.best_params_) print("最优分数:", grid_search.best_score_) # 使用最优参数训练最终模型 best_model = grid_search.best_estimator_ # 特征重要性分析 if hasattr(best_model.named_steps['clf'], 'feature_importances_'): feature_importances = best_model.named_steps['clf'].feature_importances_ feature_names = best_model.named_steps['tfidf'].get_feature_names_out() # 获取最重要的特征 important_features = sorted(zip(feature_names, feature_importances), key=lambda x: x[1], reverse=True)[:10] print("\n最重要的10个特征:") for feature, importance in important_features: print(f"{feature}: {importance:.4f}") model_optimization_demo()

10. 常见问题与解决方案

10.1 中文分词问题排查

def common_issues_solutions(): """常见问题与解决方案""" print("1. 中文分词不准确") print("问题: 专业术语被错误切分") print("解决方案: 使用自定义词典") text = "自然语言处理NLP技术很重要" print(f"原始分词: {jieba.lcut(text)}") # 添加专业术语 jieba.add_word('自然语言处理') jieba.add_word('NLP') print(f"优化后分词: {jieba.lcut(text)}") print("\n2. TF-IDF特征维度爆炸") print("问题: 特征数量过多导致内存不足") print("解决方案: 设置max_features参数") print("\n3. 文本相似度计算不准确") print("问题: 短文本相似度计算效果差") print("解决方案: 使用Word2Vec或BERT等深度学习方法")