自然语言处理实战第二版(MEAP)(六)(5)

本文涉及的产品
NLP自然语言处理_基础版,每接口每天50万次
NLP 自学习平台,3个模型定制额度 1个月
NLP自然语言处理_高级版,每接口累计50万次
简介: 自然语言处理实战第二版(MEAP)(六)

自然语言处理实战第二版(MEAP)(六)(4)https://developer.aliyun.com/article/1519696

实体和关系名称类似于 Python 中的变量名称。你希望能够像数据库中的字段名称那样查询它们,因此它们不应该有歧义的拼写。原始的 NELL 数据集每行包含一个三元组(事实)。三元组可以被读作简洁、明确定义的句子。知识三元组描述了世界上的一个单独事实。它们给出了关于世界中一个实体(对象)的一条信息。

至少,知识三元组由实体、关系和值组成。知识三元组的第一个元素给出了关于事实的实体名称。第二列“关系”包含与世界中某些其他性质(形容词)或对象(名词)的关系,称为它的值。关系通常是以“是”或“有”等词开始或暗示的动词短语。第三列“值”包含该关系的某个质量的标识符。该“值”是关系的对象,并且与三元组的主语(“实体”)一样是一个命名实体。

因为 NELL 众包了知识库的管理,所以你还有一个概率或置信度值,可以用来推断冲突信息。而且 NELL 还有关于事实的 9 个更多信息列。它列出了用于引用特定实体、关系或值的所有替代短语。NELL 还识别了创建该事实的迭代(遍历 Twitter)。最后一列提供了数据的来源 - 创建事实的所有文本列表。

NELL 包含有关 800 多种唯一关系和超过 200 万个实体的事实。因为 Twitter 主要涉及人物、地点和企业,所以它是一个很好的知识库,可用于增强常识知识库。它对于对名人或企业以及经常是错误信息宣传目标的地点进行事实核查也可能很有用。甚至有一个 “latitudelongitude” 关系,您可以使用它来验证与事物位置相关的任何事实。

>>> islatlon = df['relation'] == 'latlon'
>>> df[islatlon].head()
               entity relation                 value
241          cheveron   latlon      40.4459,-79.9577
528        licancabur   latlon   -22.83333,-67.88333
1817             tacl   latlon     13.53333,37.48333
2967            okmok   latlon  53.448195,-168.15472
2975  redoubt_volcano   latlon   60.48528,-152.74306

现在你已经学会了如何将事实组织成知识图谱。但是当我们需要使用这些知识时 - 例如,用于回答问题时,我们该怎么办?这将是本章最后一节要处理的内容。

11.9 在知识图谱中查找答案

现在我们的事实都组织在一个图形数据库中,我们如何检索那些知识呢?与任何数据库一样,图形数据库有特殊的查询语言来从中提取信息。就像 SQL 及其不同的方言用于查询关系数据库一样,一系列语言,如 SPARQL(SPARQL 协议和 RDF 查询语言),Cypher 和 AQL 存在用于查询图数据库。在本书中,我们将专注于 SPARQL,因为它已被开源社区采用为标准。其他语言,如 Cypher 或 AQL,用于查询特定的图知识库,如 Neo4j 和 ArangoDB。

我们将使用一个比 NELL 更大的知识图谱作为我们的知识基础:Wikidata,维基百科的知识数据库版本。它包含超过 1 亿个数据项(实体和关系),由志愿编辑和机器人维护,就像所有其他维基媒体项目一样。

在 Wikidata 中,实体之间的关系被称为 属性。Wikidata 系统中有超过 11,000 个属性,每个属性都有其 “P-id”,这是一个用于在查询中表示该属性的唯一标识符。同样,每个实体都有其自己独特的 “Q-id”。您可以通过使用 Wikidata 的 REST API 轻松检索任何维基百科文章的 Q-id:

>>> def get_wikidata_qid(wikiarticle, wikisite="enwiki"):
...     WIKIDATA_URL='https://www.wikidata.org/w/api.php'
...     resp = requests.get(WIKIDATA_URL, timeout=5, params={
...         'action': 'wbgetentities',
...         'titles': wikiarticle,
...         'sites': wikisite,
...         'props': '',
...         'format': 'json'
...     }).json()
...     return list(resp['entities'])[0]
>>> tg_qid = get_wikidata_qid('Timnit Gebru')
>>> tg_qid
'Q59753117'

您可以通过前往 (www.wikidata.org/entity/Q59753117) 确认您的发现,并在那里找到该实体的更多属性,将其链接到不同的实体。正如您所看到的,这是一个简单的 “GET” 查询,只有在我们已经有了实体名称并且想要找到 Q-id(或反之)时才有效。对于更复杂的查询,我们将需要使用 SPARQL。那么我们来写你的第一个查询吧!

假设你想知道谁是 Timnit Gebru 的关于 Stochastic Parrots 的著名论文的合著者。如果你不记得论文的名称确切,你实际上可以通过一个简单的查询找到它。为此,你需要一些属性和实体 ID - 为简单起见,我们只在代码中列出它们。

>>> NOTABLE_WORK_PID = 'P800'     # #1
>>> INSTANCE_OF_PID = 'P31'       # #2
>>> SCH_ARTICLE_QID= 'Q13442814'  # #3
>>> query = f"""  ... SELECT ?article WHERE {{  ... wd:{tg_qid} wdt:{NOTABLE_WORK_PID} ?article.  ... ?article wdt:{INSTANCE_OF_PID} wd:Q13442814.  ...  ... SERVICE wikibase:label {{ bd:serviceParam  ... wikibase:language "en". }}  ... }}  ... """
重要提示

不要忘记在 f-strings 中双重转义大括号!而且你不能在 f-strings 中使用反斜杠作为转义字符。 错误:f"{“,而应该是双大括号。 正确:f”{{"

如果你熟悉jinja2包,请注意混合使用 Python f-strings 来填充 jinja2 模板时,你需要四个花括号来创建一个文字双花括号。

乍一看,这个查询看起来有些神秘,它的意思是“找到一个实体 A,使得 Timnit Gebru 有 A 作为知名作品,并且 A 是学术文章的一个实例”。你可以看到每个关系条件在 SPARQL 中是如何编码的,操作数 wd: 在实体 Q-id 前面,操作数 wdt: 在属性 P-id 前面。每个关系约束都有一个“实体有-属性-实体”的形式。

现在让我们使用 WIKIDATA 的 SPARQL API 来检索我们查询的结果。为此,我们将使用一个专门的SPARQLWrapper包,它将简化我们的查询过程。首先,让我们设置我们的包装器:

>>> from SPARQLWrapper import SPARQLWrapper, JSON
>>>
>>> endpoint_url = "https://query.wikidata.org/sparql"
>>> sparql = SPARQLWrapper(endpoint_url)
>>> sparql.setReturnFormat(JSON)  # #1

一旦设置好,你就可以执行你的查询并检查响应:

>>> sparql.setQuery(query)
>>> result = sparql.queryAndConvert()
>>> result
{'head': {'vars': ['article', 'articleLabel']},
 'results': {'bindings': [{'article': {'type': 'uri',
     'value': 'http://www.wikidata.org/entity/Q105943036'},
    'articleLabel': {'xml:lang': 'en',
     'type': 'literal',
     'value': 'On the Dangers of Stochastic Parrots:
     Can Language Models Be Too Big?🦜'}}]}}

看起来没问题!现在你已经得到了文章的 Q-id - 你可以通过使用文章的 ‘author’ 属性来检索它的作者:

>>> import re
>>> uri = result['results']['bindings'][0]['article']['value']
>>> match_id = re.search(r'entity/(Q\d+)', uri)
>>> article_qid = match_id.group(1)
>>> AUTHOR_PID = 'P50'
>>>
>>> query = f"""  ... SELECT ?author ?authorLabel WHERE {{  ... wd:{article_qid} wdt:{AUTHOR_PID} ?author.  ... SERVICE wikibase:label {{ bd:serviceParam wikibase:language "en". }}  ... }}  ... """
>>> sparql.setQuery(query)
>>> result = sparql.queryAndConvert()['results']['bindings']
>>> authors = [record['authorLabel']['value'] for record in result]
>>> authors
['Timnit Gebru', 'Margaret Mitchell', 'Emily M. Bender']

现在你有了你问题的答案!

我们可以通过将查询嵌套在彼此内部来完成相同的结果,而不是执行两个查询,就像这样:

>>> query = """  ... SELECT ?author ?authorLabel WHERE {  ... {  ... SELECT ?article WHERE {  ... wd:Q59753117 wdt:P800 ?article.  ... ?article wdt:P31 wd:Q13442814.  ... }  ... }  ... ?article wdt:P50 ?author.  ... SERVICE wikibase:label {  ... bd:serviceParam wikibase:language "en".  ... }  ... }  ... """

SPARQL 是一种功能齐全的语言,其功能不仅限于简单的查询。Wikidata 本身对 SPARQL 有一个相当不错的手册。你挖掘 Wikidata 使用 SPARQL 的深度越深,你将在你的 NLP 应用中找到越多的用途。这是你可以自动评估你的 NLP 流水线对用户断言的事实的质量和正确性的唯一方式之一。

11.9.1 从问题到查询

因此,你成功在知识数据库中找到了一个相当复杂的问题的答案。如果你的数据库是关系型的,或者你只有非结构化的文本,那几乎是不可能做到的。

然而,寻找答案花费了我们相当多的工作和两个 SPARQL 查询。如何将自然语言问题转化为像 SPARQL 这样的结构化语言的查询?

你以前已经做过这种转换,在第九章的时候。将人类语言翻译成机器语言比在人类语言之间进行翻译要困难一些,但对于机器来说,这仍然是同一个基本问题。现在你知道了转换器擅长将一种语言转换成另一种语言。作为庞大的转换器,LLMs 尤其擅长此类操作。Sachin Charma 创建了一个很好的示例,使用另一个图数据库 ArangoDB 构建知识图谱。他使用 OpenAI 的模型来使数据库上的自然语言问答成为可能。

11.10 自我测试

  • 给出一个问题的例子,这个问题比使用关系数据库更容易回答。
  • 使用 networkx 的有向图将其转换为一个 Pandas DataFrame 的边列表,其中包含两列 source_nodetarget_node。对于单个源节点,检索所有目标节点 ID 需要多长时间?对于这些新的源节点的所有目标节点呢?如何通过索引加速 Pandas 图查询?
  • 创建一个 Spacy Matcher,可以从关于 Timnit Gebru 的维基百科文章中提取更多的工作地点。您能够检索到多少个?
  • 图数据库能做到的事情有关系数据库不能做到的吗?关系数据库能做到图数据库不能做到的事情吗?
  • 使用大型语言模型从自然语言生成 SPARQL wikidata 查询。在没有编辑代码的情况下,它是否正确工作?对于需要在您的知识图谱中进行五次关系(边)遍历的查询,它是否有效?
  • 使用 nlpia2.text_processing 中的 extractors.pyheatmaps.py 为从您自己的长文档(可能是一系列关于自然语言处理的 Mastodon 微博帖子)中提取的句子创建 BERT 相似度热图。编辑 heatmaps.py 代码以改进它,以便您可以专注于非常相似的行。提示:您可以使用非线性函数来缩放余弦相似度值,并使用阈值将相似度值重置为零。

11.11 总结

  • 知识图谱可以用来存储实体之间的关系。
  • 您可以使用基于规则的方法(如正则表达式)或基于神经网络的方法来隔离和提取非结构化文本中的信息。
  • 词性标注和依赖分析允许您提取句子中提到的实体之间的关系。
  • 像 SPARQL 这样的语言可以帮助您在知识图谱中找到所需的信息。

[1] Wikipedia 上的“Symbolic AI”文章(en.wikipedia.org/wiki/Symbolic_artificial_intelligence

[2] 参见名为“自然语言处理:TM-Town”的网页(www.tm-town.com/natural-language-processing#golden_rules)。

[3] “PyPi 上的 Rstr 包”(pypi.org/project/rstr/)。

[4] 参见名为“在 DuckDuckGo 上搜索 Python 句子分段”的网页(duckduckgo.com/?q=Python+sentence+segment&t=canonical&ia=qa)。

[5] GitLab 上的手稿源代码(gitlab.com/tangibleai/nlpia2/-/tree/main/src/nlpia2/data/manuscript/adoc

[6] 单层神经网络或感知器中的每个神经元,在数学上等同于逻辑回归。

[7] 参见名为“Facts & Figures:spaCy 使用文档”的网页(spacy.io/usage/facts-figures)。

[8] 参见名为“nltk.tokenize 包 — NLTK 3.3 文档”的网页(www.nltk.org/api/nltk.tokenize.html#module-nltk.tokenize.punkt)。

[9] SpaCy 是迄今为止我们发现的最准确、最高效的 NLP 解析器,并由欧洲的一个出色的、超级合作的 NLP 工程师团队在 Explosion.ai 定期维护和更新(explosion.ai/about)。

[10] GitLab 上 nlpia2 包中的heatmaps.py模块(gitlab.com/tangibleai/nlpia2/-/blob/main/src/nlpia2/heatmaps.py)。

[11] GitLab 上 nlpia2 包中的extractors.extract_lines()函数(gitlab.com/tangibleai/nlpia2/-/blob/main/src/nlpia2/text_processing/extractors.py#L69)。

[12] 官方 AsciiDoc 解析器是 Ruby。根据文档,目前还没有 Python 包(gitlab.eclipse.org/eclipse-wg/asciidoc-wg/asciidoc.org/-/blob/main/awesome-asciidoc.adoc#convert)。

[13] 斯坦福大学 AI 指数上有关 AI 研究的统计数据(AIIndex.org)。

[14] spaCy 使用“OntoNotes 5”词性标签:(spacy.io/api/annotation#pos-tagging)。

[15] 查看名为“代码示例:spaCy 使用文档”的网页(spacy.io/usage/examples#phrase-matcher)。

[16] 查看名为“匹配器:spaCy API 文档”的网页(spacy.io/api/matcher)。

[17] 这是一项积极研究的课题:nlp.stanford.edu/pubs/structuredVS.pdf

[18] “实现用于关系抽取的自定义可训练组件”:(explosion.ai/blog/relation-extraction)。

[19] 有一些硬编码的常识知识库供您使用。Google Scholar 是您在知识图谱搜索中的好朋友。

[20] Wikidata SPARQL 教程:(www.wikidata.org/wiki/Wikidata:SPARQL_tutorial)。

[21] 如何使用 ChatGPT 和 ArangoDB 构建知识图谱增强的聊天机器人(archive.today/fJB7H)。

相关文章
|
1月前
|
自然语言处理 PyTorch 算法框架/工具
掌握从零到一的进阶攻略:让你轻松成为BERT微调高手——详解模型微调全流程,含实战代码与最佳实践秘籍,助你应对各类NLP挑战!
【10月更文挑战第1天】随着深度学习技术的进步,预训练模型已成为自然语言处理(NLP)领域的常见实践。这些模型通过大规模数据集训练获得通用语言表示,但需进一步微调以适应特定任务。本文通过简化流程和示例代码,介绍了如何选择预训练模型(如BERT),并利用Python库(如Transformers和PyTorch)进行微调。文章详细说明了数据准备、模型初始化、损失函数定义及训练循环等关键步骤,并提供了评估模型性能的方法。希望本文能帮助读者更好地理解和实现模型微调。
60 2
掌握从零到一的进阶攻略:让你轻松成为BERT微调高手——详解模型微调全流程,含实战代码与最佳实践秘籍,助你应对各类NLP挑战!
|
5月前
|
机器学习/深度学习 人工智能 自然语言处理
Python自然语言处理实战:文本分类与情感分析
本文探讨了自然语言处理中的文本分类和情感分析技术,阐述了基本概念、流程,并通过Python示例展示了Scikit-learn和transformers库的应用。面对多义性理解等挑战,研究者正探索跨域适应、上下文理解和多模态融合等方法。随着深度学习的发展,这些技术将持续推动人机交互的进步。
275 1
|
5月前
|
自然语言处理 监控 数据挖掘
|
4月前
|
人工智能 自然语言处理 Java
Java中的自然语言处理应用实战
Java中的自然语言处理应用实战
|
5月前
|
机器学习/深度学习 数据采集 人工智能
Python 高级实战:基于自然语言处理的情感分析系统
**摘要:** 本文介绍了基于Python的情感分析系统,涵盖了从数据准备到模型构建的全过程。首先,讲解了如何安装Python及必需的NLP库,如nltk、sklearn、pandas和matplotlib。接着,通过抓取IMDb电影评论数据并进行预处理,构建情感分析模型。文中使用了VADER库进行基本的情感分类,并展示了如何使用`LogisticRegression`构建机器学习模型以提高分析精度。最后,提到了如何将模型部署为实时Web服务。本文旨在帮助读者提升在NLP和情感分析领域的实践技能。
163 0
|
6月前
|
机器学习/深度学习 自然语言处理 机器人
自然语言处理实战第二版(MEAP)(六)(4)
自然语言处理实战第二版(MEAP)(六)
47 2
|
6月前
|
机器学习/深度学习 自然语言处理 机器人
自然语言处理实战第二版(MEAP)(六)(3)
自然语言处理实战第二版(MEAP)(六)
61 1
|
5月前
|
机器学习/深度学习 自然语言处理 PyTorch
【从零开始学习深度学习】48.Pytorch_NLP实战案例:如何使用预训练的词向量模型求近义词和类比词
【从零开始学习深度学习】48.Pytorch_NLP实战案例:如何使用预训练的词向量模型求近义词和类比词
|
30天前
|
机器学习/深度学习 人工智能 自然语言处理
AI技术在自然语言处理中的应用与挑战
【10月更文挑战第3天】本文将探讨AI技术在自然语言处理(NLP)领域的应用及其面临的挑战。我们将分析NLP的基本原理,介绍AI技术如何推动NLP的发展,并讨论当前的挑战和未来的趋势。通过本文,读者将了解AI技术在NLP中的重要性,以及如何利用这些技术解决实际问题。
|
2月前
|
机器学习/深度学习 数据采集 自然语言处理
深度学习在自然语言处理中的应用与挑战
本文探讨了深度学习技术在自然语言处理(NLP)领域的应用,包括机器翻译、情感分析和文本生成等方面。同时,讨论了数据质量、模型复杂性和伦理问题等挑战,并提出了未来的研究方向和解决方案。通过综合分析,本文旨在为NLP领域的研究人员和从业者提供有价值的参考。