单个词的BERT嵌入表示什么?

fkvaft9z  于 4个月前  发布在  其他
关注(0)|答案(3)|浏览(47)

我一直在使用预训练的bert-base-uncased的bert嵌入来进行各种下游任务。
当我试图理解它是如何具有上下文性的,以及一个句子中的其他标记如何影响每个标记的意义或上下文时,学习过程是相当清晰的。
但是当我把它看作是一个单独的标记(一个单一标记的句子)时,就会产生一些问题,比如“当模型独立地看待它时,它真正学到了什么”。
我一直在测试它,结果相当误导人。
我不想为相同的任务使用不同的技术,但在不同的粒度级别(即单个词、n-grams、句子)
编码更像是一种杀戮而不是编程。
有人能帮我理解这种差异吗?这是意料之中的吗?
@jacobdevlin-google@hsm207

pbpqsu0x

pbpqsu0x1#

这真的很有趣!

你正在使用的库是用来进行分析的吗?我不熟悉你所调用的任何功能。

我有一些想法:

  1. 对于其他查询的结果如何?它们大多数时候是有意义的,还是像“编码”一样奇怪?
  2. “编码”的嵌入是与CLS、SEP或“编码”令牌相对应的嵌入吗?当查询被分词成多个子词时,例如稻草、##莓果,你是如何处理这种情况的?
tzdcorbm

tzdcorbm2#

这个真的很有趣!
你正在使用的库进行分析吗?我不熟悉你调用的任何功能。
我有一些想法:

  1. 其他查询的结果如何?它们大多数时候是有意义的,还是像“编码”一样奇怪?
  2. “编码”的嵌入是与CLS、SEP或“编码”令牌相对应的嵌入吗?当查询被分词成多个子词时,例如稻草、##莓果,你是如何处理这种情况的?
    @hsm207 我正在使用HuggingFace的预训练BERT模型。
def get_embeddings_concat_last_4(doc):
    indexed_tokens = tokenizer.convert_tokens_to_ids(doc)
    segments_ids = [1] * len(doc)

    tokens_tensor = torch.tensor([indexed_tokens])
    segments_tensors = torch.tensor([segments_ids])

    with torch.no_grad():
        encoded_layers, _ = model(tokens_tensor, segments_tensors)  

        token_embeddings = torch.stack(encoded_layers, dim=0)
        token_embeddings = torch.squeeze(token_embeddings, dim=1)
        token_embeddings = token_embeddings.permute(1,0,2)

    token_vecs_cat = []
    for token in token_embeddings:
        cat_vec = torch.cat((token[-1], token[-2], token[-3], token[-4]), dim=0)
        token_vecs_cat.append(cat_vec)
    return token_vecs_cat

我正在进行词级别匹配。当整个句子作为输入传递给模型时,生成令牌嵌入。

  1. 对于其他查询,它运行良好。对于编码,它会出错。吸烟似乎与许多不相关的术语有很好的匹配。
  2. 嵌入是通过连接最后4层的隐藏状态来构建的。
    到目前为止,我还没有将词片组合在一起。我会研究这个问题。但在目前的情况下,编码和谋杀没有被破坏,但仍然具有很高的相似性。
qcbq4gxm

qcbq4gxm3#

如果大多数查询运行正常,那么我会认为这是随机性的结果。
作为基线,尝试将你的方法应用于非上下文词嵌入(如word2vec)并查看是否会得到同样多的奇怪结果。
另一个想法是,你也可以考虑在前N个相似词上应用一些启发式方法作为后处理步骤,以消除明显“错误”的词。这通常用于类比任务。要了解这可能是什么样子,你可以从听 this 播客开始。

相关问题