【问题标题】:Using annoy with Torchtext for nearest neighbor search使用带 Torchtext 的 annoy 进行最近邻搜索
【发布时间】:2023-03-25 04:50:01
【问题描述】:

我将 Torchtext 用于一些 NLP 任务,特别是使用内置嵌入。

我希望能够进行逆向量搜索:生成噪声向量,找到最接近它的向量,然后取回与噪声向量“最接近”的词。

来自torchtext docs,以下是如何将嵌入附加到内置数据集:

from torchtext.vocab import GloVe
from torchtext import data

embedding = GloVe(name='6B', dim=100)

# Set up fields
TEXT = data.Field(lower=True, include_lengths=True, batch_first=True)
LABEL = data.Field(sequential=False, is_target=True)

# make splits for data
train, test = datasets.IMDB.splits(TEXT, LABEL)

# build the vocabulary
TEXT.build_vocab(train, vectors=embedding, max_size=100000)
LABEL.build_vocab(train)

# Get an example vector
embedding.get_vecs_by_tokens("germany")

然后我们就可以建立烦恼指数了:

from annoy import AnnoyIndex

num_trees = 50

ann_index = AnnoyIndex(embedding_dims, 'angular')

# Iterate through each vector in the embedding and add it to the index
for vector_num, vector in enumerate(TEXT.vocab.vectors):
    ann_index.add_item(vector_num, vector) # Here's the catch: will vector_num correspond to torchtext.vocab.Vocab.itos?

ann_index.build(num_trees)

然后说我想用嘈杂的向量检索一个词:

# Get an existing vector
original_vec = embedding.get_vecs_by_tokens("germany")
# Add some noise to it
noise = generate_noise_vector(ndims=100)
noisy_vector = original_vec + noise
# Get the vector closest to the noisy vector
closest_item_idx = ann_index.get_nns_by_vector(noisy_vector, 1)[0]
# Get word from noisy item
noisy_word = TEXT.vocab.itos[closest_item_idx]

我的问题出现在上面的最后两行:ann_index 是在 embedding 对象上使用 enumerate 构建的,这是一个 Torch 张量。

[vocab][2] 对象有自己的itos 列表,给定索引会返回一个单词。

我的问题是:我可以确定单词出现在 itos 列表中的顺序与TEXT.vocab.vectors 中的顺序相同吗?如何将一个索引映射到另一个索引?

【问题讨论】:

    标签: nlp pytorch nearest-neighbor torchtext annoy


    【解决方案1】:

    我可以确定单词在itos 列表中出现的顺序与TEXT.vocab.vectors 中的顺序相同吗?

    是的。

    Field 类将始终实例化 Vocab 对象 (source),并且由于您将预训练的向量传递给 TEXT.build_vocab,因此 Vocab 构造函数将 call load_vectors功能。

    if vectors is not None:
        self.load_vectors(vectors, unk_init=unk_init, cache=vectors_cache)
    

    load_vectors 中,通过枚举itos 中的单词,vectorsfilled

    for i, token in enumerate(self.itos):
        start_dim = 0
        for v in vectors:
            end_dim = start_dim + v.dim
            self.vectors[i][start_dim:end_dim] = v[token.strip()]
            start_dim = end_dim
        assert(start_dim == tot_dim)
    

    因此,您可以确定itosvectors 将具有相同的顺序。

    【讨论】:

    • 感谢您链接代码。我做了一些自我检讨,似乎确实如此。我会接受这是正确的。不过我还是觉得恶心,应该有一个函数可以从 TEXT.vocab 对象中获取向量。
    猜你喜欢
    • 1970-01-01
    • 2015-03-18
    • 1970-01-01
    • 2011-05-14
    • 2016-06-23
    • 1970-01-01
    • 2018-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多