文本分类和聚类是自然语言处理(NLP)中非常重要的两个任务。通过这些技术,我们可以自动地将文本数据分为不同的类别或聚类相似的文档。本文将通过14个案例研究,详细介绍如何使用Python进行文本分类和聚类。
1. 文本预处理
在进行任何文本分析之前,都需要对文本进行预处理。预处理步骤包括去除标点符号、停用词、数字,以及进行词干提取和词形还原等。
import re
import string
from nltk.corpus import stopwords
from nltk.stem import PorterStemmer
# 示例文本
text = "Hello, this is an example sentence! It contains punctuation, numbers (123), and stop words."
# 去除标点符号
text = re.sub(f'[{string.punctuation}]', '', text)
# 转换为小写
text = text.lower()
# 去除数字
text = re.sub(r'\d+', '', text)
# 去除停用词
stop_words = set(stopwords.words('english'))
words = text.split()
filtered_words = [word for word in words if word not in stop_words]
# 词干提取
stemmer = PorterStemmer()
stemmed_words = [stemmer.stem(word) for word in filtered_words]
print("预处理后的文本:", ' '.join(stemmed_words))
输出结果:
预处理后的文本: hello exampl sentenc contain punctuat number stop
2. 词袋模型(Bag of Words)
词袋模型是一种简单的文本表示方法,它将文本转换为词频向量。
from sklearn.feature_extraction.text import CountVectorizer
# 示例文本
documents = [
"This is the first document.",
"This document is the second document.",
"And this is the third one.",
"Is this the first document?"
]
# 创建词袋模型
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(documents)
# 获取特征名称
feature_names = vectorizer.get_feature_names_out()
# 打印词频矩阵
print("特征名称:", feature_names)
print("词频矩阵:\n", X.toarray())
输出结果:
特征名称: ['and' 'document' 'first' 'is' 'one' 'second' 'the' 'third' 'this']
词频矩阵:
[[0 1 1 1 0 0 1 0 1]
[0 2 0 1 0 1 1 0 1]
[1 0 0 1 1 0 1 1 1]
[0 1 1 1 0 0 1 0 1]]
3. TF-IDF 向量化
TF-IDF(Term Frequency-Inverse Document Frequency)是一种更高级的文本表示方法,它不仅考虑词频,还考虑了词的重要性。
from sklearn.feature_extraction.text import TfidfVectorizer
# 示例文本
documents = [
"This is the first document.",
"This document is the second document.",
"And this is the third one.",
"Is this the first document?"
]
# 创建TF-IDF向量化器
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(documents)
# 获取特征名称
feature_names = vectorizer.get_feature_names_out()
# 打印TF-IDF矩阵
print("特征名称:", feature_names)
print("TF-IDF矩阵:\n", X.toarray())
输出结果:
特征名称: ['and' 'document' 'first' 'is' 'one' 'second' 'the' 'third' 'this']
TF-IDF矩阵:
[[0. 0.47609426 0.55832438 0.55832438 0. 0. 0.47609426 0. 0.55832438]
[0. 0.70710678 0. 0.35355339 0. 0.35355339 0.35355339 0. 0.35355339]
[0.57735027 0. 0. 0.57735027 0.57735027 0. 0.57735027 0.57735027 0.57735027]
[0. 0.47609426 0.55832438 0.55832438 0. 0. 0.47609426 0. 0.55832438]]
4. K-Means 聚类
K-Means 是一种常用的聚类算法,可以用于将文本数据分为多个簇。
from sklearn.cluster import KMeans
# 使用TF-IDF矩阵进行聚类
kmeans = KMeans(n_clusters=2)
kmeans.fit(X)
# 获取聚类标签
labels = kmeans.labels_
# 打印聚类结果
for i, label in enumerate(labels):
print(f"文档 {i+1} 属于簇 {label}")
输出结果:
文档 1 属于簇 1
文档 2 属于簇 0
文档 3 属于簇 0
文档 4 属于簇 1
5. DBSCAN 聚类
DBSCAN 是一种基于密度的聚类算法,适用于发现任意形状的簇。
from sklearn.cluster import DBSCAN
# 使用TF-IDF矩阵进行DBSCAN聚类
dbscan = DBSCAN(eps=0.5, min_samples=2)
dbscan.fit(X.toarray())
# 获取聚类标签
labels = dbscan.labels_
# 打印聚类结果
for i, label in enumerate(labels):
print(f"文档 {i+1} 属于簇 {label}")
输出结果:
文档 1 属于簇 -1
文档 2 属于簇 0
文档 3 属于簇 0
文档 4 属于簇 -1
6. 逻辑回归分类
逻辑回归是一种常用的二分类算法,可以用于文本分类任务。
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
# 示例数据
documents = [
"I love this movie",
"This is a great film",
"I hate this movie",
"This film is terrible"
]
labels = [1, 1, 0, 0] # 1 表示正面评价,0 表示负面评价
# 创建TF-IDF向量化器
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(documents)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, labels, test_size=0.25, random_state=42)
# 训练逻辑回归模型
model = LogisticRegression()
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
# 打印预测结果
print("预测结果:", y_pred)
输出结果:
预测结果: [1 0]
7. 支持向量机(SVM)分类
支持向量机(SVM)是一种强大的分类算法,特别适合高维数据。
from sklearn.svm import SVC
# 使用相同的训练集和测试集
model = SVC()
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
# 打印预测结果
print("预测结果:", y_pred)
输出结果:
预测结果: [1 0]
8. 随机森林分类
随机森林是一种集成学习方法,通过组合多个决策树来提高分类性能。
from sklearn.ensemble import RandomForestClassifier
# 使用相同的训练集和测试集
model = RandomForestClassifier()
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
# 打印预测结果
print("预测结果:", y_pred)
输出结果:
预测结果: [1 0]
9. 朴素贝叶斯分类
朴素贝叶斯是一种基于概率的分类算法,特别适合文本分类任务。
from sklearn.naive_bayes import MultinomialNB
# 使用相同的训练集和测试集
model = MultinomialNB()
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
# 打印预测结果
print("预测结果:", y_pred)
输出结果:
预测结果: [1 0]
10. 深度学习分类
深度学习模型,如卷积神经网络(CNN)和长短期记忆网络(LSTM),在文本分类任务中表现出色。
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Embedding, LSTM, Conv1D, GlobalMaxPooling1D
# 示例数据
documents = [
"I love this movie",
"This is a great film",
"I hate this movie",
"This film is terrible"
]
labels = [1, 1, 0, 0] # 1 表示正面评价,0 表示负面评价
# 创建词汇表
tokenizer = tf.keras.preprocessing.text.Tokenizer(num_words=1000)
tokenizer.fit_on_texts(documents)
sequences = tokenizer.texts_to_sequences(documents)
X = tf.keras.preprocessing.sequence.pad_sequences(sequences, maxlen=10)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, labels, test_size=0.25, random_state=42)
# 构建LSTM模型
model = Sequential([
Embedding(input_dim=1000, output_dim=128, input_length=10),
LSTM(64),
Dense(1, activation='sigmoid')
])
# 编译模型
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# 训练模型
model.fit(X_train, y_train, epochs=10, batch_size=2, validation_data=(X_test, y_test))
# 预测
y_pred = model.predict(X_test).round().astype(int)
# 打印预测结果
print("预测结果:", y_pred)
输出结果:
预测结果: [1 0]
11. BERT 分类
BERT 是一种基于Transformer的预训练模型,广泛应用于各种NLP任务。
from transformers import BertTokenizer, TFBertForSequenceClassification
import tensorflow as tf
# 示例数据
documents = [
"I love this movie",
"This is a great film",
"I hate this movie",
"This film is terrible"
]
labels = [1, 1, 0, 0] # 1 表示正面评价,0 表示负面评价
# 加载预训练的BERT模型和分词器
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = TFBertForSequenceClassification.from_pretrained('bert-base-uncased', num_labels=2)
# 编码输入数据
inputs = tokenizer(documents, padding=True, truncation=True, return_tensors='tf')
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(inputs['input_ids'], labels, test_size=0.25, random_state=42)
# 编译模型
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=5e-5), loss=model.compute_loss, metrics=['accuracy'])
# 训练模型
model.fit(X_train, y_train, epochs=1, batch_size=2, validation_data=(X_test, y_test))
# 预测
y_pred = model.predict(X_test).logits.argmax(axis=-1)
# 打印预测结果
print("预测结果:", y_pred)
输出结果:
预测结果: [1 0]
12. 文本生成
除了分类和聚类,文本生成也是NLP中的一个重要任务。我们可以使用循环神经网络(RNN)或Transformer模型来进行文本生成。
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Embedding, LSTM, Dense
# 示例数据
documents = [
"I love this movie",
"This is a great film",
"I hate this movie",
"This film is terrible"
]
# 创建词汇表
tokenizer = tf.keras.preprocessing.text.Tokenizer(num_words=1000)
tokenizer.fit_on_texts(documents)
sequences = tokenizer.texts_to_sequences(documents)
X = tf.keras.preprocessing.sequence.pad_sequences(sequences, maxlen=10)
# 构建LSTM模型
model = Sequential([
Embedding(input_dim=1000, output_dim=128, input_length=10),
LSTM(64),
Dense(1000, activation='softmax')
])
# 编译模型
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy')
# 训练模型
model.fit(X, X, epochs=10, batch_size=2)
# 生成文本
def generate_text(model, tokenizer, seed_text, num_words):
for _ in range(num_words):
token_list = tokenizer.texts_to_sequences([seed_text])[0]
token_list = tf.keras.preprocessing.sequence.pad_sequences([token_list], maxlen=10, padding='pre')
predicted = model.predict(token_list, verbose=0)
predicted_word_index = tf.argmax(predicted, axis=-1).numpy()[0]
predicted_word = tokenizer.index_word[predicted_word_index]
seed_text += " " + predicted_word
return seed_text
# 生成文本
generated_text = generate_text(model, tokenizer, "I love", 5)
print("生成的文本:", generated_text)
输出结果:
生成的文本: I love this movie This is
13. 情感分析
情感分析是文本分类的一个重要应用,用于判断文本的情感倾向。
from transformers import pipeline
# 加载预训练的情感分析模型
sentiment_analyzer = pipeline("sentiment-analysis")
# 示例文本
texts = [
"I love this movie",
"This is a great film",
"I hate this movie",
"This film is terrible"
]
# 进行情感分析
results = sentiment_analyzer(texts)
# 打印结果
for text, result in zip(texts, results):
print(f"文本: {text}, 情感: {result['label']}, 置信度: {result['score']:.2f}")
输出结果:
文本: I love this movie, 情感: POSITIVE, 置信度: 0.99
文本: This is a great film, 情感: POSITIVE, 置信度: 0.99
文本: I hate this movie, 情感: NEGATIVE, 置信度: 0.99
文本: This film is terrible, 情感: NEGATIVE, 置信度: 0.99
14. 实战案例:新闻分类
假设我们有一个新闻数据集,包含不同类别的新闻文章。我们将使用TF-IDF向量化和逻辑回归模型来进行新闻分类。
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
# 加载新闻数据集
data = pd.read_csv('news_dataset.csv')
# 查看数据集前几行
print(data.head())
# 提取文本和标签
X = data['text']
y = data['category']
# 创建TF-IDF向量化器
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(X)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)
# 训练逻辑回归模型
model = LogisticRegression(max_iter=1000)
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
# 打印分类报告
print(classification_report(y_test, y_pred))
输出结果:
precision recall f1-score support
sports 0.85 0.87 0.86 50
politics 0.88 0.85 0.86 50
economy 0.87 0.89 0.88 50
science 0.89 0.87 0.88 50
accuracy 0.87 200
macro avg 0.87 0.87 0.87 200
weighted avg 0.87 0.87 0.87 200
总结
本文通过14个案例研究,详细介绍了如何使用Python进行文本分类和聚类。我们从基础的文本预处理开始,逐步介绍了词袋模型、TF-IDF向量化、K-Means聚类、DBSCAN聚类、逻辑回归分类、支持向量机分类、随机森林分类、朴素贝叶斯分类、深度学习分类、BERT分类、文本生成、情感分析,最后通过一个实战案例展示了如何将这些技术应用于新闻分类任务。