将 HuggingFace 模型加载到 AllenNLP 中会给出不同的预测
Posted
技术标签:
【中文标题】将 HuggingFace 模型加载到 AllenNLP 中会给出不同的预测【英文标题】:Loading a HuggingFace model into AllenNLP gives different predictions 【发布时间】:2021-12-20 21:25:17 【问题描述】:我有一个使用基于 BERT 模型的 transformers
库训练的自定义分类模型。该模型将文本分为 7 个不同的类别。它使用以下方式持久保存在目录中:
trainer.save_model(model_name)
tokenizer.save_pretrained(model_name)
我正在尝试使用allennlp
库加载此类持久模型以进行进一步分析。经过大量的工作,我设法做到了。但是,当在allennlp
框架内运行模型时,该模型的预测结果与我使用transformers
运行它时得到的预测结果大不相同,这让我认为某些部分的加载没有正确完成。推理过程中没有错误,只是预测不匹配。
关于如何加载现有模型的文档很少,所以我想知道以前是否有人遇到过同样的情况。只有一个如何使用 ROBERTA 进行 QA 分类的示例,但无法推断出我正在寻找的内容。任何人都知道以下步骤是否正确?
这是我加载训练模型的方式:
transformer_vocab = Vocabulary.from_pretrained_transformer(model_name)
transformer_tokenizer = PretrainedTransformerTokenizer(model_name)
transformer_encoder = BertPooler(model_name)
params = Params(
"token_embedders":
"tokens":
"type": "pretrained_transformer",
"model_name": model_name,
)
token_embedder = BasicTextFieldEmbedder.from_params(vocab=vocab, params=params)
token_indexer = PretrainedTransformerIndexer(model_name)
transformer_model = BasicClassifier(vocab=transformer_vocab,
text_field_embedder=token_embedder,
seq2vec_encoder=transformer_encoder,
dropout=0.1,
num_labels=7)
我还必须实现我自己的DatasetReader
,如下所示:
class ClassificationTransformerReader(DatasetReader):
def __init__(
self,
tokenizer: Tokenizer,
token_indexer: TokenIndexer,
max_tokens: int,
**kwargs
):
super().__init__(**kwargs)
self.tokenizer = tokenizer
self.token_indexers: Dict[str, TokenIndexer] = "tokens": token_indexer
self.max_tokens = max_tokens
self.vocab = vocab
def text_to_instance(self, text: str, label: str = None) -> Instance:
tokens = self.tokenizer.tokenize(text)
if self.max_tokens:
tokens = tokens[: self.max_tokens]
inputs = TextField(tokens, self.token_indexers)
fields: Dict[str, Field] = "tokens": inputs
if label:
fields["label"] = LabelField(label)
return Instance(fields)
实例化如下:
dataset_reader = ClassificationTransformerReader(tokenizer=transformer_tokenizer,
token_indexer=token_indexer,
max_tokens=400)
要运行模型并测试它是否有效,我正在执行以下操作:
instance = dataset_reader.text_to_instance("some sample text here")
dataset = Batch([instance])
dataset.index_instances(transformer_vocab)
model_input = util.move_to_device(dataset.as_tensor_dict(),
transformer_model._get_prediction_device())
outputs = transformer_model.make_output_human_readable(transformer_model(**model_input))
这可以正常工作并正确返回概率,但与我直接使用转换器运行模型的结果不匹配。知道发生了什么吗?
【问题讨论】:
【参考方案1】:默认情况下,模型在训练模式下运行,这意味着 dropout 会随机化结果。首先通过运行model.eval()
尝试将两个模型(AllenNLP 和转换器)设置为评估模式。结果应该是一样的。
我认为您的其余代码是正确的,尽管它可能不是让转换器模型在 AllenNLP 中运行的最短方法。
【讨论】:
您能否分享在 AllenNLP 中加载变压器模型的哪种方式更好或更短?找不到更好的方法来加载保存在文件夹中的模型。 我也尝试将模型切换到评估,但还是一样。预测不符。我还使用来自训练数据集的样本(模型应该正确)测试了模型,确实transformers
正确,但allenNLP
给出了不同的答案。所以我认为allenNLP
上没有正确加载某些内容。
您能否在github.com/allenai/allennlp/issues/new/choose 创建一个问题,并使用显示此行为的可执行代码?
感谢您的建议!发表于github.com/allenai/allennlp/issues/5582以上是关于将 HuggingFace 模型加载到 AllenNLP 中会给出不同的预测的主要内容,如果未能解决你的问题,请参考以下文章
使用 Huggingface Transformers 从磁盘加载预训练模型
下载huggingface-transformers模型至本地,并使用from_pretrained方法加载
HuggingFace - config.json 中的 GPT2 标记器配置
Huggingface AutoTokenizer 无法从本地路径加载