【问题标题】:The last layers of longformer for document embeddings文档嵌入的最后一层 longformer
【发布时间】:2021-01-20 20:22:53
【问题描述】:

使用 longformer API 返回有限层数的正确方法是什么?

与基本BERT 中的这种情况不同,从返回类型中我不清楚如何仅获取最后 N 层。

所以,我运行这个:

from transformers import LongformerTokenizer, LongformerModel

text = "word " * 4096 # long document!

tokenizer = LongformerTokenizer.from_pretrained('allenai/longformer-base-4096')
model = LongformerModel.from_pretrained("allenai/longformer-base-4096")

encoded_input = tokenizer(text, return_tensors="pt", max_length=4096, truncation=True)
output = model(**encoded_input)

我从返回中得到这样的尺寸:

>>> output[0].shape
torch.Size([1, 4096, 768])

>>> output[1].shape
torch.Size([1, 768])

您可以看到 [0] 的形状与我的令牌数量奇怪地相似。我相信切片只会给我更少的令牌,而不仅仅是最后 N 层。

从下面的答案更新

即使要求output_hidden_states,尺寸仍然看起来不对,我不清楚 如何将这些减少到向量大小的一维嵌入。这就是我的意思:

encoded_input = tokenizer(text, return_tensors="pt", max_length=4096, truncation=True)
output = model(**encoded_input, output_hidden_states=True)

好的,现在让我们看看输出[2],元组的第三项:

>>> len(output[2])
13

假设我们要查看 13 层中的最后 3 层:

>>> [pair[0].shape for pair in output[2][-3:]]
[torch.Size([4096, 768]), torch.Size([4096, 768]), torch.Size([4096, 768])]

所以我们看到 13 层中的每一层都是形状 (4096 x 768),它们看起来像:

>>> [pair[0] for pair in output[2][-3:]]
[tensor([[-0.1494,  0.0190,  0.0389,  ..., -0.0470,  0.0259,  0.0609],

我们仍然有 4096 的大小,因为它对应于我的令牌计数:

>>> np.mean(np.stack([pair[0].detach().numpy() for pair in output[2][-3:]]), axis=0).shape
(4096, 768)

将这些平均在一起似乎不会给出有效的嵌入(用于余弦相似度等比较)。

【问题讨论】:

    标签: word-embedding huggingface-transformers


    【解决方案1】:

    output 是一个由两个元素组成的元组:

    1. sequence_output(即最后一个编码器块)
    2. pooled_output

    为了获取所有隐藏层,需要将参数output_hidden_states设置为true:

    output = model(**encoded_input, output_hidden_states=True)
    

    输出现在有 3 个元素,第三个元素包含嵌入层和每个编码层的输出。

    【讨论】:

    • 谢谢,这很有帮助,但我认为在这一步之后我仍然感到困惑,因为我的令牌数量与我的可疑大小相同。
    • @Mittenchops 请不要修改您的问题,以免我的回答变得毫无用处。而是打开一个新问题。总的来说,我认为您的方法是错误的。不确定 Longformer,但 BERT does not produce meaningful sentence representations 可用于余弦相似度或类似的东西,因为它要求所有维度都具有相同的比例。我认为这也适用于 Longformer。你可以试试sentence-transformers
    • 谢谢,@cronoik。我确实发现您的回答有助于看到我可以请求第三个元组,但是这与获得有效嵌入之间仍然存在差距,因此更新它似乎是合适的。如果我刚刚将更新作为一个新问题,我肯定会因为与以前/太相似/而关闭问题。版主鼓励我进行更新以确保清晰。
    • 我也明白,将 BERT 嵌入的终端层用于相似性等应用程序是很常见的:stackoverflow.com/a/63464865/1052117 和它参考的 Bertology 论文:arxiv.org/pdf/2002.12327.pdf
    • @Mittenchops 我已经发布了我的答案作为对您其他问题的回答。
    【解决方案2】:
    print(outputs.keys())            
    #odict_keys(['last_hidden_state', 'pooler_output', 'hidden_states'])
    
    print("outputs[0] gives us sequence_output: \n", outputs[0].shape) #torch.Size([1, 34, 768])
    
    print("outputs[1] gives us pooled_output  \n",outputs[1]) #Embeddings ( last hidden state) #[768]
                
    print("outputs[2]: gives us Hidden_output: \n ",outputs[2][0].shape) #torch.Size([1, 512, 768]) 
              
    

    对于您的用例,您可以使用 output[1] 作为嵌入。

    【讨论】:

      猜你喜欢
      • 2020-12-21
      • 2012-02-07
      • 2020-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-30
      • 1970-01-01
      相关资源
      最近更新 更多