Могу ли я использовать BERT в качестве средства извлечения функций без какой-либо тонкой настройки моего конкретного набора данных?

Я пытаюсь решить задачу многокомпонентной классификации из 10 классов с относительно сбалансированным обучающим набором, состоящим из ~ 25K образцов, а оценочный набор состоит из ~ 5K образцов.

Я использую обнимающееся лицо:

model = transformers.BertForSequenceClassification.from_pretrained(...

и получить довольно хорошие результаты (ROC AUC = 0,98).

Однако я наблюдаю какое-то странное поведение, в котором, кажется, не понимаю -

Я добавляю следующие строки кода:

for param in model.bert.parameters():
    param.requires_grad = False

при этом убедитесь, что изучены другие слои модели, то есть:

[param[0] for param in model.named_parameters() if param[1].requires_grad == True]
gives
['classifier.weight', 'classifier.bias']

Обучение модели при такой настройке дает неприятно плохие результаты (ROC AUC = 0,59).

Я работал в предположении, что готовая предварительно обученная модель BERT (без какой-либо тонкой настройки) должна служить относительно хорошим средством извлечения признаков для уровней классификации. Итак, где я ошибся?


person SBflying    schedule 25.10.2020    source источник
comment
Не могли бы вы добавить прямо к вашему вопросу результат: [p[0] for p in model.named_parameters() if p[1].requires_grad == True]?   -  person cronoik    schedule 25.10.2020


Ответы (2)


По моему опыту, вы ошибаетесь в своем предположении

Готовая предварительно обученная модель BERT (без какой-либо тонкой настройки) должна служить относительно хорошим средством извлечения признаков для слоев классификации.

Я заметил аналогичный опыт при попытке использовать выходной слой BERT в качестве значения для встраивания слов с минимальной или нулевой тонкой настройкой, что также дало очень плохие результаты; и это тоже имеет смысл, поскольку фактически у вас есть 768*num_classes соединений в простейшей форме выходного слоя. По сравнению с миллионами параметров BERT, это дает вам почти ничтожный контроль над сложной сложностью модели. Тем не менее, я также хочу осторожно указать на результаты переобучения при обучении вашей полной модели, хотя я уверен, что вы об этом знаете.

Вся идея BERT заключается в том, что тонкая настройка вашей модели очень дёшево, поэтому для получения идеальных результатов я бы не советовал замораживать какие-либо слои. Единственный случай, в котором может быть полезно отключить хотя бы частичные слои, - это компонент внедрения, в зависимости от размера словаря модели (~ 30 КБ для BERT-base).

person dennlinger    schedule 26.10.2020
comment
Не уверен, согласны ли вы, но лично я считаю, что 0,59 - это достойный результат, если учесть 10 занятий и короткое время обучения. @dennlinger - person cronoik; 26.10.2020
comment
Я не могу судить, насколько он хорош, но по сравнению с почти идеальными результатами с полной тонкой настройкой, я все же предпочел бы в конечном итоге лучшие результаты ;-) Я думаю, что нам также очень повезло с общими результаты BERT в целом, так что некоторые в противном случае достойные результаты могут быть только хуже ... - person dennlinger; 26.10.2020
comment
Большое спасибо за поддержку @dennlinger. Я все еще нахожу эти результаты довольно неожиданными, но приятно осознавать, что это действительно может быть допустимое поведение, а не просто случайная ошибка ... Я полагаю, что дальнейшее тестирование повысит мою уверенность в этих результатах. - person SBflying; 27.10.2020

Я думаю, следующее поможет прояснить странное поведение, о котором я сообщал здесь ранее:

Во-первых, как оказалось, при замораживании слоев BERT (и использовании готовой предварительно обученной модели BERT без какой-либо тонкой настройки) количество эпох обучения, необходимых для слоя классификации, намного больше, чем это необходимо, когда разрешено изучение всех слоев.

Например,

Не замораживая слои BERT, я достиг:

ROC AUC = 0.98, train loss = 0.0988, validation loss = 0.0501 @ end of epoch 1

ROC AUC = 0.99, train loss = 0.0484, validation loss = 0.0433 @ end of epoch 2

Overfitting, train loss = 0.0270, validation loss = 0.0423 @ end of epoch 3

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

ROC AUC = 0.77, train loss = 0.2509, validation loss = 0.2491 @ end of epoch 10

ROC AUC = 0.89, train loss = 0.1743, validation loss = 0.1722 @ end of epoch 100

ROC AUC = 0.93, train loss = 0.1452, validation loss = 0.1363 @ end of epoch 1000

(Вероятный) вывод, который следует из этих результатов, заключается в том, что работа с готовой предварительно обученной моделью BERT в качестве экстрактора признаков (то есть замораживание ее слоев) при изучении только слоя классификации страдает от под примеркой.

Это демонстрируется двумя способами:

Во-первых, после прохождения 1000 эпох модель все еще не завершила обучение (потери при обучении все еще выше, чем потери при проверке).

Во-вторых, после прохождения 1000 эпох значения потерь все еще выше, чем значения, достигнутые с версией без замораживания уже в первую эпоху.

Подводя итог, @dennlinger, я думаю, что полностью с вами согласен:

Вся идея BERT заключается в том, что тонкая настройка модели обходится очень дешево, поэтому для получения идеальных результатов я бы не советовал замораживать какие-либо слои.

person SBflying    schedule 29.10.2020
comment
Вы обучили классификатор только с небольшой скоростью обучения, как и весь BERT? Предлагаю правильную прибавку :) - person cronoik; 29.10.2020
comment
Хорошая точка зрения. ответ - нет. В отличие от lr~e-5, рекомендованного для точной настройки, здесь я использовал lr~e-3, который, как уже упоминалось, не помог мне выйти из области недостаточной настройки. - person SBflying; 29.10.2020
comment
Не уверен, что вас все еще интересует, но не могли бы вы попробовать 0,01 и также измерить время обучения? - person cronoik; 31.10.2020
comment
Я пробовал 0,01, как вы просили. Спустя 100 эпох модель все еще недостаточно доработана. Время обучения осталось прежним ~ 2 секунды на эпоху. Это действительно очень быстро, однако я тренирую только один полностью подключенный слой 768 * 10, используя две машины 1080 Ti, а также используя уже извлеченные выходные данные пула из 768 длинных векторов. - person SBflying; 31.10.2020