热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

文本特征处理及文本聚类的几种方法

文本特征处理及文本聚类的几种方法本项目完整源码地址:https:github.comangeliababytextcluster项目博客地址:https:blog

文本特征处理及文本聚类的几种方法

本项目完整源码地址:
https://github.com/angeliababy/textcluster

项目博客地址:
https://blog.csdn.net/qq_29153321/article/details/104015257


数据准备


测试数据说明

data_offline文件夹包含200 economy 类,200个sports类,200个environment类,50个other类,为线下做试验的数据集,id2class.txt为data_offline文件夹中每个文件对应的类别,以此可以比较聚类效果。

src/get_data下为数据准备的过程,获取去除标点符号的文本及编号:

1.get_res.py为处理普通的txt文件

filelist = os.listdir(base_path)f2 = open(out_path, 'w', encoding='UTF-8')for files in filelist:# print (files)filename = files.split('.')[0]f = open(base_path + files, 'r', encoding='UTF-8')text = f.read().replace('\n', '')data = ''.join(re.findall(u'[\u4e00-\u9fff]+', text)) # 必须为unicode类型,取出所有中文字符f2.write(filename + ',')f2.write(data + '\n')f2.close()

2.get_res_csv.py为处理csv文件,并将繁体文转化为简体文

data = pd.read_csv(base_path, usecols=[0, 1, 2], encoding='UTF-8')data.columns = ["news_id", "title", "content"]# data = open(base_path, 'r', encoding='UTF-8')f2 = open(out_path, 'w', encoding='UTF-8')for i in range(len(data)):try:title = data["title"][i].replace('\n', '')#title = Converter('zh-hans').convert(title)title = ''.join(re.findall(u'[\u4e00-\u9fff]+', title))content =data["content"][i].replace('\n', '')content = ''.join(re.findall(u'[\u4e00-\u9fff]+', content))f2.write(str(np.squeeze(data.iloc[i, [0]].values)) + ',')f2.write(title+content + '\n')except:print(data.iloc[i,[0]].values)

文本特征处理

1.tf-idf:
tf-idf = tf(词频)*idf(逆词频)
其中idf(x) = log(N/N(x))
tfidf_Res.py:

# 一、获取标题和分词
sen_seg_list = []
title_list = []
flag, lines = self.load_processfile(process_file)
if flag == False:logging.error("load error")return False, "load error"
for line in lines:title_list.append(line.split(',')[0])sen_seg_list.append(self.seg_words(line.split(',')[1]))# 二、tf-idf提取特征
if not os.path.exists(tfidf_ResFileName):# 该类会将文本中的词语转换为词频矩阵,矩阵元素a[i][j] 表示j词在i类文本下的词频tf_vectorizer = CountVectorizer()# fit_transform是将文本转为词频矩阵tf_matrix = tf_vectorizer.fit_transform(sen_seg_list)# tf_weight = tf_matrix.toarray()# print(tf_weight)# 该类会统计每个词语的tf-idf权值tfidf_transformer = TfidfTransformer()# fit_transform是计算tf-idftfidf_matrix = tfidf_transformer.fit_transform(tf_matrix)# 获取词袋模型中的所有词语word_list = tf_vectorizer.get_feature_names()# 将tf-idf矩阵抽取出来,元素a[i][j]表示j词在i类文本中的tf-idf权重tfidf_weight = tfidf_matrix.toarray()

2.doc2vec
word2vec有2种算法:连续词袋模型(CBOW)和Skip-Gram模型。
CBOW:
在这里插入图片描述
Skip-Gram:
在这里插入图片描述
句向量,是 word2vec 的拓展,考虑了句子的序号id

# 一、获取标题和分词
sen_seg_list = []
title_list = []
flag, lines = self.load_processfile(process_file)
if flag == False:logging.error("load error")return False, "load error"
for line in lines:title_list.append(line.split(',')[0])sen_seg_list.append(self.seg_words(line.split(',')[1]))if not os.path.exists(modelpath):# 存储分词文本if not os.path.exists(data1):self.output_file(data1, sen_seg_list)print("success output")# doc2vec提取特征
sentences = gensim.models.doc2vec.TaggedLineDocument(data1)if not os.path.exists(modelpath):# doc2vec提取特征# 训练并保存模型model = gensim.models.Doc2Vec(sentences, size=100, window=2, min_count=3)model.train(sentences, total_examples=model.corpus_count, epochs=1000)model.save(modelpath)infered_vectors_list = []
print("load doc2vec model...")
model_dm = gensim.models.Doc2Vec.load(modelpath)
print("load train vectors...")
i = 0
for text, label in sentences:vector = model_dm.infer_vector(text)infered_vectors_list.append(vector)i += 1

3.lda
文档主题生成模型,词袋模型,完全考虑词语的分布来判断其主题分布,并依据每个文本的主题概率分布来进行聚类。LDA的目的就是要识别主题,即把文档—词汇矩阵变成文档—主题矩阵(分布)和主题—词汇矩阵(分布)

# 一、获取标题和分词
flag, lines = self.load_processfile(process_file)
if flag == False:logging.error("load error")return False, "load error"
# 分词结果与其他方法形式不同
title_list, sen_seg_list = self.seg_words(lines)# 二、lda模型提取特征
# 构造词典
dictionary = corpora.Dictionary(sen_seg_list)
# 基于词典,使【词】→【稀疏向量】,并将向量放入列表,形成【稀疏向量集】
corpus = [dictionary.doc2bow(words) for words in sen_seg_list]lda = models.ldamodel.LdaModel(corpus=corpus, id2word=dictionary, num_topics=15)lda.save('zhwiki_lda.model')
lda = models.ldamodel.LdaModel.load('zhwiki_lda.model')
# 打印所有主题,每个主题显示10个词
for topic in lda.print_topics(num_words=500):print(topic)# 主题矩阵
ldainfer = lda.inference(corpus)[0]

聚类分析

kmeans:
k簇中心,离簇中心最近进行聚类

k = evaluation(tfidf_matrix)
# 三、Kmeans,大数据量下用Mini-Batch-KMeans算法
km = KMeans(n_clusters=k)
km.fit(tfidf_matrix)
print(Counter(km.labels_)) # 打印每个类多少个
# print(km.cluster_centers_) # 中心点# 存储每个样本所属的簇
clusterRes = codecs.open(cluster_ResFileName, 'w', encoding='UTF-8')
count = 1
while count <&#61; len(km.labels_):clusterRes.write(str(title_list[count - 1]) &#43; &#39;\t&#39; &#43; str(km.labels_[count - 1]))clusterRes.write(&#39;\r\n&#39;)count &#61; count &#43; 1
clusterRes.close()

聚类个数选择&#xff1a;

# ### 三者选其一&#xff0c;SSE较好、但需要看拐点&#xff0c;轮廓系数法比较方便
# # 方法一&#xff1a;&#39;利用SSE选择k&#xff08;手肘法&#xff09;&#39;
# SSE &#61; [] # 存放每次结果的误差平方和
# for k in range(2, 5):
# km &#61; KMeans(n_clusters&#61;k) # 构造聚类器
# km.fit(tfidf_matrix)
# SSE.append(km.inertia_)
#
# X &#61; range(2, 5)
# plt.xlabel(&#39;k&#39;)
# plt.ylabel(&#39;SSE&#39;)
# plt.plot(X, SSE, &#39;o-&#39;)
# plt.show()# 方法二&#xff1a;利用轮廓系数法选择k
Scores &#61; [] # 存放轮廓系数
for k in range(7, 12):km &#61; KMeans(n_clusters&#61;k) # 构造聚类器km.fit(tfidf_weight)Scores.append(metrics.silhouette_score(tfidf_weight, km.labels_, metric&#61;&#39;euclidean&#39;))# X &#61; range(17, 20)
# plt.xlabel(&#39;k&#39;)
# plt.ylabel(&#39;轮廓系数&#39;)
# plt.plot(X, Scores, &#39;o-&#39;)
# plt.show()# # 方法三&#xff1a;值越大越好&#xff0c;重点是速度快
# Ss &#61; [] # 存放Ss
# for k in range(12, 30, 2):
# km &#61; KMeans(n_clusters&#61;k) # 构造聚类器
# km.fit(tfidf_weight)
# Ss.append(metrics.calinski_harabaz_score(tfidf_weight, km.labels_))
#
# X &#61; range(2, 5)
# plt.xlabel(&#39;k&#39;)
# plt.ylabel(&#39;Ss&#39;)
# plt.plot(X, Ss, &#39;o-&#39;)
# plt.show()# 求最优k值
print(Scores)
k &#61; 7 &#43; (Scores.index(max(Scores)))

dbscan:
基于密度的聚类&#xff0c;核心点、边界点、离群点。聚类的时候不需要预先指定簇的个数

# DBSCAN参数不好调节
db &#61; DBSCAN(eps&#61;1.25, min_samples&#61;10).fit(tfidf_weight)
print(db.core_sample_indices_)
print(db.labels_)
# 聚类个数为1-n之间会报错
Score &#61; metrics.silhouette_score(tfidf_weight, db.labels_)
print(Score)# 存储每个样本所属的簇
clusterRes &#61; codecs.open(cluster_ResFileName, &#39;w&#39;, encoding&#61;&#39;UTF-8&#39;)
count &#61; 1
while count <&#61; len(db.labels_):clusterRes.write(str(title_list[count - 1]) &#43; &#39;\t&#39; &#43; str(db.labels_[count - 1]))clusterRes.write(&#39;\r\n&#39;)count &#61; count &#43; 1
clusterRes.close()

gsdmm:
一种基于狄利克雷多项式混合模型的收缩型吉布斯采样算法&#xff0c;可以很好的处理稀疏、高纬度的短文本

# GSDMM文本聚类
mgp &#61; MovieGroupProcess(K&#61;35, alpha&#61;0.1, beta&#61;0.1, n_iters&#61;20)
y &#61; mgp.fit(tfidf_matrix, len(tfidf_matrix))
print(y)# 存储每个样本所属的簇
clusterRes &#61; codecs.open(cluster_ResFileName, &#39;w&#39;, encoding&#61;&#39;UTF-8&#39;)
count &#61; 1
while count <&#61; len(y):clusterRes.write(str(title_list[count - 1]) &#43; &#39;\t&#39; &#43; str(y[count - 1]))clusterRes.write(&#39;\r\n&#39;)count &#61; count &#43; 1
clusterRes.close()

模型评估
聚类模型性能评价指标
有监督的分类算法的评价指标通常是accuracy, precision, recall, etc&#xff1b;由于聚类算法是无监督的学习算法&#xff0c;评价指标则没有那么简单了。因为聚类算法得到的类别实际上不能说明任何问题&#xff0c;除非这些类别的分布和样本的真实类别分布相似&#xff0c;或者聚类的结果满足某种假设&#xff0c;即同一类别中样本间的相似性高于不同类别间样本的相似性。聚类模型的评价指标如下&#xff1a;
详细请看http://scikit-learn.org/stable/modules/clustering.html#clustering-performance-evaluation
如果C是真实类别&#xff0c;K是聚类结果&#xff0c;我们定义a和b分别是&#xff1a;
a: 在C和K中都是同一类别的样本对数
b: 在C和K中都是不同类别的样本对数
raw Rand Index 的公式如下:
在这里插入图片描述
C2nsamples 是样本所有的可能组合对.

FMI
在这里插入图片描述

dict_lable &#61; {&#39;eco&#39;: 2, &#39;env&#39;: 0, &#39;sports&#39;: 1, &#39;other&#39;: 3}
data &#61; pd.read_table(r&#39;id2class.txt&#39;, header&#61;None, delim_whitespace&#61;True)
data2 &#61; pd.read_table(r&#39;cluster_dockmResult.txt&#39;, header&#61;None, delim_whitespace&#61;True)
list_true &#61; []
list_pred &#61; []
for i in range(len(data)):data.iloc[i, 1] &#61; dict_lable[data.iloc[i, 1]]list_true.append(data.iloc[i, 1])list_pred.append(data2.iloc[i, 1])# 文档链接 http://scikit-learn.org/stable/modules/clustering.html#clustering-performance-evaluation
# 2.3.10.1 Adjusted Rand index &#xff08;RI&#xff09;
# 2.3.10.2. Mutual Information based scores&#xff08;NMI&#xff09;
# 2.3.10.4. Fowlkes-Mallows scores&#xff08;FMI&#xff09;
# 章节号为文档里面的章节号
print(metrics.adjusted_rand_score(list_true, list_pred)) # RI指数&#xff0c;越接近1越好
print(metrics.adjusted_mutual_info_score(list_true, list_pred)) # NMI指数&#xff0c;越接近1越好
print(metrics.fowlkes_mallows_score(list_true, list_pred)) # FMI指数&#xff0c;越接近1越好

参考数据集&#xff1a;

data_offline:

Total:650(other&#43;3分类)

Idfkm:4 (分类2-4)
在这里插入图片描述

Doc2veckm:3 (分类2-4)较慢

在这里插入图片描述

Idfdb:-1和3

很差&#xff0c;-1为离群点&#xff0c;254个离群点&#xff0c;仅21个为other

Idfdsgmm:9(10)

很慢&#xff0c;只有1类&#xff0c;很差

Ldakm

在这里插入图片描述
测试集中doc2vec&#43;kmeans效果最好&#xff0c;tf-idf&#43;kmeans其次


推荐阅读
  • 使用 Azure Service Principal 和 Microsoft Graph API 获取 AAD 用户列表
    本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ... [详细]
  • 本文深入探讨了 Java 中的 Serializable 接口,解释了其实现机制、用途及注意事项,帮助开发者更好地理解和使用序列化功能。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 使用Vultr云服务器和Namesilo域名搭建个人网站
    本文详细介绍了如何通过Vultr云服务器和Namesilo域名搭建一个功能齐全的个人网站,包括购买、配置服务器以及绑定域名的具体步骤。文章还提供了详细的命令行操作指南,帮助读者顺利完成建站过程。 ... [详细]
  • 在现代网络环境中,两台计算机之间的文件传输需求日益增长。传统的FTP和SSH方式虽然有效,但其配置复杂、步骤繁琐,难以满足快速且安全的传输需求。本文将介绍一种基于Go语言开发的新一代文件传输工具——Croc,它不仅简化了操作流程,还提供了强大的加密和跨平台支持。 ... [详细]
  • 高效解决应用崩溃问题!友盟新版错误分析工具全面升级
    友盟推出的最新版错误分析工具,专为移动开发者设计,提供强大的Crash收集与分析功能。该工具能够实时监控App运行状态,快速发现并修复错误,显著提升应用的稳定性和用户体验。 ... [详细]
  • 本文详细探讨了JDBC(Java数据库连接)的内部机制,重点分析其作为服务提供者接口(SPI)框架的应用。通过类图和代码示例,展示了JDBC如何注册驱动程序、建立数据库连接以及执行SQL查询的过程。 ... [详细]
  • 本文详细介绍了Java中org.neo4j.helpers.collection.Iterators.single()方法的功能、使用场景及代码示例,帮助开发者更好地理解和应用该方法。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 导航栏样式练习:项目实例解析
    本文详细介绍了如何创建一个具有动态效果的导航栏,包括HTML、CSS和JavaScript代码的实现,并附有详细的说明和效果图。 ... [详细]
  • 在Linux系统中配置并启动ActiveMQ
    本文详细介绍了如何在Linux环境中安装和配置ActiveMQ,包括端口开放及防火墙设置。通过本文,您可以掌握完整的ActiveMQ部署流程,确保其在网络环境中正常运行。 ... [详细]
  • DNN Community 和 Professional 版本的主要差异
    本文详细解析了 DotNetNuke (DNN) 的两种主要版本:Community 和 Professional。通过对比两者的功能和附加组件,帮助用户选择最适合其需求的版本。 ... [详细]
  • 本文深入探讨了Linux系统中网卡绑定(bonding)的七种工作模式。网卡绑定技术通过将多个物理网卡组合成一个逻辑网卡,实现网络冗余、带宽聚合和负载均衡,在生产环境中广泛应用。文章详细介绍了每种模式的特点、适用场景及配置方法。 ... [详细]
  • ImmutableX Poised to Pioneer Web3 Gaming Revolution
    ImmutableX is set to spearhead the evolution of Web3 gaming, with its innovative technologies and strategic partnerships driving significant advancements in the industry. ... [详细]
  • 本教程涵盖OpenGL基础操作及直线光栅化技术,包括点的绘制、简单图形绘制、直线绘制以及DDA和中点画线算法。通过逐步实践,帮助读者掌握OpenGL的基本使用方法。 ... [详细]
author-avatar
天云2_776
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有