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
Применяемые фрагменты кода
Код в целом без подробностей и комментариев, так как все подробно изложено в приведенных статьях.
# устанавливаем библиотеки 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')
# делаем из списков массив, чтобы была одинаковая длина 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])
Теперь проверим «визуально», что у нас в принципе получилось обучить модель. Для этого возьмем размеченные фрагменты из датасета, посчитаем их сами с помощью полученных коэффициентов и сравним результаты.
# распечатаем фрагмент из датасета 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))
Видим, что 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 - негативно
Видим, что модель корректно классифицирует представленные фрагменты.
Результат
В результате модель корректно классифицирует фрагменты текста на позитивный/негативный.
На следующем этапе предполагается протестировать разные наборы данных и сделать варианты модели для русского языка.