Как модель BERT выбирает порядок этикеток?
Я тренирую BertForSequenceClassification для задачи классификации. Мой набор данных состоит из «содержит побочные эффекты» (1) и «не содержит побочных эффектов» (0). Набор данных содержит все единицы, а затем нули после (данные не перемешиваются). Для обучения я перетасовал свои данные и получил логиты. Насколько я понял, логиты - это распределения вероятностей до softmax. Пример логита: [-4,673831, 4,7095485]. Соответствует ли первое значение метке 1 (содержит AE), потому что оно появляется первым в наборе данных, или метке 0. Любая помощь будет принята с благодарностью.
1 ответ
Первое значение соответствует метке 0, а второе значение соответствует метке 1. Что делает это вывод пула на линейный уровень (после выпадения, которое я проигнорирую в этом ответе). Давайте посмотрим на следующий пример:
from torch import nn
from transformers import BertModel, BertTokenizer
t = BertTokenizer.from_pretrained('bert-base-uncased')
m = BertModel.from_pretrained('bert-base-uncased')
i = t.encode_plus('This is an example.', return_tensors='pt')
o = m(**i)
print(o.pooler_output.shape)
Выход:
torch.Size([1, 768])
Pooled_output - это тензор формы [batch_size,hidden_size] и представляет контекстуализированный (т.е. было применено внимание)
[CLS]
токен ваших входных последовательностей. Этот тензор на линейный слой для вычисления подаетсялогитов вашей последовательности:
classificationLayer = nn.Linear(768,2)
logits = classificationLayer(o.pooler_output)
Когда мы нормализуем эти логиты, мы видим, что линейный слой предсказывает, что наш ввод должен принадлежать метке 1:
print(nn.functional.softmax(logits,dim=-1))
Вывод (будет отличаться, так как линейный слой инициализируется случайным образом):
Линейный слой применяет линейное преобразование:
y=xA^T+b
и вы уже можете видеть, что линейный слой не знает ваших меток. Он «только» имеет матрицу весов размером [2,768] для создания логитов размера [1,2] (то есть: первая строка соответствует первому значению, а вторая строка - второму):
import torch:
logitsOwnCalculation = torch.matmul(o.pooler_output, classificationLayer.weight.transpose(0,1))+classificationLayer.bias
print(nn.functional.softmax(logitsOwnCalculation,dim=-1))
Выход:
tensor([[0.1679, 0.8321]], grad_fn=<SoftmaxBackward>)
Модель BertForSequenceClassification, такBertForSequenceClassificationподает обучается путем применения . Эта функция потерь дает небольшую потерю, когда логиты для определенного класса (метка в вашем случае) лишь незначительно отклоняются от ожидаемого. Это означает, что CrossEntropyLossCrossEntropyLoss - это тот, который позволяет вашей модели узнать, что первый логит должен быть высоким, когда вход
does not contain adverse effect
или маленький, когда это
contains adverse effect
. Вы можете проверить это на нашем примере следующим образом:
loss_fct = nn.CrossEntropyLoss()
label0 = torch.tensor([0]) #does not contain adverse effect
label1 = torch.tensor([1]) #contains adverse effect
print(loss_fct(logits, label0))
print(loss_fct(logits, label1))
Выход:
tensor(1.7845, grad_fn=<NllLossBackward>)
tensor(0.1838, grad_fn=<NllLossBackward>)