Розпізнавання іменованих об'єктів за допомогою трансформаторів

ВступПерманентне посилання

У моєму попередньому дописі в блозі ми обговорювали, як ми навчили SpanBERTa, мовну модель-трансформер для іспанської мови, на великому корпусі з нуля. Модель показала, що вона здатна правильно передбачати замасковані слова в послідовності, що базується на контексті. У цьому дописі блогу, щоб по-справжньому використати можливості моделей-трансформерів, ми налаштуємо SpanBERTa для завдання розпізнавання іменованих об'єктів.

Згідно з його визначенням на ВікіпедіяРозпізнавання іменованих об'єктів (NER) (також відоме як ідентифікація об'єктів, розбиття об'єктів на частини та вилучення об'єктів) - це підзадача вилучення інформації, яка має на меті знайти та класифікувати іменовані об'єкти, згадані в неструктурованому тексті, за попередньо визначеними категоріями, такими як імена людей, організації, місцезнаходження, медичні коди, часові вирази, кількості, грошові значення, відсотки тощо.

Ми використаємо скрипт run_ner.py Hugging Face та Набір даних CoNLL-2002 щоб налаштувати SpanBERTa.

НалаштуванняПерманентне посилання

Завантажити трансформатори і встановіть необхідні пакунки.

%%захоплення
!гівнюк клон https://github.com/обіймаюче обличчя/трансформатори
%cd трансформатори
!піп встановити .
!піп встановити -r ./приклади/вимоги.txt
%cd ..

ДаніПерманентне посилання

1. Завантажити набори данихПерманентне посилання

Наведена нижче команда завантажить і розархівує набір даних. Файли містять дані поїздів і тестів для трьох частин CoNLL-2002 спільне завдання:

  • esp.testa: Іспанські тестові дані для етапу розробки
  • esp.testb: дані іспанського тесту
  • esp.train: Дані про іспанські поїзди
%%захоплення
!wget -O 'conll2002.zip' "https://drive.google.com/uc?export=download&id=1Wrl1b39ZXgKqCeAFNM9EoXtA1kzwNhCe
!розстебни блискавку 'conll2002.zip'

Розмір кожного набору даних:

!туалет -l conll2002/esp.потяг
!туалет -l conll2002/esp.яєчка
!туалет -l conll2002/esp.testb
273038 conll2002/esp.train
54838 conll2002/esp.testa
53050 conll2002/esp.testb

Усі файли даних мають три колонки: слова, пов'язані з ними теги частин мови та іменовані теги сутностей у форматі IOB2. Розриви речень кодуються порожніми рядками.

!голова -n20 conll2002/esp.потяг
Мельбурнський НП B-LOC
( Fpa O
Австралія NP B-LOC
) Fpt O
, Fc O
25 Z O
may NC O
( Fpa O
EFE NC B-ORG
) Fpt O
. Fp O
- Fg O
El DA O
Abogado NC B-PER
General AQ I-PER
del SP I-PER
Estado NC I-PER
, Fc O

Ми збережемо лише стовпчик слів та стовпчик іменованих тегів сутностей для наших наборів даних train, dev та test.

!кішка conll2002/esp.потяг | вирізати -d " " -f 1,3 > train_temp.txt
!кішка conll2002/esp.яєчка | вирізати -d " " -f 1,3 > dev_temp.txt
!кішка conll2002/esp.testb | вирізати -d " " -f 1,3 > test_temp.txt

2. Попередня обробкаПерманентне посилання

Визначимо деякі змінні, які нам знадобляться для подальших кроків попередньої обробки та навчання моделі:

MAX_LENGTH = 120 #@param {type: "integer"}
МОДЕЛЬ = "chriskhanhtran/spanberta" #@param ["chriskhanhtran/spanberta", "bert-base-multilingual-cased"]

Наведений нижче скрипт розділить речення, довші за MAX_LENGTH (з точки зору токенів) на невеликі. В іншому випадку довгі речення будуть усікатися при токенізації, що призведе до втрати навчальних даних і непередбачуваності деяких токенів у тестовому наборі.

%%захоплення
!wget "https://raw.githubusercontent.com/stefan-it/fine-tuned-berts-seq/master/scripts/preprocess.py"
!python3 препроцес.py train_temp.txt $МОДЕЛЬ $MAX_LENGTH > потяг.txt
!python3 препроцес.py dev_temp.txt $МОДЕЛЬ $MAX_LENGTH > dev.txt
!python3 препроцес.py test_temp.txt $МОДЕЛЬ $MAX_LENGTH > тест.txt
2020-04-22 23:02:05.747294: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Успішно відкрито динамічну бібліотеку libcudart.so.10.1
Завантаження: 100% 1.03k/1.03k [00:00<00:00, 704kB/s]
Завантаження: 100% 954k/954k [00:00<00:00, 1.89MB/s].
Завантажуємо: 100% 512k/512k [00:00<00:00, 1.19MB/s].
Завантажуємо: 100% 16.0/16.0 [00:00<00:00, 12.6 КБ/с].
2020-04-22 23:02:23.409488: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Успішно відкрито динамічну бібліотеку libcudart.so.10.1
2020-04-22 23:02:31.168967: I tensorflow/stream_executor/platform/default/dso_loader.cc:44] Успішно відкрито динамічну бібліотеку libcudart.so.10.1

3. ЕтикеткиПерманентне посилання

У наборах даних CoNLL-2002/2003 є 9 класів тегів NER:

  • O, За межами названого об'єкта
  • B-MIS, Початок різної сутності одразу після іншої різної сутності
  • I-MIS, Інша організація
  • B-PER, Початок імені особи одразу після імені іншої особи
  • I-PER, Ім'я особи
  • B-ORG, створення організації одразу після іншої організації
  • I-ORG, Організація
  • B-LOC, Початок локації одразу після іншої локації
  • I-LOC, місцезнаходження

Якщо ваш набір даних має інші мітки або більше міток, ніж набір даних CoNLL-2002/2003, запустіть рядок нижче, щоб отримати унікальні мітки з ваших даних і збережіть їх у папці labels.txt. Цей файл буде використано, коли ми почнемо точне налаштування нашої моделі.

!кішка потяг.txt dev.txt тест.txt | вирізати -d " " -f 2 | grep -v "^$"| вид | uniq > етикетки.txt

Тонке налаштування моделіПерманентне посилання

Ось приклади скриптів з трансформаториякі ми будемо використовувати для доопрацювання нашої моделі для NER. Після 21.04.2020 Hugging Face оновили свої приклади скриптів, щоб використовувати новий Тренер клас. Щоб уникнути конфліктів у майбутньому, давайте використовувати версію до того, як вони зробили ці оновлення.

%%захоплення
!wget "https://raw.githubusercontent.com/chriskhanhtran/spanish-bert/master/ner/run_ner.py"
!wget "https://raw.githubusercontent.com/chriskhanhtran/spanish-bert/master/ner/utils_ner.py"

Тепер настав час для трансферного навчання. У моєму попередня публікація в блозіЯ попередньо навчив мовну модель RoBERTa на дуже великому корпусі іспанської мови передбачати замасковані слова на основі контексту, в якому вони перебувають. Таким чином, модель навчилася властивостям, притаманним мові. Я завантажив попередньо навчену модель на сервер Hugging Face. Зараз ми завантажимо модель і почнемо її тонке налаштування для завдання NER.

Нижче наведені наші гіперпараметри тренування.

MAX_LENGTH = 128 #@param {type: "integer"}
МОДЕЛЬ = "chriskhanhtran/spanberta" #@param ["chriskhanhtran/spanberta", "bert-base-multilingual-cased"]
OUTPUT_DIR = "Спанберта-нер" #@param ["spanberta-ner", "bert-base-ml-ner"].
BATCH_SIZE = 32 #@param {type: "integer"}
NUM_EPOCHS = 3 #@param {type: "integer"}
SAVE_STEPS = 100 #@param {type: "integer"}
LOGGING_STEPS = 100 #@param {type: "integer"}
НАСІННЯ = 42 #@param {type: "integer"}

Почнемо тренування.

!python3 run_ner.py \
 --data_dir ./ \
 --model_type Берт \
 --етикетки ./етикетки.txt \
 --назва_моделі_або_шлях $МОДЕЛЬ \
 --output_dir $OUTPUT_DIR \
 --max_seq_length $MAX_LENGTH \
 --num_train_epochs $NUM_EPOCHS \
 --per_gpu_train_batch_size $BATCH_SIZE \
 --save_steps $SAVE_STEPS \
 --logging_steps $LOGGING_STEPS \
 --насіння $НАСІННЯ \
 --do_train \
 --do_eval \
 --do_predict \
 --overwrite_output_dir

Виступ на знімальному майданчику:

04/21/2020 02:24:31 - INFO - __main__ - ***** Результати оцінки *****
04/21/2020 02:24:31 - INFO - __main__ - f1 = 0.831027443864822
04/21/2020 02:24:31 - INFO - __main__ - loss = 0.1004064822183894
04/21/2020 02:24:31 - INFO - __main__ - точність = 0.8207885304659498
04/21/2020 02:24:31 - INFO - __main__ - відкликання = 0.8415250344510795

Продуктивність на тестовому наборі:

04/21/2020 02:24:48 - INFO - __main__ - ***** Результати оцінки *****
04/21/2020 02:24:48 - INFO - __main__ - f1 = 0.8559533721898419
04/21/2020 02:24:48 - INFO - __main__ - loss = 0.06848683688204177
04/21/2020 02:24:48 - INFO - __main__ - точність = 0.845858475041141
04/21/2020 02:24:48 - INFO - __main__ - відкликання = 0.8662921348314607

Ось тензорні дошки тонкого налаштування спанберта і bert-base-multilingual-cased для 5 епох. Ми бачимо, що моделі підганяються під навчальні дані після 3 епох.

Звіт про класифікацію

Щоб зрозуміти, наскільки добре працює наша модель, завантажимо її прогнози і проаналізуємо звіт про класифікацію.

def прочитати_приклади_з_файлу(шлях до файлу):
 """Прочитати слова та мітки з файлу даних CoNLL-2002/2003.
 Аргументи:
 шлях_до_файлу (str): шлях до файлу даних NER.
 Повертається:
 examples (dict): словник з двома ключами: `words` (список списків)
 що містить слова у кожній послідовності, і `labels` (список списків), що містить
 відповідні мітки.
 """
 з відкрито(шлях до файлу, кодування="utf-8") як f:
 приклади = {"слова": [], "етикетки": []}
 слова = []
 етикетки = []
 за лінія в f:
 якщо лінія.починається з("-DOCSTART-") або лінія == "" або лінія == "\n":
 якщо слова:
 приклади["слова"].додати(слова)
 приклади["етикетки"].додати(етикетки)
 слова = []
 етикетки = []
 інакше:
 розщеплення = лінія.розкол(" ")
 слова.додати(розщеплення[0])
 якщо Лен(розщеплення) > 1:
 етикетки.додати(розщеплення[-1].замінити("\n", ""))
 інакше:
 # Приклади можуть не мати мітки для mode = "test"
 етикетки.додати("O")
 повернення приклади

Зчитування даних і міток з необроблених текстових файлів:

y_true = прочитати_приклади_з_файлу("test.txt")["етикетки"]
y_pred = прочитати_приклади_з_файлу("spanberta-ner/test_predictions.txt")["етикетки"]

Роздрукуйте звіт про класифікацію:

від seqeval.metrics імпорт класифікаційний_звіт як classification_report_seqeval
друк(classification_report_seqeval(y_true, y_pred))
 підтримка точного відкликання f1-score
 LOC 0.87 0.84 0.85 1084
 ORG 0.82 0.87 0.85 1401
 MISC 0.63 0.66 0.65 340
 PER 0.94 0.96 0.95 735
micro avg 0.84 0.86 0.85 3560
macro avg 0.84 0.86 0.85 3560

Метрики, які ми бачимо в цьому звіті, розроблені спеціально для завдань НЛП, таких як NER і POS-тегування, в яких всі слова сутності повинні бути правильно передбачені, щоб зарахувати їх як одне правильне передбачення. Тому метрики в цьому звіті про класифікацію набагато нижчі, ніж у Звіт про класифікацію scikit-learn.

імпорт неслухняний. як np
від sklearn.metrics імпорт класифікаційний_звіт
друк(класифікаційний_звіт(np.конкатенат(y_true), np.конкатенат(y_pred)))
 підтримка точного відкликання f1-score
 B-LOC 0.88 0.85 0.86 1084
 B-MISC 0.73 0.73 0.73 339
 B-ORG 0.87 0.91 0.89 1400
 B-PER 0.95 0.96 0.95 735
 I-LOC 0.82 0.81 0.81 325
 I-MISC 0,85 0,76 0,80 557
 I-ORG 0,89 0,87 0,88 1104
 I-PER 0,98 0,98 0,98 634
 O 1.00 1.00 1.00 45355
 accuracy 0.98 51533
 macro avg 0.89 0.87 0.88 51533
середньозважена 0.98 0.98 0.98 51533

З наведених вище звітів випливає, що наша модель має хороші показники в прогнозуванні особи, місцезнаходження та організації. Нам знадобиться більше даних для MISC для покращення ефективності нашої моделі на цих підприємствах.

ТрубопровідПерманентне посилання

Після доопрацювання наших моделей ми можемо поділитися ними зі спільнотою, дотримуючись інструкцій у цьому посібнику сторінка. Тепер ми можемо почати завантажувати доопрацьовану модель з сервера Hugging Face і використовувати її для прогнозування іменованих сутностей в іспанських документах.

від трансформатори імпорт трубопровід, Автоматична модель для класифікації токенів, Автоматичний токенізатор
модель = Автоматична модель для класифікації токенів.from_pretrained("skimai/spanberta-base-cased-ner-conll02")
токенізатор = Автоматичний токенізатор.from_pretrained("skimai/spanberta-base-cased-ner-conll02")
ner_model = трубопровід("Нер, модель=модель, токенізатор=токенізатор)

Приклад, наведений нижче, взято з La Opinion і означає "Економічне відновлення Сполучених Штатів після пандемії коронавірусу буде питанням кількох місяців, заявив міністр фінансів Стівен Мнучін."

послідовність = "Економічне відновлення Сполучених Штатів Америки після "Великої Вітчизняної війни". \
 "Пандемія коронавірусу буде питанням кількох місяців, запевнив ель " \
 "Секретар Тесоро, Стівен Мнучін".
ner_model(послідовність)
[{ 'entity': 'B-ORG', 'score': 0.9155661463737488, 'word': 'ĠEstados'},
 { 'entity': 'I-ORG', 'score': 0.800682544708252, 'word': 'ĠUnidos'},
 { 'entity': 'I-MISC', "score": 0.5006815791130066, "word": 'Ġcorona'},
 {'entity': 'I-MISC', 'score': 0.510674774646759, 'word': 'virus'},
 {'entity': 'B-PER', "score": 0.5558510422706604, "word": 'ĠSecretario'},
 {'entity': 'I-PER', 'score': 0.7758238315582275, 'word': 'Ġdel'},
 {'entity': 'I-PER', 'score': 0.7096233367919922, 'word': 'ĠTesoro'},
 {'entity': 'B-PER', 'score': 0.9940345883369446, 'word': 'ĠSteven'},
 {'entity': 'I-PER', 'score': 0.9962581992149353, 'word': 'ĠM'},
 {'entity': 'I-PER', 'score': 0.9918380379676819, 'word': 'n'},
 {'entity': 'I-PER', 'score': 0.9848328828811646, 'word': 'uch'},
 {'entity': 'I-PER', 'score': 0.8513168096542358, 'word': 'in'}]

Виглядає чудово! Налаштована модель успішно розпізнає всі сутності в нашому прикладі, і навіть розпізнає "вірус корони".

ВисновокПерманентне посилання

Розпізнавання іменованих об'єктів може допомогти нам швидко витягувати важливу інформацію з текстів. Тому його застосування в бізнесі може мати прямий вплив на підвищення продуктивності людини при читанні контрактів і документів. Однак це складне завдання для НЛП, оскільки NER вимагає точної класифікації на рівні слів, що унеможливлює використання простих підходів, таких як мішок слів, для вирішення цього завдання.

Ми розглянули, як можна використовувати попередньо навчену модель BERT для швидкого отримання відмінних результатів у завданні NER для іспанської мови. Попередньо навчену модель SpanBERTa також можна налаштувати для інших завдань, таких як класифікація документів. Я написав детальний посібник з налаштування BERT для класифікації послідовностей та аналізу настроїв.

Далі в цій серії ми обговоримо ELECTRA, більш ефективний підхід до попереднього навчання моделей трансформаторів, який дозволяє швидко досягти найсучасніших характеристик. Залишайтеся з нами!

ukУкраїнська