Предварительно обученная модель Берта дает случайный результат каждый раз - PullRequest
2 голосов
/ 09 мая 2020

Я пытался добавить дополнительный слой после трансформатора huggingface bert, поэтому я использовал BertForSequenceClassification внутри своей nn.Module Network. Но я вижу, что модель дает мне случайные выходные данные по сравнению с загрузкой модели напрямую.

Модель 1:

from transformers import BertForSequenceClassification

model = BertForSequenceClassification.from_pretrained('bert-base-uncased', num_labels = 5) # as we have 5 classes

import torch
from transformers import BertTokenizer
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')

input_ids = torch.tensor(tokenizer.encode(texts[0], add_special_tokens=True, max_length = 512)).unsqueeze(0)  # Batch size 1

print(model(input_ids))

Выход:

(tensor([[ 0.3610, -0.0193, -0.1881, -0.1375, -0.3208]],
        grad_fn=<AddmmBackward>),)

Модель 2 :

import torch
from torch import nn

class BertClassifier(nn.Module):
    def __init__(self):
        super(BertClassifier, self).__init__()
        self.bert = BertForSequenceClassification.from_pretrained('bert-base-uncased', num_labels = 5)
        # as we have 5 classes

        # we want our output as probability so, in the evaluation mode, we'll pass the logits to a softmax layer
        self.softmax = torch.nn.Softmax(dim = 1) # last dimension
    def forward(self, x):
        print(x.shape)
        x = self.bert(x)

        if self.training == False: # in evaluation mode
            pass
            #x = self.softmax(x)

        return x

# create our model

bertclassifier = BertClassifier()

print(bertclassifier(input_ids))
torch.Size([1, 512])
torch.Size([1, 5])
(tensor([[-0.3729, -0.2192,  0.1183,  0.0778, -0.2820]],
        grad_fn=<AddmmBackward>),)

Они должны быть одной модели, верно. Я обнаружил здесь аналогичную проблему, но без разумного объяснения https://github.com/huggingface/transformers/issues/2770

  1. Имеется ли у Берта какой-то рандомизированный параметр, если да, как получить воспроизводимый результат?

  2. Почему две модели дают разные выходы? Что-то я делаю не так?

1 Ответ

4 голосов
/ 09 мая 2020

Причина в случайной инициализации слоя классификатора Берта. Если вы распечатаете свою модель, вы увидите

    (pooler): BertPooler(
      (dense): Linear(in_features=768, out_features=768, bias=True)
      (activation): Tanh()
    )
  )
  (dropout): Dropout(p=0.1, inplace=False)
  (classifier): Linear(in_features=768, out_features=5, bias=True)
)

На последнем слое есть classifier, этот слой добавляется после bert-base. Ожидается, что вы обучите этот уровень своей последующей задаче.

Если вы хотите получить больше информации:

model, li = BertForSequenceClassification.from_pretrained('bert-base-uncased', num_labels = 5, output_loading_info=True) # as we have 5 classes
print(li)
{'missing_keys': ['classifier.weight', 'classifier.bias'], 'unexpected_keys': ['cls.predictions.bias', 'cls.predictions.transform.dense.weight', 'cls.predictions.transform.dense.bias', 'cls.predictions.decoder.weight', 'cls.seq_relationship.weight', 'cls.seq_relationship.bias', 'cls.predictions.transform.LayerNorm.weight', 'cls.predictions.transform.LayerNorm.bias'], 'error_msgs': []}

Вы можете увидеть classifier.weight и bias отсутствуют, поэтому эти части будут случайным образом инициализироваться каждый раз, когда вы вызываете BertForSequenceClassification.from_pretrained('bert-base-uncased', num_labels = 5).

...