BertModel 转换器输出字符串而不是张量

Posted

技术标签:

【中文标题】BertModel 转换器输出字符串而不是张量【英文标题】:BertModel transformers outputs string instead of tensor 【发布时间】:2021-03-15 19:59:02 【问题描述】:

我正在关注 this 教程,该教程使用带有 huggingface 库的 BERT 编写情绪分析分类器,但我的行为非常奇怪。当使用示例文本尝试 BERT 模型时,我得到一个字符串而不是隐藏状态。这是我正在使用的代码:

import transformers
from transformers import BertModel, BertTokenizer

print(transformers.__version__)

PRE_TRAINED_MODEL_NAME = 'bert-base-cased'
PATH_OF_CACHE = "/home/mwon/data-mwon/paperChega/src_classificador/data/hugingface"

tokenizer = BertTokenizer.from_pretrained(PRE_TRAINED_MODEL_NAME,cache_dir = PATH_OF_CACHE)

sample_txt = 'When was I last outside? I am stuck at home for 2 weeks.'

encoding_sample = tokenizer.encode_plus(
  sample_txt,
  max_length=32,
  add_special_tokens=True, # Add '[CLS]' and '[SEP]'
  return_token_type_ids=False,
  padding=True,
  truncation = True,
  return_attention_mask=True,
  return_tensors='pt',  # Return PyTorch tensors
)

bert_model = BertModel.from_pretrained(PRE_TRAINED_MODEL_NAME,cache_dir = PATH_OF_CACHE)


last_hidden_state, pooled_output = bert_model(
  encoding_sample['input_ids'],
  encoding_sample['attention_mask']
)

print([last_hidden_state,pooled_output])

输出:

4.0.0
['last_hidden_state', 'pooler_output']
 

【问题讨论】:

【参考方案1】:

虽然Aakash 的回答提供了问题的解决方案,但并没有解释问题。由于转换器库的 3.X 版本之一,模型不再返回元组,而是返回特定的输出对象:

o = bert_model(
    encoding_sample['input_ids'],
    encoding_sample['attention_mask']
)
print(type(o))
print(o.keys())

输出:

transformers.modeling_outputs.BaseModelOutputWithPoolingAndCrossAttentions
odict_keys(['last_hidden_state', 'pooler_output'])

你可以通过添加return_dict=False来获得一个元组来返回之前的行为:

o = bert_model(
   encoding_sample['input_ids'],
   encoding_sample['attention_mask'],
   return_dict=False
)

print(type(o))

输出:

<class 'tuple'>

我不建议这样做,因为现在选择输出的特定部分而不转向文档是明确的,如下例所示:

o = bert_model(encoding_sample['input_ids'],  encoding_sample['attention_mask'], return_dict=False, output_attentions=True, output_hidden_states=True)
print('I am a tuple with  elements. You do not know what each element presents without checking the documentation'.format(len(o)))

o = bert_model(encoding_sample['input_ids'],  encoding_sample['attention_mask'], output_attentions=True, output_hidden_states=True)
print('I am a cool object and you can acces my elements with o.last_hidden_state, o["last_hidden_state"] or even o[0]. My keys are;  '.format(o.keys()))

输出:

I am a tuple with 4 elements. You do not know what each element presents without checking the documentation
I am a cool object and you can acces my elements with o.last_hidden_state,  o["last_hidden_state"] or even o[0]. My keys are; odict_keys(['last_hidden_state', 'pooler_output', 'hidden_states', 'attentions']) 

【讨论】:

确实,我建议始终使用return_dict=True,以便可以从模型返回的字典中明确检索输出。 如何解码bertmodel的输出得到句子或字符串? bert_model 的输出只是您输入的上下文表示,句子仍然相同。您可以简单地执行tokenizer.decode(input_ids)。如果您在 bert 之上有不同的层,那就不同了。在这种情况下,请打开您自己的问题。 @shaikmoed【参考方案2】:

我在学习如何实现 Bert 时遇到了同样的问题。我注意到使用

last_hidden_state, pooled_output = bert_model(encoding_sample['input_ids'], encoding_sample['attention_mask'])

是问题所在。使用:

outputs = bert_model(encoding_sample['input_ids'], encoding_sample['attention_mask'])

并使用

提取last_hidden状态
output[0]

您可以参考文档here,它告诉您 BertModel 返回的内容

【讨论】:

以上是关于BertModel 转换器输出字符串而不是张量的主要内容,如果未能解决你的问题,请参考以下文章

Pandas 字符串系列到张量的 int 规范化

NotImplementedError:无法将符号张量 (2nd_target:0) 转换为 numpy 数组

在张量流中将 SSD 转换为冻结图。必须使用哪些输出节点名称?

如何将字符串列表转换为pytorch中的张量?

TypeError:获取参数数组的类型无效 numpy.ndarray,必须是字符串或张量。 (不能将 ndarray 转换为张量或操作。)

如何将 pytorch 张量转换为 numpy 数组?