Обработка естественного языка (NLP). Личный опыт — мой первый запуск BERT

МЕНЮ


Главная страница
Поиск
Регистрация на сайте
Помощь проекту
Архив новостей

ТЕМЫ


Новости ИИРазработка ИИВнедрение ИИРабота разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика

Авторизация



RSS


RSS новости


BERT — Bidirectional Encoder Representations from Transformers

Здесь не будет рассказываться о том, что такое BERT, как это работает и для чего применяется — в сети об этом достаточно информации.

Эта статья про личный опыт — как конкретно у меня получилось запустить BERT с чистого Colab по конкретным описаниям.

Исходники

Изучение материала основывалось на следующих статьях:

Визуализируя нейронный машинный перевод (seq2seq модели с механизмом внимания)Transformer в картинкахBERT, ELMO и Ко в картинках (как в NLP пришло трансферное обучение)Ваш первый BERT: иллюстрированное руководствоA Visual Notebook to Using BERT for the First TIme.ipynb

Применяемые фрагменты кода

Код в целом без подробностей и комментариев, так как все подробно изложено в приведенных статьях.

# устанавливаем трансформеры !pip install transformers 
# устанавливаем библиотеки  import numpy as np import pandas as pd import torch import transformers as ppb  from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression from sklearn.model_selection import GridSearchCV from sklearn.model_selection import cross_val_score  import warnings warnings.filterwarnings('ignore')
# скачиваем dataset df = pd.read_csv('https://github.com/clairett/pytorch-sentiment-classification/raw/master/data/SST2/train.tsv', delimiter='	', header=None)
# выбираем фрагмент для ускорения и экономии времени batch_1 = df[:2000]
# проверяем, что с данными все ок print(batch_1[:5])
# Загружаем предобученную модель и токенизаторы  model_class, tokenizer_class, pretrained_weights = (ppb.DistilBertModel, ppb.DistilBertTokenizer, 'distilbert-base-uncased') tokenizer = tokenizer_class.from_pretrained(pretrained_weights) model = model_class.from_pretrained(pretrained_weights)
# токенизируем  tokenized = batch_1[0].apply((lambda x: tokenizer.encode(x, add_special_tokens=True)))
# делаем из списков массив, чтобы была одинаковая длина  max_len = 0 for i in tokenized.values:     if len(i) > max_len:         max_len = len(i)  padded = np.array([i + [0]*(max_len-len(i)) for i in tokenized.values])
# маскируем сделанные добавления attention_mask = np.where(padded != 0, 1, 0)
# создаем входной вектор из матрицы токенов  input_ids = torch.tensor(padded)   attention_mask = torch.tensor(attention_mask)  with torch.no_grad():     last_hidden_states = model(input_ids, attention_mask=attention_mask)
# разделяем данные на обучающую и тестовую выборки labels = batch_1[1] train_features, test_features, train_labels, test_labels = train_test_split(features, labels)
# обучаем модель логистической регрессии на обучающей выборке lr_clf = LogisticRegression() lr_clf.fit(train_features, train_labels)

На данном этапе работы по обучению модели, описанные в статьях, закончены.

Ссылка на блокнот Colab

Проверяем корректность

Прежде всего посмотрим показатели точности:

# модель обучена, смотрим метрики  print('# train:',lr_clf.score(train_features, train_labels)) print('# test:',lr_clf.score(test_features, test_labels))

# train: 0.906
# test: 0.844

Теперь проверим «визуально», что у нас в принципе получилось обучить модель. Для этого возьмем размеченные фрагменты из датасета, посчитаем их сами с помощью полученных коэффициентов и сравним результаты.

# распечатаем фрагмент из датасета print(batch_1[:5])

0 a stirring , funny and finally transporting re... 1
1 apparently reassembled from the cutting room f... 0
2 they presume their audience wo n't sit still f... 0
3 this is a visually stunning rumination on love... 1
4 jonathan parker 's bartleby should have been t... 1

# посчитаем сами и сравним  def LR(x): return (1 if x > 0 else 0) def correct(LR, label): return True if LR - label == 0 else False  sum_false = 0 N = 5  for i in range (N):   if i and i % 100 == 0: print(i)   array = np.array(tokenized[i])   array = np.pad(array, (0, max_len - len(array)), 'constant')   attention_mask_this = np.where(array != 0, 1, 0)   input_ids_this = torch.tensor([array])     attention_mask_this = torch.tensor(attention_mask_this)   with torch.no_grad():       last_hidden_states_this = model(input_ids_this, attention_mask=attention_mask_this)   features_this = last_hidden_states_this[0][:,0,:].numpy()    sum = np.dot(features_this,lr_clf.coef_[0])     if N < 20: print(i, labels[i], LR(sum), correct(LR(sum), labels[i]), sum)     if correct(LR(sum), labels[i]) == True: sum_false += 1  print() print(sum_false/(i+1))

0 1 1 True [3.85857511]
1 0 0 True [-6.51904703]
2 0 0 True [-2.21694384]
3 1 1 True [3.65850942]
4 1 0 False [-0.32528463]

0.8

Видим, что 1 ошибка из 5, то есть совпадает с ожидаемой точностью.
Можно сравнивать и больше строк, меняя N, и видно, что вывод модели совпадает с заданной разметкой в параметрах заявленной точности, то есть считаем, что модель понята и «перенесена» корректно.

Анализируем свой текст

Теперь проанализируем свои фрагменты текста, то есть зададим новые фрагменты и выведем оценку с помощью полученных коэффициентов.

# задаем свои фрагменты  texts = [     'All is good',      'it is so bad',      'nice to meet you',     'it is so rainy',     'he is a stupid',     'I like my car',     'have a nice day'         ]
# Классифицируем свои фрагменты  for text in texts:   array = tokenizer.encode(text, add_special_tokens=True)   array = np.pad(array, (0, max_len - len(array)), 'constant')   attention_mask_this = np.where(array != 0, 1, 0)   input_ids_this = torch.tensor([array])     attention_mask_this = torch.tensor(attention_mask_this)   with torch.no_grad():       last_hidden_states_this = model(input_ids_this, attention_mask=attention_mask_this)   features_this = last_hidden_states_this[0][:,0,:].numpy()    sum = np.dot(features_this,lr_clf.coef_[0])     print(text, ':', sum, ':', LR(sum)) 

All is good : [1.90097556] : 1
it is so bad : [-1.86999172] : 0
nice to meet you : [4.96587936] : 1
it is so rainy : [-2.53429642] : 0
he is a stupid : [-2.4318853] : 0
I like my car : [0.2118134] : 1
have a nice day : [2.30864912] : 1

1 - позитивно
0 - негативно

Видим, что модель корректно классифицирует представленные фрагменты.

Результат

В результате модель корректно классифицирует фрагменты текста на позитивный/негативный.

На следующем этапе предполагается протестировать разные наборы данных и сделать варианты модели для русского языка.



Источник: habr.com

Комментарии: