@[toc]
Задача классификации отношений занимает центральное место в задачах извлечения информации. Задача классификации отношений заключается в извлечении структурированных знаний из неструктурированных текстов; конкретно, это означает выявление семантических отношений между головной и хвостовой сущностями, например: ! Здесь можно вставить изображение С помощью модели классифицируется семантическое отношение между головной и хвостовой сущностью. Как же модель BERT применяется к задаче классификации отношений? Архитектура модели классификации отношений имеет множество вариантов: - Первый способ реализации: применение модели BERT для векторного представления предложений, независимо от положения сущностей в предложении. Сначала предложение разбивается на токены, к которым добавляются маркеры [CLS] и [SEP] в начале и в конце соответственно. Затем векторное представление [CLS] используется как вход для классификатора, который выдает оценки для предсказания типа отношений. !
| ----- | ------ | --- | ---- | ----------- | | SemEval10 | 6507 | 1493 | 2717 | 19 |
В этом разделе мы используем набор данных semeval10
. Набор данных состоит из тренировочного, валидационного и тестового множеств.
Файл
semeval.txt
содержит данные semeval10
, который является широко используемым набором данных в академических статьях. Каждая строка в этом наборе данных представляет собой файл JSON следующего формата:
{"token": ["the", "original", "play", "was", "filled", "with", "very", "topical", "humor", ",", "so", "the", "director",
"felt", "free", "to", "add", "current", "topical", "humor", "to", "the", "script", "."], "h": {"name": "play",
"pos": [2, 3]}, "t": {"name": "humor", "pos": [8, 9]}, "relation": "Component-Whole(e2,e1)"}
Файл semeval_rel2id.json
содержит отображение меток для классификации отношений, всего 19 меток для классификации отношений.
### 3. Описание кода
Файл data_loader.py
: Этот файл преобразует текстовые файлы в объекты класса InputExample
, а затем преобразует входные образцы в объекты класса InputFeatures
, которые могут быть прочитаны моделью BERT, и сохраняет их в кэше для быстрой загрузки в следующий раз.
Файл utils.py
: Содержит множество утилит, которые удобно использовать.
Файл trainer.py
: Определяет процесс обучения и оценки модели, а также сохранения и загрузки модели.
Файл main.py
: Используется для обучения и оценки модели.
Файл predict.py
: Используется для предсказания модели.
Файл modeling_bert.py
: Содержит определение пользовательской модели BERT для классификации отношений.#### 1. Функция потерь Focal Loss
$$FL(p_t)=-\alpha_t(1-p_t)^{\gamma}log(p_t)$$
$\alpha_t$: Учитывает дисбаланс классов;
$(1 - p_t)^{\gamma}$: Если правильный класс $t$, то исходная функция потерь CE равна $-log(p_t)$. Если $p_t$ велико, это означает, что модель очень уверена в этом предсказании, $(1 - p_t)^{\gamma}$ будет малым, то есть эта уверенная выборка будет иметь небольшое влияние на общий ущерб;
Если $p_t$ мало, это означает, что модель имеет низкую уверенность в этом предсказании, $(1 - p_t)^{\gamma}$ будет близко к единице, что увеличивает влияние этой выборки на общий ущерб.
Пользовательский код для реализации функции потерь Focal Loss:
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
class FocalLoss(nn.Module):
r"""
Эта критерия является реализацией Focal Loss, которая была предложена в
статье "Focal Loss for Dense Object Detection".
Loss(x, class) = - \alpha (1-softmax(x)[class])^gamma \log(softmax(x)[class])
Потери усредняются по наблюдениям для каждого мини-батча.
"""
``` Аргументы:
alpha(1D Tensor, Variable) : скалярный коэффициент для этого критерия
gamma(float, double) : gamma > 0; уменьшает относительную потерю для хорошо классифицированных примеров (p > 0.5),
увеличивая акцент на трудных, неправильно классифицированных примерах
size_average(bool): По умолчанию, потери усредняются по наблюдениям для каждого мини-батча.
Однако, если поле size_average установлено на False, потери
суммируются для каждого мини-батча. """
def __init__(self, class_num, alpha=None, gamma=2, size_average=True):
super(FocalLoss, self).__init__()
# Если alpha пуст, то веса для каждого класса равны
if alpha is None:
self.alpha = torch.ones(class_num, 1)
# Если alpha не пуст, torch.FloatTensor инициализирует alpha
else:
self.alpha = torch.FloatTensor(alpha)
# gamma по умолчанию равен 2, чем больше gamma, тем меньше вклад уверенных примеров в общую потерю
self.gamma = gamma
# Общее количество классов
self.class_num = class_num
# Определяет, вычисляется ли общая потеря для батча или средняя потеря
self.size_average = size_average
def forward(self, inputs, targets):
"""
Определяет прямое распространение
:param inputs: выходы классификационного слоя [B, class_num]
:param targets: правильные метки
:return:
"""
# Размер батча
N = inputs.size(0)
# Количество классов
C = inputs.size(1)
# Нормализация выходов softmax
P = F.softmax(inputs)
""" # правильные метки и соответствующие предсказанные вероятности влияют на потерю, class_mask в этом месте равен 1
class_mask = torch.zeros_like(inputs).to(inputs.device)
# правильные метки
ids = targets.view(-1, 1)
# заполнение 1 в соответствующих позициях class_mask
class_mask.scatter_(1, ids.data, 1.)
# print("class_mask: ", class_mask)
# Если inputs находится на GPU, а alpha находится на CPU, то необходимо выполнить преобразование
if inputs.is_cuda and not self.alpha.is_cuda:
self.alpha = self.alpha.cuda()
# Получаем веса классов для каждого образца
alpha = self.alpha[ids.data.view(-1)]
# print("alpha: ", alpha)
# Получаем вероятности правильного класса для каждого образца
probs = (P * class_mask).sum(1).view(-1, 1)
# print("probs: ", probs)
# Применяем логарифмирование к вероятностям
log_p = probs.log()
# print('log_p size= {}'.format(log_p.size()))
# print(log_p)
# Вычисляем потери для каждого образца в батче
batch_loss = -alpha * (torch.pow((1 - probs), self.gamma)) * log_p
# print('-----bacth_loss------')
# print(batch_loss)
# Вычисляем среднее значение потерь
if self.size_average:
loss = batch_loss.mean()
# Вычисляем суммарное значение потерь
else:
loss = batch_loss.sum()
return loss
### 4. Результаты тестирования
#### 1. Код программы
  Если не использовать cls_vector, а использовать только entity_vector,
```python
python bert_finetune_re/main.py --data_dir .
```/bert_finetune_re/data/ --task semeval10 --model_type bert --model_dir bert_finetune_re/experiments/outputs/rebert_0 --do_train --do_eval --train_batch_size 8 --num_train_epochs 8 --learning_rate 5e-5 --linear_learning_rate 5e-4 --warmup_steps 600 --ignore_index -100 --max_seq_len 64 --use_entity_vector
Результаты тестирования:```python re_acc = 0.7425414364640884
  Если использовать только `cls_vector`, а не `entity_vector`,
```python
python bert_finetune_re/main.py --data_dir ./bert_finetune_re/data/ --task semeval10 --model_type bert --model_dir bert_finetune_re/experiments/outputs/rebert_2 --do_train --do_eval --train_batch_size 8 --num_train_epochs 8 --use_cls_vector --learning_rate 5e-5 --linear_learning_rate 5e-4 --warmup_steps 600 --ignore_index -100 --max_seq_len 64
Результаты тестирования:
re_acc = 0.5915285451197053
Если использовать cls_vector
и entity_vector
,
python bert_finetune_re/main.py --data_dir ./bert_finetune_re/data/ --task semeval10 --model_type bert --model_dir bert_finetune_re/experiments/outputs/rebert_2 --do_train --do_eval --train_batch_size 8 --num_train_epochs 8 --use_cls_vector --use_entity_vector --learning_rate 5e-5 --linear_learning_rate 5e-4 --warmup_steps 600 --ignore_index -100 --max_seq_len 64
Результат тестирования:
re_acc = 0.7325966850828729
Если использовать mention_pooling = avg
,
python bert_finetune_re/main.py --data_dir ./bert_finetune_re/data/ --task semeval10 --model_type bert --model_dir bert_finetune_re/experiments/outputs/rebert_0 --do_train --do_eval --train_batch_size 8 --num_train_epochs 8 --learning_rate 5e-5 --linear_learning_rate 5e-4 --warmup_steps 600 --ignore_index -100 --max_seq_len 64 --use_entity_vector --mention_pooling avg
Тестовые результаты:
re_acc = 0.7421731123388582
Если использовать mention_pooling = max
,
python bert_finetune_re/main.py --data_dir ./bert_finetune_re/data/ --task semeval10 --model_type bert --model_dir bert_finetune_re/experiments/outputs/rebert_0 --do_train --do_eval --train_batch_size 8 --num_train_epochs 8 --learning_rate 5e-5 --linear_learning_rate 5e-4 --warmup_steps 600 --ignore_index -100 --max_seq_len 64 --use_entity_vector --mention_pooling max
Тестовые результаты:
re_acc = 0.7403314917127072
Если использовать `focal_loss````python python bert_finetune_re/main.py --data_dir ./bert_finetune_re/data/ --task semeval10 --model_type bert --model_dir bert_finetune_re/experiments/outputs/rebert_0 --do_train --do_eval --train_batch_size 8 --num_train_epochs 8 --learning_rate 5e-5 --linear_learning_rate 5e-4 --warmup_steps 600 --ignore_index -100 --max_seq_len 64 --use_entity_vector --mention_pooling start --use_focal_loss --focal_loss_gamma 2.5
**Тестовые результаты:**
```python
re_acc = 0.7384898710865562
Поскольку этот набор данных хорошо сбалансирован, focal_loss
не показал хороших результатов.
python bert_finetune_ner/predict.py --input_file bert_finetune_ner/data/atis/test/seq.in --output_file bert_finetune_ner/experiments/outputs/nerbert_0/atis_test_predicted.txt --model_dir bert_finetune_ner/experiments/outputs/nerbert_0
Ссылка на блог: https://blog.csdn.net/weixin_46649052/article/details/119120199
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )