【问题标题】:BERT sentence embedding by summing last 4 layers通过对最后 4 层求和的 BERT 句子嵌入
【发布时间】:2020-02-07 00:48:39
【问题描述】:

我在 BERT 上使用了 Chris McCormick 教程,使用 pytorch-pretained-bert 得到了如下的句子嵌入:

tokenized_text = tokenizer.tokenize(marked_text)
indexed_tokens = tokenizer.convert_tokens_to_ids(tokenized_text)
segments_ids = [1] * len(tokenized_text)
tokens_tensor = torch.tensor([indexed_tokens])
segments_tensors = torch.tensor([segments_ids])
model = BertModel.from_pretrained('bert-base-uncased')
model.eval()

with torch.no_grad():
    encoded_layers, _ = model(tokens_tensor, segments_tensors)
    # Holds the list of 12 layer embeddings for each token
    # Will have the shape: [# tokens, # layers, # features]
    token_embeddings = []

    # For each token in the sentence...
    for token_i in range(len(tokenized_text)):
        # Holds 12 layers of hidden states for each token
        hidden_layers = []

        # For each of the 12 layers...
        for layer_i in range(len(encoded_layers)):

                # Lookup the vector for `token_i` in `layer_i`
                vec = encoded_layers[layer_i][batch_i][token_i]

                hidden_layers.append(vec)

        token_embeddings.append(hidden_layers)

现在,我试图通过对最后 4 层求和来获得最终的句子嵌入,如下所示:

summed_last_4_layers = [torch.sum(torch.stack(layer)[-4:], 0) for layer in token_embeddings]

但我没有得到长度为 768 的单个火炬矢量,而是得到以下内容:

[tensor([-3.8930e+00, -3.2564e+00, -3.0373e-01,  2.6618e+00,  5.7803e-01,
-1.0007e+00, -2.3180e+00,  1.4215e+00,  2.6551e-01, -1.8784e+00,
-1.5268e+00,  3.6681e+00, ...., 3.9084e+00]), tensor([-2.0884e+00, -3.6244e-01,  ....2.5715e+00]), tensor([ 1.0816e+00,...-4.7801e+00]), tensor([ 1.2713e+00,.... 1.0275e+00]), tensor([-6.6105e+00,..., -2.9349e-01])]

我在这里得到了什么?如何合并最后一层的总和?

谢谢!

【问题讨论】:

    标签: python neural-network nlp pytorch


    【解决方案1】:

    您使用迭代token_embeddings 的列表推导创建一个列表。它是一个列表,每个标记包含一个张量 - 而不是您可能认为的每层一个张量(从您的 for layer in token_embeddings 判断)。因此,您会得到一个长度等于令牌数量的列表。对于每个标记,您都有一个向量,该向量是最后 4 层的 BERT 嵌入的总和。

    更有效的方法是避免显式的 for 循环和列表理解:

    summed_last_4_layers = torch.stack(encoded_layers[-4:]).sum(0)
    

    现在,变量summed_last_4_layers 包含相同的数据,但以单个维度张量的形式:句子长度 × 768。

    要获得单个(即池化)向量,您可以在张量的第一维上进行池化。在这种情况下,最大池化或平均池化可能比将所有令牌嵌入相加更有意义。对这些值求和时,不同长句子的向量在不同的范围内,并没有真正的可比性。

    【讨论】:

    • 谢谢!!我现在明白我所有的错误了。感谢您花时间修改、更正和解释 :)
    猜你喜欢
    • 2020-01-29
    • 1970-01-01
    • 1970-01-01
    • 2021-11-29
    • 1970-01-01
    • 2020-05-18
    • 2020-04-07
    • 2020-07-01
    • 2020-12-07
    相关资源
    最近更新 更多