维基百科文章爬虫和聚类【二】:KMeans

维基百科是丰富的信息和知识来源。它可以方便地构建为带有类别和其他文章链接的文章,还形成了相关文档的网络。我的 NLP 项目下载、处理和应用维基百科文章上的机器学习算法。

一、说明

        在我的上一篇文章中,展示了该项目的轮廓,并奠定了其基础。首先,维基百科爬虫对象按名称搜索文章,提取标题、类别、内容和相关页面,并将文章存储为纯文本文件。其次,语料库对象处理完整的文章集,允许方便地访问单个文件,并提供全局数据,例如单个标记的数量。

        在本文中,创建了一组精选的维基百科文章并应用了 KMeans 聚类。具体来说,您将学习如何将语料库数据准备为 DataFrame。

        本文的技术背景是Python v3.11scikit-learn v1.2.2。所有示例也应该适用于较新的库版本。

二、语境

        本文是有关使用 Python 进行 NLP 的博客系列的一部分。在我之前的文章中,我介绍了如何创建WikipediaReader文章爬虫,它将以文章名称作为输入,然后系统地下载所有链接的文章,直到达到给定的文章总数或深度。爬虫生成文本文件,然后由一个WikipediaCorpus对象(一个在 NLTK 之上自行创建的抽象)进一步处理,该对象可以方便地访问单个语料库文件和语料库统计信息,例如句子、段落和词汇的数量。

        在本文中,WikipediaReader将从“机器学习”、“航天器”和“Python(编程语言)”文章中下载 100 个子页面,创建包含 270 篇文章的语料库。然后,应用 SciKit Learn 管道来处理每个文档,以进行预处理、标记化和词袋编码。该数据最终被矢量化并输入 KMeans 聚类。

三、设置和数据探索

WikipediaReader和管道的基础WikipediaCorpus以及所有必需的库已在之前的文章中进行了解释。

本文的起点是下载上述三个主题的 100 篇文章文档。

reader = WikipediaReader(dir = "articles")reader.crawl_pages("Artificial Intelligence", total_number = 100)
reader.process()
reader.reset()reader.crawl_pages("Spacecraft", total_number = 100)
reader.process()
reader.reset()reader.crawl_pages("Python (programming language)", total_number = 100)
reader.process()
reader.reset()

语料库对象产生以下统计数据。由于有些文章被多次提及,因此最终的文档数量仅为 270 篇。

root_path = './articles'
corpus = WikipediaPlaintextCorpus(root_path)
print(corpus.describe())
# {'files': 270, 'paras': 13974, 'sents': 47289, 'words': 1146248, 'vocab': 40785, 'max_words': 21058, 'time': 6.870430946350098}

在此语料库中,应用以下 SciKit Learn 管道定义:

root_path = './articles'pipeline = Pipeline([('corpus', WikipediaCorpusTransformer(root_path=root_path)),('categorizer', Categorizer(WikipediaReader())),('preprocessor', TextPreprocessor(root_path=root_path)),('tokenizer', TextTokenizer()),('vectorizer', BagOfWordVectorizer(WikipediaPlaintextCorpus(root_path))),
])

生成的 DataFrame 包含这些列:

  • title:维基百科文章标题(保留大写,但用下划线替换空格)
  • raw:原始的、未格式化的文本
  • 类别:维基百科上为此页面定义的类别名称字典
  • 预处理:词形还原和删除停用词的文本
  • tokens:标记化的预处理文本
  • Bow:对预处理文本进行词袋计数器。

四、使用 SciKit Learn 进行聚类

        聚类是将多维数据点分离成具有相同属性的连贯集合的过程。存在几种具体算法,它们的方法、检测簇的能力和方法、以及它们对输入值的处理和生成输出值的不同。查看 SciKit Learn聚类算法文档页面,支持以下算法:

  • 亲和力传播
  • 凝聚聚类
  • 桦木
  • 数据库扫描
  • 特征集聚
  • K均值
    • 二等分K均值
    • 小批量K均值
  • 均值平移
  • 光学
  • 谱聚类
    • 谱双聚类
    • 光谱共聚类

        对这些算法的深入解释超出了本文的范围。如果您好奇,请参阅文档页面和其他来源,例如维基百科文章。

        要开始在 SciKit learn 中使用聚类算法,最好理解并从示例中学习。具体而言,应明确以下几点:

  1. 如何定义和配置特定的聚类算法?
  2. 输入数据的预期形状是什么?
  3. 如何开始聚类生成(迭代次数,保持最佳拟合模型)?
  4. 算法的输出是什么(二元关联与多类关联、在输入数据中检测到的特征)?
  5. 哪些指标可用于计算聚类分离的好坏?

选择的示例是KMeans 示例教程,它展示了如何对内置数据集进行聚类。

五、KMeans 聚类示例

        KMeans算法通过形成具有质心点的沃罗尼单元来检测簇,使得数据点和质心之间的平均距离最小。

        SciKit Learn 示例适用于新闻组文章的内置数据集。文章加载如下:

# Source: https://scikit-learn.org/stable/auto_examples/text/plot_document_clustering.html#sphx-glr-auto-examples-text-plot-document-clustering-py
import numpy as np
from sklearn.datasets import fetch_20newsgroupscategories = ["alt.atheism","talk.religion.misc","comp.graphics","sci.space",
]dataset = fetch_20newsgroups(remove=("headers", "footers", "quotes"),subset="all",categories=categories,shuffle=True,random_state=42,
)

        生成的对象dataset提供以下方法来访问语料库及其类别:

print(dataset.DESCR)
# _20newsgroups_dataset:
#
#  The 20 newsgroups text dataset
#  ------------------------------
#
#  The 20 newsgroups dataset comprises around 18000 newsgroups posts on
#  20 topics split in two subsets: one for tr ...print(dataset.data[:1])
# ["My point is that you set up your views as the only way to believe.  Saying \nthat all eveil in this world is caused by atheism is ridiculous and \ncounterproductive to dialogue in this newsgroups.  I see in your posts a \nspirit of condemnation of the atheists in this newsgroup bacause they don'\nt believe exactly as you do.  If you're here to try to convert the atheists \nhere, you're failing miserably.  Who wants to be in position of constantly \ndefending themselves agaist insulting attacks, like you seem to like to do?!\nI'm sorry you're so blind that you didn't get the messgae in the quote, \neveryone else has seemed to."]print(dataset.filenames)
#['/Users/guenthers/scikit_learn_data/20news_home/20news-bydate-train/alt.atheism/53184'
# '/Users/guenthers/scikit_learn_data/20news_home/20news-bydate-train/comp.graphics/37932'
# '/Users/guenthers/scikit_learn_data/20news_home/20news-bydate-test/comp.graphics/38933' ...print(dataset.target)
# [0 1 1 ... 2 1 1]print(dataset.target_names)
# ['alt.atheism', 'comp.graphics', 'sci.space', 'talk.religion.misc']

        可以看出,数据集只是原始文本表示,类别名称是存储在列表中的字符串。文章和类别之间的关联表示为代表其列表中的类别的单个数字。例如,上面示例中的第一篇文章列出了0其类别,这意味着dataset.target_names[0]导致alt.atheism.

        该数据使用内置矢量化器进行矢量化。该示例使用 TfIdf。

# https://scikit-learn.org/stable/auto_examples/text/plot_document_clustering.html#sphx-glr-auto-examples-text-plot-document-clustering-py
from sklearn.feature_extraction.text import TfidfVectorizervectorizer = TfidfVectorizer(max_df=0.5,min_df=5,stop_words="english",
)
t0 = time()
X_tfidf = vectorizer.fit_transform(dataset.data)

聚类算法由以下代码片段定义:

# https://scikit-learn.org/stable/auto_examples/text/plot_document_clustering.html#sphx-glr-auto-examples-text-plot-document-clustering-py
kmeans = KMeans(n_clusters=true_k,max_iter=100,n_init=5,
)

        为了计算特定的聚类模型、其指标(同质性、完整性、v-measure)及其训练时间,使用以下方法:

# Source: https://scikit-learn.org/stable/auto_examples/text/plot_document_clustering.html#sphx-glr-auto-examples-text-plot-document-clustering-py
def fit_and_evaluate(km, X, name=None, n_runs=5):name = km.__class__.__name__ if name is None else nametrain_times = []scores = defaultdict(list)for seed in range(n_runs):km.set_params(random_state=seed)t0 = time()km.fit(X)train_times.append(time() - t0)scores["Homogeneity"].append(metrics.homogeneity_score(labels, km.labels_))scores["Completeness"].append(metrics.completeness_score(labels, km.labels_))scores["V-measure"].append(metrics.v_measure_score(labels, km.labels_))scores["Adjusted Rand-Index"].append(metrics.adjusted_rand_score(labels, km.labels_))scores["Silhouette Coefficient"].append(metrics.silhouette_score(X, km.labels_, sample_size=2000))train_times = np.asarray(train_times)fit_and_evaluate(kmeans, X_tfidf, name="KMeans\non tf-idf vectors")

        这是很多代码,让我们稍微分离一下观察结果。此方法使用不同的随机种子值重复启动 KMeans 集群。它设置训练的开始时间,调用.fit(X)创建集群的方法,然后计算不同的指标分数。每个分数将预期标签集与聚类算法生成的标签进行比较。最后,训练时间和指标作为字典返回给调用者。

        现在所有提出的问题都可以得到解答。

  1. 如何定义和配置特定的聚类算法?=> 该算法表示为一个 Python 类,其中包含一组特定于该算法的预定义和可自定义参数。
  2. 输入数据的预期形状是什么?=> 形状​​为 的矩阵number_of_samples x data_vector,其中data_vector是数值数据,并且所有样本需要具有相同的长度。
  3. 如何开始聚类生成(迭代次数,保持最佳拟合模型)?.fit()=> 通过调用Python 对象并提供输入数据来开始生成簇。此方法返回一个表示具体聚类模式的对象。
  4. 算法的输出是什么(二元关联与多类关联、在输入数据中检测到的特征)?=> 聚类方案由将样本与索引号相关联的列表组成。索引号代表一个簇。
  5. 哪些指标可用于计算聚类分离的好坏?指标是特定于集群算法的,它们需要计算一组预期的集群。

有了这些知识,让我们尝试一下使用 KMeans 的简单尝试。

六、朴素 K 均值

        首先,维基百科文章需要转换为向量表示。为此,我们将使用创建的词袋,它是一个字典数据结构,其中索引是一个单词,值是该单词出现的次数。该字典将使用内置的DictVectorizer.

from sklearn.feature_extraction import DictVectorizervectorizer = DictVectorizer(sparse=False)
x_train = vectorizer.fit_transform(X['bow'].to_numpy())

        然后,我们创建 KMains 对象并定义其属性(8 个集群,随机状态设置为 0)。

from sklearn.cluster import KMeanskmeans = KMeans(n_clusters=8, random_state=0)

        该对象根据输入数据进行训练。

kmeans.fit(x_train)

        然后可以检查生成的簇。

print(kmeans.labels_.shape)
#(272,)

print(kmeans.labels_)
#[0 0 5 3 6 6 3 0 0 0 0 0 0 3 0 0 0 6 0 3 6 0 5 0 1 6 0 3 6 0 0 0 6 6 0 6 0
# 6 3 0 0 0 3 6 6 0 3 3 0 0 0 3 0 1 5 3 0 0 0 0 6 0 0 5 6 3 5 1 6 5 0 0 0 0
# 0 6 3 0 0 6 0 0 3 3 3 0 6 0 0 0 0 0 6 6 6 6 4 6 5 3 3 6 3 0 1 3 0 0 3 0 6
# 0 0 0 3 5 6 6 4 0 0 0 1 0 6 6 3 6 6 1 0 0 1 6 3 0 6 1 6 6 0 6 0 3 0 6 0 0
# 0 3 1 0 0 6 0 6 6 1 6 6 3 0 0 0 6 0 0 6 0 6 0 6 0 0 0 3 0 0 0 1 0 6 6 6 0
# 1 0 0 3 6 0 1 5 0 0 0 0 3 0 0 5 0 3 6 0 2 6 0 2 0 6 3 3 6 0 0 7 5 0 0 1 3
# 1 6 3 6 0 0 6 1 6 6 0 0 0 0 6 6 0 0 0 6 6 1 5 1 6 1 4 0 0 6 2 3 6 1 3 7 6
# 4 3 3 0 1 3 6 6 6 6 0 



七、聚类解释和绘图

        只需查看标签向量,似乎许多文章都与第一个集群相关联。让我们想象一下具体的关联。

显示文档与集群关联的顺序的条形图:

import matplotlib.pyplot as pltplt.ylabel('Clusters')
plt.xlabel('Document ID')
plt.plot(kmeans.labels_, 'o')

以及显示每个簇的文档绝对计数的直方图:

plt.hist(x=kmeans.labels_,  bins=8, density=False)
plt.grid(True)
plt.show()

好的,但是簇 0 具体是关于什么的呢?我们先看一下文章名称。

def get_cluster_articles(c_id, lables):return [X['title'][i] for i,l in enumerate(lables) if l == c_id]print(get_cluster_articles(0, kmeans.labels_))
# '"Hello,_World!"_program', '2001_A_Space_Odyssey', 'ABC_programming_language', 'ACM_Computing_Classification_System', 'ADMB', 'AIVA', 'AIXI', 'AI_accelerator', 'AI_boom', 'AI_capability_control', 'AI_effect', 'AI_takeover', 'ALGOL_60', 'ANSI_C', 'Abaqus', 'Abstract_and_concrete', 'Academic_Free_License', 'Academic_conference', 'Acoustic_location', 'Activation_function', 'Adam_Tooze', 'Adaptable_robotics', 'Advanced_Simulation_Library', 'Aeronautics', 'Agent_architecture', 'Agricultural_robot', 'Ai', ... 'Earth_observation_satellite', 'Eclipsed_conformation', 'European_Union_Space_Programme', 'Expendable_launch_system', 'Fédération_Aéronautique_Internationale', "Gagarin's_Start", 'Geocentric_orbit', 'Geosynchronous_orbit', 'Ground_segment', 'Ground_station', 'Guidance,_navigation,_and_control', 'Inter-satellite_service', 'Intergalactic_travel', 'Orbital_inclination', 'Transponder_satellite_communications']

此外,让我们使用同名库创建一个Wordcloud 。

from wordcloud import WordClouddef wordcloud_for_cluster(c_id, lables):text = ' '.join([X['preprocessed'][i] for i,l in enumerate(lables) if l == c_id ])wordcloud = WordCloud(max_font_size=50, max_words=20).generate(text)plt.imshow(wordcloud, interpolation='bilinear')plt.axis("off")plt.show()wordcloud_for_cluster(0, kmeans.labels_)

        嗯,几篇关于人工智能与航天器混合的文章?虽然我第一次尝试使用 KMeans 时对一个聚类的“抽查”只是经验数据的印象,但所实现的聚类效果并不令人满意。没有预期的簇分离,没有预期的标签是理所当然的。

        那么如何在人工智能和航天器文章更加分离的意义上改善这种聚类呢?这将是下一篇文章的任务。

八、项目学习

        在项目期间,由于不熟悉所涉及的不同库,我做出了一些错误的假设和简单的编程错误。本节简要反映了这些经验教训,希望其他人可以避免它们:

  1. SciKit learn 使用传递给它的完整矩阵。使用 Pandas DataFrame 时,请确保仅转发那些包含数字数据的列。
  2. SciKit 学习算法仅适用于数字数据。您不能传递预处理的、标记化的文本,也不能传递表示单词出现或频率的字典对象。
  3. 决定从头开始推出自己的算法或使用库提供的算法。一方面,从头开始编程很有教育意义,另一方面,如果您使用错误的假设,则会令人沮丧。对于文本矢量化,所有库都提供了您可以使用的简单分词器和矢量化器。

九、结论

        本文展示了如何将 KMeans 聚类应用于维基百科的一组文档。起点是创建一个语料库,这是来自维基百科的关于三个不同主题的纯文本文章列表。这些文章由 SciKit Learn 管道使用,以对文章进行预处理、标记化和词袋编码。为了实际理解聚类,您看到了 KMeans 示例的解释,它回答了有关聚类算法设置和配置、输入数据、如何执行聚类以及输出数据的问题。本文的最后部分使用 KMeans 对词袋进行向量化。唉,这些集群似乎没有足够的区别,例如将人工智能和宇宙飞船归为同一类别。下一篇文章将研究如何改进聚类。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/199713.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LOJ #10134. 「一本通 4.4 练习 1」Dis

分析 根据数据范围分析一下复杂度,Floyd和dj算法都必爆。 发现题目说的是树,还是边还是双向的(树本身就是无向的,连通无回路的无向图叫做无向树,简称树。如果题目说了树,那么默认边就是双向的&#xff09…

(二)汇编语句组成

一个完整的 RISC-V 汇编程序有多条 语句(statement) 组成。 一条典型的 RISC-V 汇编 语句 由 3 部分组成: 1.标签 List item label(标签): 标签是标识程序位置的记号。通常定义一个名称然后加上":"后缀。…

PP-PicoDet算法训练行人检测模型

PP-PicoDet算法训练行人检测模型 1,效果图2,PP-PicoDet介绍3,使用飞浆框架训练模型1,准备好图片和对应的标注文件2,划分训练集和验证集3,vi label_list.txt4,目录结构5,修改配置文件…

【Windows 常用工具系列 11 -- 福昕PDF搜索高亮过的文本】

文章目录 福昕 PDF 搜索高亮过的文本 福昕 PDF 搜索高亮过的文本 在 pdf 文档阅读过程中,我们需要经常高亮一些文本,以方便下次阅读时找到重点。我这边使用的是 福昕PDF 阅读器,下面就介绍下如何在福昕阅读器中搜索已经高亮过的文本。

场景交互与场景漫游-交运算与对象选取(8-1)

交运算与对象选取 在面对大规模的场景管理时,场景图形的交运算和图形对象的拾取变成了一项基本工作。OSG作为一个场景管理系统,自然也实现了场景图形的交运算,交运算主要封装在osgUtil 工具中在OSG中,osgUtil是一个非常强有力的工…

python实战—核心基础4(超市购物小票随机抽奖程序) lv1

目录 一、核心代码解释 二、代码 三、运行截图 一、核心代码解释 1、random() 函数 描述 random() 方法返回随机生成的一个实数,它在[0,1)范围内。 语法 以下是 random() 方法的语法: import randomrandom.random() 注意:random()是不能直接访问…

OpenLDAP配置web管理界面PhpLDAPAdmin服务-centos9stream

之前已经发了一篇关于centos9下面配置openldap多主高可用集群的内容,不会配置ldap集群的请参考:服务器集群配置LDAP统一认证高可用集群(配置tsl安全链接)-centos9stream-openldap2.6.2-CSDN博客 这里跟着前篇文章详细说明如何配置…

在回调之间共享数据

可以在 App 中为 UI 组件编写回调函数,以指定用户与其交互时的行为方式。 在具有多个相互依赖的 UI 组件的 App 中,回调函数通常必须访问主 App 函数中定义的数据,或与其他回调函数共享数据。例如,如果创建一个具有列表框的 App&a…

.Net中Redis的基本使用

前言 Redis可以用来存储、缓存和消息传递。它具有高性能、持久化、高可用性、扩展性和灵活性等特点,尤其适用于处理高并发业务和大量数据量的系统,它支持多种数据结构,如字符串、哈希表、列表、集合、有序集合等。 Redis的使用 安装包Ser…

云计算赛项容器云2023搭建

部署容器云平台[5 分] 使 用 OpenStack 私 有 云 平 台 创 建 两 台 云 主 机 , 云 主 机 类 型 使 用 4vCPU/12G/100G 类型,分别作为 Kubernetes 集群的 Master 节点和 node 节点, 然后完成 Kubernetes 集群的部署,并完成 Istio …

【MySql】13- 实践篇(十一)

文章目录 1. 自增主键为什么不是连续的?1.1 自增值保存在哪儿?1.2 自增值修改机制1.2.1 自增值的修改时机1.2.2 自增值为什么不能回退? 1.3 自增锁的优化1.3.1 自增锁设计历史 2. Insert语句为何很多锁?2.1 insert … select 语句2.2 insert 循环写入2…

鸿蒙4.0真机调试踩坑

传言鸿蒙next版本将不再兼容Android,所以领导安排做下鸿蒙开发的调研工作。 鸿蒙开发指南其实已经非常的友好了。但是鸿蒙开发本身还是有些坑要踩,这篇文章主要讲了鸿蒙真机调试问题。 目前手上的真机为华为 nova6,处理器为麒麟990.鸿蒙系统…

AI绘画使用Stable Diffusion(SDXL)绘制三星堆风格的图片

一、前言 三星堆文化是一种古老的中国文化,它以其精湛的青铜铸造技术闻名,出土文物中最著名的包括青铜面具、青铜人像、金杖、玉器等。这些文物具有独特的艺术风格,显示了高度的工艺水平和复杂的社会结构。 青铜面具的巨大眼睛和突出的颧骨&a…

11.16~11.19绘制图表,导入EXCEL中数据,进行拟合

这个错误通常是由于传递给curve_fit函数的数据类型不正确引起的。根据你提供的代码和错误信息,有几个可能的原因: 数据类型错误:请确保ce_data、lg_data和product_data是NumPy数组或类似的可迭代对象,且其元素的数据类型为浮点数。…

C#,怎么修改(VS)Visual Studio 2022支持的C#版本

一些文字来自于 Microsoft . (只需要读下面的红色文字即可!) 1 C# 语言版本控制 最新的 C# 编译器根据项目的一个或多个目标框架确定默认语言版本。 Visual Studio 不提供用于更改值的 UI,但可以通过编辑 .csproj 文件来更改值。…

基于SSM的学院网站设计与实现

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:Vue 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目:是 目录…

4.3 Windows驱动开发:监控进程与线程对象操作

在内核中,可以使用ObRegisterCallbacks这个内核回调函数来实现监控进程和线程对象操作。通过注册一个OB_CALLBACK_REGISTRATION回调结构体,可以指定所需的回调函数和回调的监控类型。这个回调结构体包含了回调函数和监控的对象类型,还有一个A…

Camtasia2024年破解版安装包如何下载?

作为一个互联网人,没少在录屏软件这个坑里摸爬滚打。培训、学习、游戏、影视解说……都得用它。这时候没个拿得出手的私藏软件,还怎么混?说实话,录屏软件这两年也用了不少,基本功能是有但总觉得缺点什么,直…

C进阶---文件操作

我们在日常使用电脑保存文件时,其目的就是为了便于以后查看、修改、更新等操作;保存在文件中可以使数据持久化,所以今天我们家里学习文件的相关操作。 一、文件 1.1什么是文件 磁盘上的文件是文件。 在程序设计中,文件一般分…

某60区块链安全之51%攻击实战学习记录

区块链安全 文章目录 区块链安全51%攻击实战实验目的实验环境实验工具实验原理攻击过程 51%攻击实战 实验目的 1.理解并掌握区块链基本概念及区块链原理 2.理解区块链分又问题 3.理解掌握区块链51%算力攻击原理与利用 4.找到题目漏洞进行分析并形成利用 实验环境 1.Ubuntu1…