spacy v3 en_core_web_trf 管道和 en_core_web_lg 管道之间的区别

ryk*_*ryk 10 python spacy spacy-transformers spacy-3

我正在使用 spacy 版本 3 进行一些性能测试,以便在生产中调整实例的大小。我正在观察以下情况

观察:

型号名称 没有 NER 的时间 与 NER 共度时光 评论
en_core_web_lg 4.89秒 21.9秒 NER在原来的基础上增加了350%
en_core_web_trf 43.64秒 52.83秒 NER 只比原来的时间增加了 20%

为什么在使用 Transformer 模型的情况下,使用 NER不使用 NER 的情况没有显着差异?在 en_core_web_trf 的情况下,NER 是否只是 POS 标记之后的增量任务?

测试环境: GPU实例

测试代码:

import spacy

assert(spacy.__version__ == '3.0.3')
spacy.require_gpu()
texts = load_sample_texts()  # loads 10,000 texts from a file
assert(len(texts) == 10000)

def get_execution_time(nlp, texts, N):
    return timeit.timeit(stmt="[nlp(text) for text in texts]", 
                           globals={'nlp': nlp, 'texts': texts}, number=N) / N


#  load models
nlp_lg_pos = spacy.load('en_core_web_lg', disable=['ner', 'parser'])
nlp_lg_all = spacy.load('en_core_web_lg')
nlp_trf_pos = spacy.load('en_core_web_trf', disable=['ner', 'parser'])
nlp_trf_all = spacy.load('en_core_web_trf')

#  get execution time
print(f'nlp_lg_pos = {get_execution_time(nlp_lg_pos, texts, N=1)}')
print(f'nlp_lg_all = {get_execution_time(nlp_lg_all, texts, N=1)}')
print(f'nlp_trf_pos = {get_execution_time(nlp_trf_pos, texts, N=1)}')
print(f'nlp_trf_all = {get_execution_time(nlp_trf_all, texts, N=1)}')
Run Code Online (Sandbox Code Playgroud)

Ian*_*son 1

虽然不是专家,但我认为这可能是由于管道的设计造成的。

\n

训练有素的管道设计

\n

模型的文档sm/md/lg指出:

\n
\n

ner组件是独立的,有自己的内部 tok2vec 层。\nsm/md/lg管道设计

\n
\n

该模型的文档trf指出:

\n
\n

在变压器 ( trf) 模型中,taggerparserner(如果存在)都侦听该transformer组件。

\n
\n

共享嵌入层

\n
\n

在组件之间重用 tok2vec 层可以使管道运行得更快,并产生更小的模型。但是,它可能会降低管道的模块化程度,并使交换组件或重新训练管道的某些部分变得更加困难。\n共享与独立

\n
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
共享独立的
\xe2\x9c\x85更小:模型只需要包含嵌入的单个副本\xe2\x9d\x8c较大:模型需要包含每个组件的嵌入
\xe2\x9c\x85更快:为整个管道嵌入文档一次\xe2\x9d\x8c较慢:重新运行每个组件的嵌入
\xe2\x9d\x8c可组合性较差:所有组件都需要在管道中使用相同的嵌入组件\xe2\x9c\x85模块化:组件可以自由移动和交换
\n

实验

\n
    \n
  • 注 1:我正在使用20 个新闻组文本数据集,并且没有 GPU,因此时间可能会有所不同,但结果指向相同的总体方向。

    \n
  • \n
  • 注2:我正在使用:

    \n
      \n
    • spacy3.5.4
    • \n
    • en_core_web_lg3.5.0
    • \n
    • en_core_web_trf3.5.0
    • \n
    • scikit-learn1.3.0
    • \n
    • Python3.11.4.
    • \n
    \n
  • \n
\n
"""Replicating code as much as possible."""\n\nimport timeit\n\nfrom sklearn.datasets import fetch_20newsgroups\nimport spacy  # 3.5.4\n\n\n# spacy.require_gpu()  # I don\'t have a GPU available\nbunch = fetch_20newsgroups(random_state=0)\ntexts = bunch.data\n\ndef get_execution_time(nlp, texts, N):\n    return timeit.timeit(\n        stmt="[nlp(text) for text in texts]",\n        globals={\'nlp\': nlp, \'texts\': texts},\n        number=N\n    ) / N\n\n#  load models\nnlp_lg_pos = spacy.load(\'en_core_web_lg\', disable=[\'ner\', \'parser\'])\nnlp_lg_all = spacy.load(\'en_core_web_lg\')\nnlp_trf_pos = spacy.load(\'en_core_web_trf\', disable=[\'ner\', \'parser\'])\nnlp_trf_all = spacy.load(\'en_core_web_trf\')\n\n#  get execution time\nprint(f\'nlp_lg_pos = {get_execution_time(nlp_lg_pos, texts, N=1)}\')\nprint(f\'nlp_lg_all = {get_execution_time(nlp_lg_all, texts, N=1)}\')\nprint(f\'nlp_trf_pos = {get_execution_time(nlp_trf_pos, texts, N=1)}\')\nprint(f\'nlp_trf_all = {get_execution_time(nlp_trf_all, texts, N=1)}\')\n
Run Code Online (Sandbox Code Playgroud)\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
型号名称没有 NER 或解析器的时间使用 NER 和解析器的时间评论
en_core_web_lg8.48秒13.98秒NER 和 Parser 比原始时间增加 65%
en_core_web_trf387.67秒382.84秒NER 和 Parser 减少了 1% 的时间(可以忽略不计)
\n
\n

修改现有组件并使其在不重新训练的情况下监听共享tok2vectransformer层是很困难的。因此,我将用变压器层自己的副本替换 和 组件侦听en_core_web_trf nerparser如果文档正确,这应该会导致“Time with (Independent) NER and (Independent) Parser”结果比之前的结果慢得多en_core_web_trf

\n
nlp_trf_all_independent = spacy.load(\'en_core_web_trf\')\n\n# make `ner` and `parser` components independent\nnlp_trf_all_independent.replace_listeners("transformer", "ner", ["model.tok2vec"])\nnlp_trf_all_independent.replace_listeners("transformer", "parser", ["model.tok2vec"])\n\nprint(f\'nlp_trf_all_independent = {get_execution_time(nlp_trf_all_independent, texts, N=1)}\')\n
Run Code Online (Sandbox Code Playgroud)\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
型号名称没有 NER 或解析器的时间使用(独立)NER 和(独立)解析器的时间评论
en_core_web_trf387.67秒1125.31 秒(独立)NER和(独立)解析器在原始时间上加上190%
\n
\n

正如您所看到的,使组件独立,即不共享/监听tok2vec/transformer层,会导致更慢(但更模块化)的管道。en_core_web_lg我相信这就是当您添加组件时模型明显变慢的原因,ner因为默认情况下它是独立的。

\n