Python实现新闻文本聚类:基于Onehot、TF-IDF和BoW向量化方法
以下是Python实现:
- 数据预处理
首先,需要从文件夹中读取所有的新闻,并将它们进行分词。这里可以使用jieba库进行中文分词。
import os
import jieba
# 读取新闻文件夹中的所有新闻
news_folder = './news/'
news = []
for folder in os.listdir(news_folder):
folder_path = os.path.join(news_folder, folder)
if os.path.isdir(folder_path):
for file_name in os.listdir(folder_path):
file_path = os.path.join(folder_path, file_name)
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
news.append(content)
# 对每个新闻进行分词
news_tokens = []
for n in news:
tokens = jieba.lcut(n)
news_tokens.append(tokens)
这里使用了os库来遍历文件夹,jieba库进行分词。对于每个新闻,将其读取出来,然后分词并保存在一个列表中。
- 向量化
接下来,需要将每个新闻的内容向量化。这里可以使用onehot、TF-IDF和BoW等方法。
2.1 onehot
onehot方法是一种简单的向量化方法,它将每个词表示为一个独热向量,然后将每个句子表示为所有词的独热向量之和。
# 将每个词表示成独热向量
vocab = set()
for tokens in news_tokens:
for token in tokens:
vocab.add(token)
vocab = list(vocab)
vocab_size = len(vocab)
onehot_vectors = {}
for i, word in enumerate(vocab):
vector = [0] * vocab_size
vector[i] = 1
onehot_vectors[word] = vector
# 将每个新闻表示为所有词的独热向量之和
onehot_vectors_list = []
for tokens in news_tokens:
vector = [0] * vocab_size
for token in tokens:
if token in onehot_vectors:
vector = [x + y for x, y in zip(vector, onehot_vectors[token])]
onehot_vectors_list.append(vector)
这里先将所有的词表示成独热向量,然后将每个新闻表示为所有词的独热向量之和。最终得到的是一个向量列表,每个向量表示一篇新闻。
2.2 TF-IDF
TF-IDF方法则是将每个词表示成一个权重向量,其中权重由词频和文档频率计算得出。然后将每个句子表示为所有词的权重向量之和。
# 计算词频和文档频率
word_count = {}
doc_count = {}
for tokens in news_tokens:
doc_count_set = set()
for token in tokens:
word_count[token] = word_count.get(token, 0) + 1
if token not in doc_count_set:
doc_count[token] = doc_count.get(token, 0) + 1
doc_count_set.add(token)
# 计算TF-IDF权重
tfidf_vectors_list = []
for tokens in news_tokens:
vector = [0] * vocab_size
for token in tokens:
if token in vocab:
tf = tokens.count(token) / len(tokens)
idf = 1 + math.log(len(news_tokens) / doc_count[token])
tfidf = tf * idf
index = vocab.index(token)
vector[index] = tfidf
tfidf_vectors_list.append(vector)
这里先计算每个词的词频和文档频率,然后根据公式计算TF-IDF权重。最终得到的是一个向量列表,每个向量表示一篇新闻。
2.3 BoW
BoW方法则是将每个词表示成一个计数向量,然后将每个句子表示为所有词的计数向量之和。
# 将每个词表示成计数向量
bow_vectors = {}
for tokens in news_tokens:
for token in tokens:
bow_vectors[token] = bow_vectors.get(token, 0) + 1
# 将每个新闻表示为所有词的计数向量之和
bow_vectors_list = []
for tokens in news_tokens:
vector = [0] * vocab_size
for token in tokens:
if token in bow_vectors:
index = vocab.index(token)
vector[index] += 1
bow_vectors_list.append(vector)
这里先将所有的词表示成计数向量,然后将每个新闻表示为所有词的计数向量之和。最终得到的是一个向量列表,每个向量表示一篇新闻。
- 网页相似度与聚类
有了向量化后的数据,就可以计算网页相似度和进行聚类了。这里可以使用scikit-learn库来进行计算。
3.1 网页相似度
首先,可以使用余弦相似度来计算两个向量的相似度。
from sklearn.metrics.pairwise import cosine_similarity
# 计算余弦相似度
similarity_matrix = cosine_similarity(tfidf_vectors_list)
这里使用了cosine_similarity函数来计算余弦相似度矩阵。得到的similarity_matrix是一个矩阵,其中每个元素表示两篇新闻的相似度。
3.2 聚类
接下来,可以使用聚类算法将新闻进行聚类。这里可以使用KMeans算法来进行聚类。
from sklearn.cluster import KMeans
# 使用KMeans算法进行聚类
kmeans = KMeans(n_clusters=4, random_state=0).fit(tfidf_vectors_list)
labels = kmeans.labels_
这里使用了KMeans算法,将新闻分为4个簇。得到的labels是一个列表,其中每个元素表示一篇新闻所属的簇。
完整代码如下:
import os
import jieba
import math
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.cluster import KMeans
# 读取新闻文件夹中的所有新闻
news_folder = './news/'
news = []
for folder in os.listdir(news_folder):
folder_path = os.path.join(news_folder, folder)
if os.path.isdir(folder_path):
for file_name in os.listdir(folder_path):
file_path = os.path.join(folder_path, file_name)
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
news.append(content)
# 对每个新闻进行分词
news_tokens = []
for n in news:
tokens = jieba.lcut(n)
news_tokens.append(tokens)
# 将每个词表示成独热向量
vocab = set()
for tokens in news_tokens:
for token in tokens:
vocab.add(token)
vocab = list(vocab)
vocab_size = len(vocab)
onehot_vectors = {}
for i, word in enumerate(vocab):
vector = [0] * vocab_size
vector[i] = 1
onehot_vectors[word] = vector
# 将每个新闻表示为所有词的独热向量之和
onehot_vectors_list = []
for tokens in news_tokens:
vector = [0] * vocab_size
for token in tokens:
if token in onehot_vectors:
vector = [x + y for x, y in zip(vector, onehot_vectors[token])]
onehot_vectors_list.append(vector)
# 计算词频和文档频率
word_count = {}
doc_count = {}
for tokens in news_tokens:
doc_count_set = set()
for token in tokens:
word_count[token] = word_count.get(token, 0) + 1
if token not in doc_count_set:
doc_count[token] = doc_count.get(token, 0) + 1
doc_count_set.add(token)
# 计算TF-IDF权重
tfidf_vectors_list = []
for tokens in news_tokens:
vector = [0] * vocab_size
for token in tokens:
if token in vocab:
tf = tokens.count(token) / len(tokens)
idf = 1 + math.log(len(news_tokens) / doc_count[token])
tfidf = tf * idf
index = vocab.index(token)
vector[index] = tfidf
tfidf_vectors_list.append(vector)
# 将每个词表示成计数向量
bow_vectors = {}
for tokens in news_tokens:
for token in tokens:
bow_vectors[token] = bow_vectors.get(token, 0) + 1
# 将每个新闻表示为所有词的计数向量之和
bow_vectors_list = []
for tokens in news_tokens:
vector = [0] * vocab_size
for token in tokens:
if token in bow_vectors:
index = vocab.index(token)
vector[index] += 1
bow_vectors_list.append(vector)
# 计算余弦相似度
similarity_matrix = cosine_similarity(tfidf_vectors_list)
# 使用KMeans算法进行聚类
kmeans = KMeans(n_clusters=4, random_state=0).fit(tfidf_vectors_list)
labels = kmeans.labels_
通过以上代码,就可以完成新闻文本的聚类分析。在实际应用中,可以根据具体的需求调整向量化方法、相似度计算方法和聚类算法,以便获得最佳的聚类结果。
原文地址: https://www.cveoy.top/t/topic/n2LM 著作权归作者所有。请勿转载和采集!