Private score: 0.7673505952640405
Score = 0.8*(1 - logloss) + 0.2*F1
(Multilabel classification + NER)
Необходимо по текстовому описанию болезней:
- определить потенциальные болезни коров ("label")
- научиться автоматически выделять признаки заболеваний и симптомы болезней ("span")
label – вероятность каждого из 11 возможных заболеваний
span – индексы начала и конца размеченных признаков болезни
Пример текста:
У нетели болячки на вымени. Здравствуйте. Нетель на позднем сроке. Обнаружила, что все вымя покрылось маленькими болячками. Вымя массирую - стоит смирно. На фото - коричневые точки. Что это? Помогите, пожалуйста.
-
The Russian Drug Reaction Corpus (RuDReC).
Датасет для NER, содержит много симптомов с контекстом, что полезно для нашей задачи(остальные тэги из датасета мы не учитываем) https://github.com/natasha/corus
-
labeled_train_by_hand.json
-
labeled_by_hand_version_2.json
Ручная разметка в label-studio, пытался соотвествовать логике разметки авторов разметки первых 30 сэмплов.
Отличие второго файла от третьего:
- Второй файл больше соотвествует разметке авторов.
- В третьем файле добавлено больше подробностей, которые, как мне кажется, помогли бы при классификации.
-
В ноутбуке NER стандартный процесс обучения, используются данные с ручной разметкой, как модель я использую cointegrated/rubert-tiny2.
-
Для полей теста, где модель выдала пустое предсказание, я использую простой бейзлайн для предсказания спанов:
span_words.py состоит из слов, которые содержались в размеченных спанах для трейна.
prediction = model(text) if len(prediction) == 0: text = text.lower() prediction = model(text) if len(prediction) == 0: spans = self.predict_spans_baseline(text)
-
Как модель также использую cointegrated/rubert-tiny2 от @avidale
-
Для обучения использую текст из спанов, которые разметил руками + полный текст из датасета(получил большой прирост):
new_train_df['text'] = " ".join(span_text) + " | " + new_train['text']
-
Для обучения использую LSEP Loss, его нет в PyTorch, но на MultiLabel классификации показывает лучший результат(в моих экспериментах это так).
classification/lsep_loss.py содержит класс для использования в PyTorch.
class LSEPLoss(nn.Module): def __init__(self): super(LSEPLoss, self).__init__() def forward(self, input, target): return LSEP.apply(input.cpu(), target.cpu())
Reference: Li+2017: https://arxiv.org/pdf/1704.03135.pdf
-
Для теста также используем текст из спанов, полученных после NER + полный текст из датасета.
-
Небольшая фишка с log-loss score:
Из-за особенностей метрики, если значения меньше, например, 0.01, то мы их оставляем равными 0.01, аналогично, если больше 0.94.
np.clip(x, 0.01, 0.94)
(Данный трюк не используется в лучшем сабмите, но докинул на паблике и привате в других случаях)