文章目录
官网英文教程:https://spacy.io/usage/spacy-101#architecture
spaCy是什么?
spaCy 是一个免费的开源库,用于 Python 中的高级自然语言处理(NLP)。
如果你正在处理大量文本,你会想要了解spaCy的更多内容。例如,它是关于什么的?单词在上下文中是什么意思?谁对谁做了什么?文本中提到了哪些公司和产品?哪些文本彼此相似?
spaCy 专为生产用途而设计,可帮助您构建处理和“理解”大量文本的应用程序。它可用于构建信息提取或自然语言理解 系统,或对文本进行深度学习的预处理。
spaCy 不是什么?
- spaCy 不是一个平台或“API” 。与平台不同,spaCy 不提供软件即服务或 Web 应用程序。它是一个旨在帮助您构建 NLP 应用程序的开源库,而不是可消费的服务。
- spaCy 并不是一个开箱即用的聊天机器人引擎。虽然 spaCy 可用于支持对话应用程序,但它并非专门为聊天机器人设计的,仅提供底层文本处理功能。
- spaCy 不是研究软件。它基于最新研究,但旨在完成任务。这导致了与NLTK截然不同的设计决策或者 CoreNLP ,它们是作为教学和研究平台创建的。主要区别在于 spaCy 是集成的和有主见的。spaCy 试图避免要求用户在提供等效功能的多种算法之间进行选择。保持菜单较小可以让 spaCy 提供更好的性能和开发人员体验。
- spaCy 不是一家公司。它是一个开源库。
spaCy的功能和特性
在文档中,您会看到对 spaCy 特性和功能的提及。其中一些涉及语言概念,而另一些则与更通用的机器学习功能有关。
名称概念 | 概念解释 |
---|---|
Tokenization | 将文本分割成的单词、或者标点符号等。 |
Part-of-speech (POS) Tagging | 为tokens分配词类,如动词或名词。 |
Dependency Parsing | 分配句法依赖标签,描述各个tokens之间的关系,如主语或宾语。 |
Lemmatization | 指定单词的基本形式。例如,“was”的词干是“be”,“rats”的词干是“rat”。 |
Sentence Boundary Detection (SBD) | 查找并分割单个句子。 |
Named Entity Recognition (NER) | 标记命名的“现实世界”对象,例如人、公司或地点。 |
Entity Linking (EL) | 将文本实体消除歧义,使其成为知识库中的唯一标识符。 |
Similarity | 比较单词、文本段落和文档以及它们彼此之间的相似程度。 |
Text Classification | 为整个文档或文档的某些部分分配类别或标签。 |
Rule-based Matching | 根据文本和语言注释查找标记序列,类似于正则表达式。 |
Training | 更新和改进Statistical models的预测。 |
Serialization | 将对象保存到文件或字节字符串。 |
Statistical models 统计模型
虽然 spaCy 的某些功能可以独立运行,但其他功能则需要 加载经过训练的管道 ,使 spaCy 能够预测 语言注释——例如,一个词是动词还是名词。
训练好的管道可以由使用统计模型的多个组件组成,这些统计模型在标记数据上进行了训练。
spaCy 目前提供各种不同语言的训练管道 ,这些不同语言的训练管道可以作为单独的 Python 模块安装。
管道 软件包的大小、速度、内存使用量、准确性和它们所包含的数据可能有所不同。
您选择的包始应该取决于您的使用用例和你正在使用的文本。对于通用用例,小型默认包 始终是一个好的开始。它们通常包括以下组件:
-
二进制权重:part-of-speech tagger词性标注器、 dependency parser 依存句法分析、和 named entity recognizer命名实体识别依赖二进制权重在上下文中预测标签
-
词汇条目:词汇表中的词汇条目,即单词及其与上下文无关的属性,如形状或拼写。
-
数据文件:例如词形还原规则和查找表。
-
词向量:即单词的多维含义表示,可以让您确定它们彼此之间的相似程度。
-
配置:配置选项,例如语言和处理管道设置以及要使用的模型实现,以便在加载管道时将 spaCy 置于正确的状态。
Linguistic annotations 语言注释
spaCy 提供各种语言注释,让您深入了解文本的语法结构。
这包括词类(如词性)以及单词之间的关系。
例如,如果您正在分析文本,名词是句子的主语还是宾语,或者“google”是用作动词还是在特定语境中指代网站或公司,这会产生很大的不同。
下载并安装训练好的管道后,您可以通过spacy.load
加载它.这将返回一个 Language
对象包含处理文本所需的所有组件和数据。我们通常称之为nlp
。在文本字符串上调用nlp
对象将返回已处理好的Doc
:
import spacy
nlp = spacy.load("en_core_web_sm")
doc = nlp("Apple is looking at buying U.K. startup for $1 billion")
for token in doc:
print(token.text, token.pos_, token.dep_)
即使Doc
经过处理(例如拆分成单个单词并进行注释),它仍然保留原始文本的所有信息,例如空格字符。您始终可以获取标记在原始字符串中的偏移量,或者通过连接标记及其尾随空格来重建原始字符串。这样,您在使用 spaCy 处理文本时就不会丢失任何信息。
Tokenization 标记
在处理过程中,spaCy 首先对文本进行标记,即将其分割成单词、标点符号等。这是通过应用特定于每种语言的规则来完成的。例如,句子末尾的标点符号应该被删除掉,取而代之是保留“U.K.”这个标记。每个Doc都由单独的标记组成,我们可以对它们进行遍历:
import spacy
nlp = spacy.load("en_core_web_sm")
doc = nlp("Apple is looking at buying U.K. startup for $1 billion")
for token in doc:
print(token.text)
首先,原始文本按空格字符进行拆分,类似于 text.split(' ')
。然后,标记器从左到右处理文本。对于每个子字符串,它执行两项检查:
-
**子字符串substring 是否符合标记器例外规则?**例如,“don’t”不包含空格,但应拆分为两个标记,“do”和“n’t”,而“U.K.”应始终保留为一个标记。
-
**前缀、后缀或中缀可以拆分吗?**例如逗号、句号、连字符或引号等标点符号。
如果匹配,则应用规则,标记器继续循环,从新拆分的子字符串开始。这样,spaCy 可以拆分复杂的嵌套标记,例如缩写和多个标点符号的组合。如下图所示:
虽然标点符号规则通常很通用,但标记器例外 在很大程度上取决于个别语言的具体情况。这就是为什么每个 可用的语言有自己的子类,例如 English
或German
,加载硬编码数据和例外规则的列表。
要详细了解 spaCy 的标记化规则如何工作,如何 自定义和替换默认标记器以及如何添加特定于语言的数据,请参阅使用指南 语言数据和 定制标记器。
Part-of-speech tags and dependencies 词性标记和依赖关系
标记化后,spaCy 可以解析并标记给定的Doc
。在这里,训练好的管道及其统计模型开始发挥作用,这使得 spaCy 能够 预测哪个标签或标记最有可能适用于此上下文。经过训练的组件包括二进制数据(也称统计模型权重),这些模型是通过向系统展示足够多的示例而生成的,以便系统能够做出适用于整个语言的预测 - 例如,英语中跟在“the”后面的单词最有可能是名词。
语言注释可用作 Token属性. 与许多 NLP 库一样,spaCy 将所有字符串编码为哈希值,以减少内存使用量并提高效率。因此,为了获取属性的可读字符串表示,我们需要在其名称中添加下划线_ :
import spacy
nlp = spacy.load("en_core_web_sm")
doc = nlp("Apple is looking at buying U.K. startup for $1 billion")
for token in doc:
print(token.text, token.lemma_, token.pos_, token.tag_, token.dep_,
token.shape_, token.is_alpha, token.is_stop)
使用 spaCy 的内置displaCy 可视化工具,我们的例句及其依赖项如下所示:
词性标注和形态 Part-of-speech tagging and morphology
要了解有关词性标注和基于规则的形态学的更多信息,以及如何有效地使用解析树,请参阅使用指南 词性标注和 使用依赖项解析。
Named Entities 实体命名
命名实体是被分配了名称的“现实世界对象”,例如,一个人、一个国家、一个产品或一本书名。spaCy 可以通过要求模型进行预测来识别文档中各种类型的命名实体。由于模型是统计性的,并且很大程度上依赖于它们所训练的示例,因此这并不总是完美无缺的,并且可能需要根据您的用例进行一些调整。
命名实体是Doc
的ents
属性:
import spacy
nlp = spacy.load("en_core_web_sm")
doc = nlp("Apple is looking at buying U.K. startup for $1 billion")
for ent in doc.ents:
print(ent.text, ent.start_char, ent.end_char, ent.label_)
使用 spaCy 的内置displaCy 可视化工具,我们的例句及其命名实体如下所示:
Named Entity Recognition 命名实体识别
要了解有关 spaCy 中的实体识别的更多信息,如何将自己的实体添加到文档以及如何训练和更新实体预测 有关模型的详细信息,请参阅 命名实体识别和 训练管道。
Word vectors and similarity 词向量和相似度
相似度是通过比较词向量或词嵌入来确定的, 单词的多维含义表示。词向量可以是使用 word2vec类似算法生成的,词嵌入通常看起来像这样:
array([2.02280000e-01, -7.66180009e-02, 3.70319992e-01,
3.28450017e-02, -4.19569999e-01, 7.20689967e-02,
-3.74760002e-01, 5.74599989e-02, -1.24009997e-02,
5.29489994e-01, -5.23800015e-01, -1.97710007e-01,
-3.41470003e-01, 5.33169985e-01, -2.53309999e-02,
1.73800007e-01, 1.67720005e-01, 8.39839995e-01,
5.51070012e-02, 1.05470002e-01, 3.78719985e-01,
2.42750004e-01, 1.47449998e-02, 5.59509993e-01,
1.25210002e-01, -6.75960004e-01, 3.58420014e-01,
# ... and so on ...
3.66849989e-01, 2.52470002e-03, -6.40089989e-01,
-2.97650009e-01, 7.89430022e-01, 3.31680000e-01,
-1.19659996e+00, -4.71559986e-02, 5.31750023e-01], dtype=float32)
【重要提示】
为了使它们紧凑而快速,spaCy 的小型管道包(所有以sm结尾的包)不附带词向量,只包含上下文敏感的张量。这意味着你仍然可以使用similarity()
方法来比较文档、跨度和标记——但结果不会像 很好,并且单个标记不会分配任何向量。因此,为了使用 真实的词向量,你需要下载更大的管道包:
- python -m spacy download en_core_web_sm
+ python -m spacy download en_core_web_lg
一些自然语言处理的流水线(pipeline)包自带了预训练的词向量。这些词向量可以通过每个Token对象的.vector属性直接访问到。这里,“Token”指的是句子中的单个词语或符号。
对于整个文档(Doc)或者文档中的一部分(Span),它们的向量(.vector)默认是通过计算其包含的所有Token向量的平均值得出的。这意味着,如果你需要获取一个段落或整个文档的向量表示,它会自动为你计算所有单词向量的平均值作为该段落或文档的向量
你可以检查某个Token是否已经被分配了一个向量(即是否有对应的词向量)。此外,你还可以获取该向量的L2范数(Euclidean范数),这可以用于向量的归一化。L2范数是向量各元素平方和的平方根,常用来衡量向量的长度。归一化是指将向量转换为单位长度的过程,这在比较不同长度的向量时非常有用
import spacy
nlp = spacy.load("en_core_web_md")
tokens = nlp("dog cat banana afskfsd")
for token in tokens:
print(token.text, token.has_vector, token.vector_norm, token.is_oov)
“dog”、“cat”和“banana”这些词在英语中都很常见,它们是管道词汇的一部分,并带有一个向量。但是,“afskfsd”这个词不太常见,也不在词汇表中——所以它的向量表示由 300 个0维度组成,这意味着它实际上不存在。如果你的应用程序需要一个大的词汇表, 更多的向量,你应该考虑使用一个更大的管道包或 在完整的矢量包中加载,例如, en_core_web_lg
,其中包括685000 个词向量。
spaCy 能够比较两个对象,并预测它们的相似程度。预测相似度对于构建推荐系统或标记重复项非常有用。例如,您可以向用户推荐与他们当前正在查看的内容相似的内容,或者如果支持工单与现有工单非常相似,则将其标记为重复。
每个Doc
、 Span
、 Token
和 Lexeme
带有.similarity 可以让你将其与另一个对象进行比较的方法,并确定 相似性。当然,相似性总是主观的——无论是两个单词,段落 或文档是否相似实际上取决于你如何看待它。spaCy 的 相似性实现通常假设一个非常通用的定义 相似。
import spacy
nlp = spacy.load("en_core_web_md") # make sure to use larger package!
doc1 = nlp("I like salty fries and hamburgers.")
doc2 = nlp("Fast food tastes very good.")
# Similarity of two documents
print(doc1, "<->", doc2, doc1.similarity(doc2))
# Similarity of tokens and spans
french_fries = doc1[2:4]
burgers = doc1[5]
print(french_fries, "<->", burgers, french_fries.similarity(burgers))
如何理解相似度
计算相似度得分在许多情况下都很有帮助,但对它能提供什么信息保持现实的期望也很重要。单词之间可以以多种方式相互关联,因此单个“相似度”得分始终是不同信号的混合,而用不同数据训练的向量可能会产生非常不同的结果,这可能对您的目的没有用处。以下是一些需要牢记的重要注意事项:
-
相似性没有客观定义。“我喜欢汉堡”和“我喜欢意大利面”是否相似取决于你的应用。两者都谈论食物偏好,这使得它们非常相似 - 但如果你分析提到食物的地方,这些句子就非常不同了,因为它们谈论的是完全不同的食物。
-
Doc的相似性和Span对象默认为标记向量的平均值。这意味着“fast food”的向量是“fast”和“food”向量的平均值,这不一定代表短语“fast food”。
你提到的向量平均(vector averaging)确实揭示了这种方法的一个关键局限性。让我们详细解释一下这段话的意义及其背后的原理:
- 向量平均:在自然语言处理中,当我们计算一个文档或段落的向量表示时,常用的方法是对其中所有词向量进行平均。这意味着最终得到的文档向量是各个单词向量的算术平均值。
向量平均的局限性
-
对词序不敏感:
- 问题描述:向量平均方法忽略了词序信息。例如,“狗咬人”和“人咬狗”这两个句子,虽然表达了完全不同的意思,但在向量平均后可能得到非常相似的文档向量。
- 原因分析:因为这两个句子包含相同的单词,只是顺序不同,而向量平均会将这些单词的向量相加并除以单词数量,导致结果相似。
-
语义相似但用词不同的文档:
- 问题描述:如果两个文档表达相同的意思但使用不同的词汇,它们的相似度得分可能会较低。例如,“猫喜欢玩毛线球”和“猫咪爱追逐绒线团”,尽管表达的是同一个意思,但由于使用的具体词汇不同,其向量平均后的结果可能差异较大。
- 原因分析:每个词都有自己的向量表示,即使它们在语义上相近,但具体的数值表示可能差别很大,导致最终的文档向量也有显著差异。
-
语义不同但用词相同的文档:
- 问题描述:相反,如果两个文档恰好包含了相同的词语但表达的意思不同,它们可能会有较高的相似度得分。例如,“他不喜欢苹果”和“他喜欢吃苹果”,虽然都提到了“苹果”,但意义完全不同。
- 原因分析:由于向量平均只考虑了词语本身的向量,没有考虑到词语之间的组合关系和上下文,因此无法准确区分这种情况下语义的不同。
Word vectors
要了解有关词向量的更多信息、如何自定义它们以及如何加载 将你自己的向量导入 spaCy,请参阅使用指南 使用词向量和语义相似性。
Pipelines 管道
当你在文本上调用nlp
时,spaCy 首先对文本进行标记以生成Doc
对象。然后, Doc
会通过几个不同的步骤进行处理 - 这也称为处理管道。 训练好的管道通常包括标记器、词形还原器、解析器和实体识别器。每个管道组件都会返回处理后的Doc
,然后将其传递给下一个组件。
处理管道的功能始终取决于组件、其模型以及训练方式。例如,命名实体识别管道需要包含经过训练的命名实体识别器组件,该组件具有统计模型和权重,使其能够预测实体标签。这就是为什么每个管道都在配置中指定其组件及其设置的原因:
[nlp]
pipeline = ["tok2vec", "tagger", "parser", "ner"]
流水线(pipeline)中各组件的顺序是否重要?
- 统计组件(如词性标注器tagger或句法分析器parser)通常是独立的,它们之间不会共享任何数据。这意味着这些组件各自处理文本的不同方面,互不干扰。例如,命名实体识别器(NER)不会使用由词性标注器和句法分析器设置的特征。也就是说,NER独立于其他统计组件运行,不需要它们提供的信息。这意味着你可以交换这些组件的位置,或者从流水线中移除某个组件而不影响其他组件的工作。因为它们是独立的,所以调整它们的顺序或删除其中一些不会影响其他组件的功能。
- 然而,有些组件可能会共享一个“词到向量”的组件,比如Tok2Vec或Transformer。这意味着某些组件可能依赖于同一个将词汇转换为向量表示的基础模块。
- 自定义组件也可能依赖于其他组件设置的注释(annotations)。例如,自定义的词形还原器(lemmatizer)可能需要词性标签(POS tags),因此它必须在词性标注器之后添加到流水线中。举例来说,自定义的词形还原器需要已经分配好的词性标签才能工作,因此它必须在词性标注器之后被添加到流水线中。
- 句法分析器会尊重预定义的句子边界。如果流水线中的前一个组件设置了这些边界,那么句法分析器生成的依存关系预测可能会有所不同。类似地,将EntityRuler(基于规则的实体识别器)添加到统计实体识别器之前还是之后会影响结果。如果EntityRuler在统计实体识别器之前被添加,那么统计实体识别器在做预测时会考虑已有的实体。
- EntityLinker(将命名实体解析为知识库ID的组件)应该放在能够识别实体的组件(如EntityRecognizer)之后。这是因为EntityLinker需要先有实体识别的结果,然后才能将这些实体链接到知识库中的相应ID。
顺序是否重要的总结:
- 统计组件通常是独立工作的,但某些组件可能共享基础的词向量转换模块。
自定义组件可能依赖于其他组件生成的注释,因此组件的顺序在这种情况下非常重要。
对于特定任务(如实体识别、依存关系解析等),组件的顺序会影响最终的结果和准确性。
标记器tokenizer是一个“特殊”组件,不是常规管道的一部分。它也不会出现在nlp.pipe_names
中。原因是实际上只能有一个标记器,而所有其他管道组件都采用Doc
并返回它,标记器获取一串文本并将其转换为 Doc
。不过,你仍然可以自定义nlp.tokenizer
,因此你可以创建自己的 从头开始创建Tokenizer类, 或者甚至用 完全定制的功能。
处理管道
要详细了解处理管道的工作原理、如何启用和禁用其组件以及如何创建自己的处理管道,请参阅语言处理管道的使用指南。
Architecture 架构
理解SpaCy的工作原理和核心数据结构:
-
核心数据结构:
- Language 类:这是处理文本的主要类。它通常作为一个名为
nlp
的变量存储,并用于将文本转换为Doc
对象。 - Vocab 对象:集中管理字符串、词向量和词汇属性,避免重复存储相同的数据,从而节省内存并确保单一数据源的真实性和一致性。
- Doc 对象:包含文本的所有信息和注释。它是通过Tokenizer构造的,并在语言处理管道中被各个组件就地修改。
- Language 类:这是处理文本的主要类。它通常作为一个名为
-
工作流程:
- 当你有一个原始文本时,首先使用
Language
(即nlp
对象)中的Tokenizer将其转换为一个Doc
对象。 - 然后,这个
Doc
对象会通过一系列预定义的处理组件(例如分词器、标注器等),这些组件对文档进行各种自然语言处理任务,并在过程中修改Doc
对象。 Language
对象协调这些组件的操作,确保文本经过整个处理管道,最终返回一个带有注释的文档。
- 当你有一个原始文本时,首先使用
-
设计特点:
- 通过让
Doc
对象拥有所有数据,而Span
和Token
作为指向Doc
数据的视图,SpaCy的设计允许了一个单一真实来源的数据管理方式。 - 这种设计不仅优化了内存使用,还保证了在整个处理过程中数据的一致性和准确性。
- 通过让
SpaCy通过其核心数据结构Language
、Vocab
和Doc
有效地管理和处理文本,使得用户可以轻松执行复杂的自然语言处理任务,同时保持高效和一致的数据处理流程。
Container objects 容器对象
处理中的管道
处理管道由一个或多个管道组件组成,这些组件按顺序在Doc
上调用。标记器在组件之前运行。可以使用Language.add_pipe
添加管道组件。它们可以包含统计模型和训练权重,或者仅对Doc
进行基于规则的修改。spaCy 提供了一系列内置 用于不同语言处理任务的组件,还允许添加 定制 组件。
Matchers 匹配器
匹配器可帮助您从Doc中查找和提取信息根据匹配模式查找对象,描述您要查找的序列。匹配器对Doc进行操作,并允许您访问上下文中匹配的标记。
Other classes 其它类
Vocab, hashes and lexemes 词汇、哈希和词素
只要有可能,spaCy 都会尝试将数据存储在一个词汇表(称为 Vocab)中,这个词汇表可以被多个文档共享。spaCy 使用一个共享的词汇表(Vocab)来存储所有文档中出现过的单词、字符或其他符号。这种设计可以节省内存,因为相同的单词在不同文档中只需要存储一次,而不是每个文档都存储一份独立的副本。
为了节省内存,spaCy 还会将所有字符串编码为哈希值——例如,在这种情况下,“coffee” 的哈希值是 3197928453018144401。为了避免直接存储和处理字符串(字符串可能占用较多内存),spaCy 使用哈希函数将字符串转换为固定长度的数字(哈希值)。这样,单词“coffee”在程序中就以数字 3197928453018144401 的形式存在,而不是以字符串的形式。哈希值是唯一的,且占用内存更少。
像“ORG”这样的实体标签和像“VERB”这样的词性标签也会被编码。除了单词本身,spaCy 还会对实体标签(如“ORG”表示组织)和词性标签(如“VERB”表示动词)进行编码。这些标签通常也是字符串,spaCy 会将它们转换为哈希值以节省内存。
在 spaCy 的内部处理过程中,所有的单词、标签等信息都以哈希值的形式存在和操作,而不是以字符串的形式。这种设计提高了程序的运行效率并减少了内存占用。
如果你处理大量包含"coffee”一词的文档,这些文档有各种各样的 不同的上下文,每次存储精确的字符串“coffee”将占用 占用太多空间。因此,spaCy 会散列字符串并将其存储在 StringStore
. 你可以将StringStore视为 双向查找表——您可以查找字符串来获取其哈希值,或者查找哈希值来获取其字符串:
import spacy
nlp = spacy.load("en_core_web_sm")
doc = nlp("I love coffee")
print(doc.vocab.strings["coffee"]) # 3197928453018144401
print(doc.vocab.strings[3197928453018144401]) # 'coffee'
现在所有字符串都已编码,词汇表中的条目无需包含单词文本本身。相反,它们可以在 StringStore通过其哈希值进行存储。词汇表中的每个条目也称为 Lexeme ,只包含单词本身,不会包含上下文信息。例如,无论“love”在某个上下文中是用作动词还是名词,它的拼写以及是否由字母组成都不会改变。它的哈希值也始终相同。
import spacy
nlp = spacy.load("en_core_web_sm")
doc = nlp("I love coffee")
for word in doc:
lexeme = doc.vocab[word.text]
print(lexeme.text, lexeme.orth, lexeme.shape_, lexeme.prefix_, lexeme.suffix_,
lexeme.is_alpha, lexeme.is_digit, lexeme.is_title, lexeme.lang_)
单词到哈希的映射不依赖于任何状态。为了确保每个 值是唯一的,spaCy 使用 hash 函数根据字符串计算哈希值。这也意味着“coffee”的哈希值始终相同,无论您使用哪个管道或如何配置 spaCy。
然而,哈希值无法逆转,也没有办法解决 3197928453018144401返回“coffee”。spaCy 所能做的就是在词汇表中查找。这就是为什么你总是需要确保你创建的所有对象都可以访问相同的词汇表。如果没有,spaCy 可能无法找到它需要的字符串。
import spacy
from spacy.tokens import Doc
from spacy.vocab import Vocab
nlp = spacy.load("en_core_web_sm")
doc = nlp("I love coffee") # Original Doc
print(doc.vocab.strings["coffee"]) # 3197928453018144401
print(doc.vocab.strings[3197928453018144401]) # 'coffee' 👍
empty_doc = Doc(Vocab()) # New Doc with empty Vocab
# empty_doc.vocab.strings[3197928453018144401] will raise an error :(
empty_doc.vocab.strings.add("coffee") # Add "coffee" and generate hash
print(empty_doc.vocab.strings[3197928453018144401]) # 'coffee' 👍
new_doc = Doc(doc.vocab) # Create new doc with first doc's vocab
print(new_doc.vocab.strings[3197928453018144401]) # 'coffee' 👍
如果词汇表中不包含3197928453018144401的字符串,spaCy 将引发错误。您可以手动重新添加“coffee”,但这只有在您确实知道文档包含该单词时才有效。为了防止出现此问题,spaCy 还会在您保存Doc或nlp对象时导出Vocab 。这将为您提供对象及其编码注释,以及解码它的“密钥”。
Serialization 序列化
如果您一直在修改管道、词汇表、向量和实体,或者对组件模型进行了更新,那么您最终会想要保存进度——例如, nlp对象中的所有内容。这意味着您必须将其内容和结构转换为可以保存的格式,例如文件或字节字符串。此过程称为序列化。spaCy 带有内置序列化方法,并支持 Pickle 协议。
所有容器类,即Language ( nlp ), Doc 、 Vocab和StringStore 有以下方法可用:
保存和加载
要了解有关如何保存和加载您自己的管道的更多信息,请参阅保存和加载的使用指南。
Training 训练
spaCy 的标记器tagger、解析器parser、文本分类器text categorizer和许多其他组件均由统计模型提供支持。这些组件做出的每一个“决定”——例如, 分配哪个词性标记,或者一个词是否是一个命名实体——是一个 根据模型的当前权重值进行预测。权重值是根据模型在训练期间看到的示例估计的。要训练模型,首先需要训练数据 - 文本示例,以及您希望模型预测的标签。这可以是词性标记、命名实体或任何其他信息。
训练是一个迭代过程,其中将模型的预测与参考注释进行比较,以估计损失的梯度。然后使用损失的梯度通过反向传播计算权重的梯度。梯度指示权重值如何改变,以便模型的预测随着时间的推移变得更加类似于参考标签。
在训练模型时,我们不希望它只记住我们的例子——我们希望它提出一个可以推广到看不见的数据的理论。毕竟,我们不希望模型只知道这里的“亚马逊”这一个实例是一家公司——我们希望它知道,“亚马逊”在这样的语境中很可能是一家公司。这就是为什么训练数据应该始终代表我们想要处理的数据。在维基百科上训练的模型,其中第一人称的句子极其罕见,在推特上的表现很可能很差。同样,用浪漫小说训练的模型在法律文本上的表现很可能很差。
这也意味着,为了了解模型的表现如何,以及它是否在学习正确的东西,你不仅需要训练数据,还需要评估数据。如果你只用训练数据来测试模型,你就无法知道它的泛化能力有多强。如果你想从头开始训练一个模型,你通常至少需要几百个样本来进行训练和评估。
Training pipelines and models
要了解有关训练和更新管道的更多信息,以及如何创建训练 数据以及如何改进 spaCy 的命名模型,请参阅使用指南 训练。
Training config and lifecycle 训练配置和训练生命周期
训练配置文件包含训练管道所需的所有设置和超参数。您无需在命令行上提供大量参数,只需将config.cfg文件传递给spacy train 。这也使得集成使用您选择的框架编写的自定义模型和架构变得容易。管道的config.cfg被视为“单一事实来源”,无论是在训练时还是在运行时。
Training configuration system
有关 spaCy配置系统的更多详细信息以及如何使用它来自定义管道组件、组件模型、训练设置和超参数,请参阅训练配置使用指南。
Trainable components 可训练的组件
spaCy 的Pipe类可帮助你实现自己的可训练组件,这些组件具有自己的模型实例,可以对Doc进行预测 对象,可以使用spacy train进行更新.这使您可以将完全自定义的机器学习组件插入到可以通过单个训练配置进行配置的管道中。
Custom trainable components
要了解如何实现自己的模型架构并使用它们来支持自定义可训练组件,请参阅 可训练组件 API以及实现层和架构 对于可训练的组件。
Language data 语言数据
每种语言都是不同的——通常充满了例外和特殊情况,尤其是在最常用的单词中。其中一些例外是跨语言共享的,而另一些则完全是特定的——通常如此 具体来说,它们需要硬编码。 lang
模块包含所有特定于语言的数据,以简单的 Python 文件形式组织。这使得数据易于更新和扩展。
目录根目录中的共享语言数据包括可跨语言通用的规则,例如基本标点符号、表情符号、表情符号和单字母缩写的规则。 子模块包含仅与特定语言相关的规则。它 还负责组装所有组件并创建 Language
子类 – 例如, English
或German
。这些值在Language.Defaults中定义。