TLearn - VocabularyProcessor 忽略部分给定词汇

TFlearn - VocabularyProcessor ignores parts of given vocabulary

我正在使用 TFlearn 的 VocabularyProcessor 将文档映射到整数数组。但是,我似乎无法用自己的词汇表初始化 VocabularyProcessor。在文档中它说我可以在创建 VocabularyProcessor 时提供一个词汇表:

vocab_processor = learn.preprocessing.VocabularyProcessor(max_document_length, vocabulary=vocab)

但是,当像这样创建 VocabularyProcessor 时,我无法正确转换我的文档。 我将词汇表作为字典提供,使用单词索引作为值:

vocab={'hello':3, '.':5, 'world':20}

句子提供如下:

sentences = ['hello summer .', 'summer is here .', ...]

VocabularyProcessor 使用给定的索引来转换文档非常重要,因为每个索引都引用特定的词嵌入。调用时

list(vocab_processor.transform(['hello world .', 'hello'])) 

输出是

[array([ 3, 20, 0]), array([3, 0, 0])]

所以句子没有根据映射“.”的提供的词汇表进行转换。到 5。 如何正确地向 VocabularyProcessor 提供词汇表?

这应该有效:

processor = learn.preprocessing.VocabularyProcessor(
    max_document_length=4, 
    vocabulary={'hello':2, 'world':20})

list(processor.transform(['world hello']))
>> [array([20,  2,  0, 0])]

注意此方法的输出形状为 (1, max_document_length)。因此最后两个零的填充。

更新:关于'.'在您的词汇表中,我认为它不被处理器中的默认标记生成器识别为标记(因此返回 0)。默认tokenizer uses a very simple Regex to do the real work (identifying tokens). See it here. To solve the problem, I guess you should provide the VocabularyProcessor with your own tokenizer by supplying the 4-th argument tokenizer_fn为其构造函数。

让我们做一些实验来回答您的问题,

vocab={'hello':3, '.':5, 'world':20, '/' : 10}
sentences= ['hello world . / hello', 'hello']

vocab_processor = learn.preprocessing.VocabularyProcessor(max_document_length=6, vocabulary=vocab)
list(vocab_processor.transform(sentences)) 

下面代码段的输出是,

[array([ 3, 20,  3,  0,  0,  0]), array([3, 0, 0, 0, 0, 0])]

现在您可能已经看到 space(' ') 和点 ('.') 实际上都没有标记化。因此,在您的代码中,tensorflow 仅识别两个单词并填充一个额外的零以使其成为 max_document_length=3。要对它们执行标记化,您可以编写自己的 tokenized function。下面给出了示例代码。

def my_func(iterator):
  return (x.split(" ") for x in iterator)

vocab={'hello':3, '.':5, 'world':20, '/' : 10}
sentences= ['hello world . / hello', 'hello']

vocab_processor = learn.preprocessing.VocabularyProcessor(max_document_length=6, vocabulary=vocab, tokenizer_fn = my_func)

list(vocab_processor.transform(sentences)) 

现在代码段的输出就像

[array([ 3, 20,  5, 10,  3,  0]), array([3, 0, 0, 0, 0, 0])]

这是预期的输出。希望这能消除您的困惑。

您的下一个困惑可能是默认情况下将标记化的值是什么。让我post在这里原文source让你永远不会混淆,

TOKENIZER_RE = re.compile(r"[A-Z]{2,}(?![a-z])|[A-Z][a-z]+(?=[A-Z])|[\'\w\-]+",
                          re.UNICODE)
def tokenizer(iterator):
  """Tokenizer generator.
  Args:
    iterator: Input iterator with strings.
  Yields:
    array of tokens per each value in the input.
  """
  for value in iterator:
    yield TOKENIZER_RE.findall(value)

但我的建议是,"write your own function and be confident"

此外,如果您错过了(希望没有),我想指出几件事。如果您使用的是 transform() 函数,您的 min_frequency 参数将不起作用,因为它不适合数据。在下面的代码中试试看效果,

for i in range(6):
    vocab_processor = learn.preprocessing.VocabularyProcessor(
        max_document_length=7, min_frequency=i)
    tokens = vocab_processor.transform(["a b c d e f","a b c d e","a b c" , "a b", "a"])
    print(list(vocab_processor.transform(sentences))[0] )

输出:

[1 2 3 4 5 6 0]
[1 2 3 4 5 6 0]
[1 2 3 4 5 6 0]
[1 2 3 4 5 6 0]
[1 2 3 4 5 6 0]
[1 2 3 4 5 6 0]

再次使用稍微相似的代码,

for i in range(6):
    vocab_processor = learn.preprocessing.VocabularyProcessor(
        max_document_length=7, min_frequency=i)
    tokens = vocab_processor.fit_transform(["a b c d e f","a b c d e","a b c" , "a b", "a"])
    print(list(tokens)[0])

输出:

[1 2 3 4 5 6 0]
[1 2 3 4 5 0 0]
[1 2 3 0 0 0 0]
[1 2 0 0 0 0 0]
[1 0 0 0 0 0 0]
[0 0 0 0 0 0 0]