Nlp Spacy的Torch使用--带有标准数据集的奇怪错误

Nlp Spacy的Torch使用--带有标准数据集的奇怪错误,nlp,pytorch,spacy,Nlp,Pytorch,Spacy,在以下代码中: from torchtext.datasets import Multi30k from torchtext.data import Field, BucketIterator import spacy from spacy.tokenizer import Tokenizer nlp = spacy.load("en_core_web_sm") tokenizer = Tokenizer(nlp.vocab) SRC = Field(tokenize = tokenize

在以下代码中:

from torchtext.datasets import Multi30k
from torchtext.data import Field, BucketIterator
import spacy
from spacy.tokenizer import Tokenizer

nlp = spacy.load("en_core_web_sm")
tokenizer = Tokenizer(nlp.vocab)


SRC = Field(tokenize = tokenizer,
            init_token = '<sos>',
            eos_token = '<eos>',
            lower = True)

TRG = SRC

train_data, valid_data, test_data = Multi30k.splits(exts = ('.en', '.en'), fields = (SRC, TRG), root='.')
使用调试器,我发现错误发生在Torch文件“pipeline.py”的类字段(RawField)的以下行(classmethod preprocess(x)中

if self.lower:
   x = Pipeline(six.text_type.lower)(x)
其中arg'x'的类型确实是spacy.tokens.doc.doc。但是,令我惊讶的是,当我向上移动堆栈一步时,我发现调用预处理(x)的行是这样的--

但在这种情况下,“val”的类型是“str”,这是与“lower”一起使用所必需的(!!??)

我的代码是一个完全标准的用例,那么我遗漏了什么呢

相反,如果我使用'lower'=False,代码运行时不会出错,生成的Train/Test/Val数据是正确的(Train_数据生成29000对)。但是,如果--

我得到的vocab只有4项,即:

Vocab stoi:
 [('<unk>', 0), ('<pad>', 1), ('<sos>', 2), ('<eos>', 3)]
但很明显,spacy模型已经下载,因为我能够将相应的标记器函数传递给同一个关键字arg(我也通过调试器检查了这一点——标记器被传递进来)

我真的很想知道发生了什么

(我已经将SRC=TRG设置为简化,但是如果我使用语言对,我会得到相同的行为,例如SRC=en,TRG=de)

找到了我问题的答案:

在代码中--

返回的“标记器”是一个返回spacy“Doc”对象的函数。字段的Torch构造函数需要一个返回字符串列表的函数。将以下内容添加到上述内容中--

并将其作为'tokenize'关键字的值传递,如下所示--

SRC=Field(tokenize=spacy\u tokenize,
标记器_language=“en”,
初始令牌=“”,
eos_标记=“”,
下限=真)
解决了这个问题

但是,我仍然无法使用字符串'spacy'作为'tokenizer'的值,因为这依赖于一个符号链接,该符号链接将'en'设置为对模型“en_core_web_sm”的引用。我确定我有权设置符号链接,模型安装很高兴地宣布它已经设置了链接,可以使用spacy.load('en'),但是 Torch字段ctor仍然抛出“OSError:[E050]找不到模型‘en’。它似乎不是快捷链接、Python包或数据目录的有效路径。”

setattr(ex, name, field.preprocess(val))
SRC.build_vocab(train_data, min_freq = 2)
Vocab stoi:
 [('<unk>', 0), ('<pad>', 1), ('<sos>', 2), ('<eos>', 3)]
"OSError: [E050] Can't find model 'en'. It doesn't seem to be a shortcut link, a Python package or a valid path to a data directory."
from spacy.tokenizer import Tokenizer

nlp = spacy.load("en_core_web_sm")
tokenizer = Tokenizer(nlp.vocab)
def spacy_tokenize(x):
    return [tok.text for tok in tokenizer(x)]
SRC = Field(tokenize = spacy_tokenize,
            tokenizer_language="en",
            init_token = '<sos>',
            eos_token = '<eos>',
            lower = True)