[НЛП] Языковое моделирование и трансферное обучение

искусственный интеллект NLP Архитектура OpenAI

Обновление 10.13: недавно была выпущена новая современная модель предварительного обучения.Портал:

Ли Юмо: [НЛП] Подробное объяснение Google BERTzhuanlan.zhihu.com图标

1. Введение

Векторы слов долгое время были доминирующим методом представления в задачах НЛП. После ряда технологических прорывов в конце 2017 и начале 2018 года исследования подтвердили, что предварительно обученные языковые представления могут повысить производительность при выполнении многочисленных задач НЛП после точной настройки. В настоящее время существует два метода предварительной подготовки:

  1. На основе функций: используйте обученное представление в качестве функции для задач из векторов слов, векторов предложений, векторов сегментов и векторов текста. Новый ELMo также попадает в эту категорию, но представление входных данных необходимо пересчитывать после миграции.
  2. Тонкая настройка: это в основном заимствовано из CV, которое заключается в добавлении некоторых слоев для конкретных задач в предварительно обученную модель, а затем в точной настройке последних слоев. Новые ULMFit и OpenAI GPT попадают в эту категорию.

В этой статье в основном представлены три предварительно обученные языковые модели ELMo, ULMFiT и OpenAI GPT.

2. ELMo

2.1 Принцип модели и архитектура

Оригинальная ссылка:Deep contextualized word representations

ELMo — это вложение, извлеченное из двунаправленной языковой модели (BiLM). BiLSTM используется во время обучения, учитывая N токенов (t1, t2,...,tN), цель состоит в том, чтобы максимизировать:

\sum^N_{k=1}(\log p(t_k| t_1, ...,t_{k-1};\Theta x, \overrightarrow{\Theta}{LSTM}, \Theta s) + \log p(t_k\vert t{k+1}, ...,t_{N}; \Theta x, \overleftarrow{\Theta}{LSTM}, \Theta _s))  \\

ELMo за каждый токенt_k, 2L+1 представления вычисляются с помощью L-слоя biLM:

R_k = {x_k^{LM}, \overrightarrow{h}{k,j}^{LM}, \overleftarrow{h}{k, j}^{LM} \vert j=1, ..., L} = {h_{k,j}^{LM} \vert j=0,..., L} \\

вh_{k,0}^{LM}является результатом прямого кодирования токена (здесь символы кодируются CNN),h_{k,j}^{LM} = [\overrightarrow{h}{k,j}^{LM}; \overleftarrow{h}{k, j}^{LM}]является выходом каждого слоя biLSTM.

Приложение сжимает выходные данные R всех слоев в ELMo в один вектор,ELMo_k = E(R_k;\Theta \epsilon), самый простой метод сжатия — взять результат верхнего слоя в качестве представления токена:E(R_k) = h_{k,L}^{LM}, более общий подход заключается в объединении информации всех слоев по некоторым параметрам:

ELMo_k^{task} = E(R_k;\Theta ^{task}) = \gamma ^{task} \sum_{j=0}^L s_j^{task}h_{k,j}^{LM}  \\

вs_jэто вес от softmax,\gamma— это масштабный параметр, связанный с задачей, который очень важен в процессе оптимизации, а также потому, что выходное распределение каждого слоя BiLM отличается,\gammaМожет играть роль нормализации слоев.

Предварительно обученный BiLM, используемый в статье,Jozefowicz et al.серединаCNN-BIG-LSTMНа основе были сделаны модификации, и окончательная модель2слой biLSTM (4096 единиц, 512 размерных проекций) с остаточными связями, добавленными между первым и вторым слоями. Контекстно-свободное кодирование токенов на уровне символов с использованием как CNN, так и двухслойного Highway. Наконец, модель выводит трехслойное векторное представление для каждого токена.

2.2 Меры предосторожности при обучении моделей

- Регуляризация:

1. Dropout

2. Добавьте к потерям штрафной пункт в виде веса.\lambda||w||^{2}_{2}(Экспериментальные результаты показывают, что ELMo подходит для небольших\lambda )

- Исходный код версии TFРазобрать:

1. Код архитектуры модели в основном находится в классе LanguageModel учебного модуля, который разделен на два этапа: первый шаг — создание слоя встраивания слов или символов (CNN+Highway), второй шаг — создание слой BiLSTM.

2. Загрузите требуемую модель предварительного обучения как класс BidirectionalLanguageModel в модуле модели.

2.3 Использование модели

  1. Преобразуйте вектор ELMoELMo_k^{task}с традиционными векторами словx_{k}сращенный в[x_{k};ELMo_k^{task}]После этого он вводится в РНС, соответствующую конкретной задаче.
  2. Поместите вектор ELMo в часть вывода модели, а вывод конкретной задачи RNNh_{k}сращенный в[h_{k};ELMo_k^{task}].
  3. Пример кода Кераса
import tensorflow as tf
from keras import backend as K
import keras.layers as layers
from keras.models import Model

# Initialize session
sess = tf.Session()
K.set_session(sess)

# Instantiate the elmo model
elmo_model = hub.Module("https://tfhub.dev/google/elmo/1", trainable=True)
sess.run(tf.global_variables_initializer())
sess.run(tf.tables_initializer())

# We create a function to integrate the tensorflow model with a Keras model
# This requires explicitly casting the tensor to a string, because of a Keras quirk
def ElmoEmbedding(x):
    return elmo_model(tf.squeeze(tf.cast(x, tf.string)), signature="default", as_dict=True)["default"]

input_text = layers.Input(shape=(1,), dtype=tf.string)
embedding = layers.Lambda(ElmoEmbedding, output_shape=(1024,))(input_text)
dense = layers.Dense(256, activation='relu')(embedding)
pred = layers.Dense(1, activation='sigmoid')(dense)

model = Model(inputs=[input_text], outputs=pred)

model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
model.summary()

2.4 Преимущества и недостатки модели

преимущество:

  1. Эффект хороший, и в большинстве задач он лучше традиционной модели. Экспериментальные результаты показывают, что ELMo может лучше фиксировать синтаксическую и семантическую информацию, чем векторы слов.
  2. Традиционные предварительно обученные векторы слов могут обеспечить только один уровень представления, а размер словаря ограничен. ELMo обеспечивает представление на уровне символов без ограничения размера словарного запаса.

недостаток:

Скорость низкая, и кодировка каждого токена должна рассчитываться языковой моделью.

2.5 Применимые задачи

  • Question Answering
  • Textual entailment
  • Semantic role labeling
  • Coreference resolution
  • Named entity extraction
  • Sentiment analysis

3. ULMFiT

3.1 Принцип модели и архитектура

Оригинальная ссылка:Universal Language Model Fine-tuning for Text Classification

ULMFiT — это эффективный метод обучения переносу НЛП, основная идея которого заключается в выполнении других задач НЛП путем точной настройки предварительно обученной языковой модели. Языковая модель, используемая в этой статье, относится кMerity et al. 2017aизAWD-LSTMМодель, то есть трехслойная модель LSTM без внимания и ярлыков.

Процесс ULMFiT делится на три этапа:


1. General-domain LM pre-train

  • Предобучение языковых моделей на Викитексте-103.
  • Требования к предварительно обученному корпусу: большой объем и охват общих свойств языка
  • Предварительное обучение хорошо работает для небольших наборов данных, после чего модель может обобщаться только с несколькими образцами.

2. Target task LM fine-tuning

В статье представлены два метода тонкой настройки:

  • Discriminative fine-tuning

Поскольку разные уровни в сети могут захватывать разные типы информации, во время тонкой настройки также следует использовать разные скорости обучения. Автор назначает скорость обучения каждому слою\eta^{l}, после эксперимента обнаруживается, что скорость обучения сначала определяется тонкой настройкой последнего слоя L модели\eta^{L}, а затем рекурсивно выбрать скорость обучения предыдущего слоя для точной настройки, рекурсивная формула:\eta^{l-1} = \eta^{l}/2.6

  • Slanted triangular learning rates (STLR)

Чтобы выбрать параметры для конкретной задачи, идеально позволить параметрам быстро сойтись в подходящей области в начале обучения, а затем настроить их позже. Для достижения этого эффекта автор предлагает метод STLR, то есть LR кратковременно увеличивают в начале тренировки, а затем уменьшают. Как показано в правом верхнем углу рисунка б. Конкретная формула:

cut = floor{(T * cut_frac)} \\

f(x)= \begin{cases} t/cut & \text{t < cut}\\ 1 - \frac{t-cut}{cut*(1/cut\_frac - 1)} & \text{otherwise} \end{cases} \\

\eta_{t} = \eta_{max} \frac{1+p(ratio -1)}{ratio} \\

    • T: number of training iterations
    • cut_frac: fraction of iterations we increase the LR
    • cut: the iteration when we switch from increasing to decreasing the LR
    • p: the fraction of the number of iterations we have increased or will decrease the LR respectively
    • ratio: specifies how much smaller the lowest LR is from thr max LR \eta_{max}
    • \eta_{t} : the LR at iteration t

используется авторомcut\_frac=1, ration=32, \eta_{max} = 0.01

3. Target task classifier fine-tuning

Чтобы завершить тонкую настройку задачи классификации, автор добавляет к последнему слою два линейных блока, каждый с пакетной нормой и отсевом, использует ReLU в качестве функции активации промежуточного слоя и, наконец, выводит распределение вероятностей классификация через softmax. Окончательная тонкая настройка включает в себя следующие этапы:

  • Concat pooling
    Входными данными для первого линейного слоя является объединение состояний последнего скрытого слоя. Поскольку ключевая информация для классификации текста может находиться где угодно в тексте, недостаточно просто использовать выходные данные последнего временного шага. Автор сделает окончательный временной шагh_{T}с максимально возможным количеством временных шаговH= {h_{1},... , h_{T}}После объединения они соединяются вместе вh_{c} = [h_{T}, maxpool(H), meanpool(H)]в качестве ввода.
  • Gradual unfreezing
    Поскольку чрезмерная тонкая настройка приведет к тому, что модель забудет информацию, полученную в результате предыдущего предварительного обучения, автор предлагает метод постепенной разморозки слоев сети, начиная с последнего слоя для разморозки и тонкой настройки, а затем размораживания и тонкой настройки. -настройте все слои от заднего к переднему.
  • BPTT for Text Classification (BPT3C)
    Чтобы точно настроить модель на больших документах, автор делит документы на пакеты фиксированной длины b и записывает среднее и максимальное объединение во время обучения каждого пакета, а градиенты обратно распространяются на пакеты, которые вносят вклад в окончательный прогноз..
  • Bidirectional language model
    В наших экспериментах прямой и обратный LM точно настраиваются независимо, и предсказания обоих усредняются. Результаты комбинации двух имеют улучшение 0,5-0,7.

3.2 Меры предосторожности при обучении моделей

- Исходный код версии PyTorchРазобрать(Урок FastAI 10)

# location: fastai/lm_rnn.py

def get_language_model(n_tok, emb_sz, n_hid, n_layers, pad_token,
                 dropout=0.4, dropouth=0.3, dropouti=0.5, dropoute=0.1, wdrop=0.5, tie_weights=True, qrnn=False, bias=False):
    """Returns a SequentialRNN model.

    A RNN_Encoder layer is instantiated using the parameters provided.

    This is followed by the creation of a LinearDecoder layer.

    Also by default (i.e. tie_weights = True), the embedding matrix used in the RNN_Encoder
    is used to  instantiate the weights for the LinearDecoder layer.

    The SequentialRNN layer is the native torch's Sequential wrapper that puts the RNN_Encoder and
    LinearDecoder layers sequentially in the model.

    Args:
        n_tok (int): number of unique vocabulary words (or tokens) in the source dataset
        emb_sz (int): the embedding size to use to encode each token
        n_hid (int): number of hidden activation per LSTM layer
        n_layers (int): number of LSTM layers to use in the architecture
        pad_token (int): the int value used for padding text.
        dropouth (float): dropout to apply to the activations going from one LSTM layer to another
        dropouti (float): dropout to apply to the input layer.
        dropoute (float): dropout to apply to the embedding layer.
        wdrop (float): dropout used for a LSTM's internal (or hidden) recurrent weights.
        tie_weights (bool): decide if the weights of the embedding matrix in the RNN encoder should be tied to the
            weights of the LinearDecoder layer.
        qrnn (bool): decide if the model is composed of LSTMS (False) or QRNNs (True).
        bias (bool): decide if the decoder should have a bias layer or not.
    Returns:
        A SequentialRNN model
    """
    rnn_enc = RNN_Encoder(n_tok, emb_sz, n_hid=n_hid, n_layers=n_layers, pad_token=pad_token,
                 dropouth=dropouth, dropouti=dropouti, dropoute=dropoute, wdrop=wdrop, qrnn=qrnn)
    enc = rnn_enc.encoder if tie_weights else None
    return SequentialRNN(rnn_enc, LinearDecoder(n_tok, emb_sz, dropout, tie_encoder=enc, bias=bias))


def get_rnn_classifier(bptt, max_seq, n_class, n_tok, emb_sz, n_hid, n_layers, pad_token, layers, drops, bidir=False,
                      dropouth=0.3, dropouti=0.5, dropoute=0.1, wdrop=0.5, qrnn=False):
    rnn_enc = MultiBatchRNN(bptt, max_seq, n_tok, emb_sz, n_hid, n_layers, pad_token=pad_token, bidir=bidir,
                      dropouth=dropouth, dropouti=dropouti, dropoute=dropoute, wdrop=wdrop, qrnn=qrnn)
    return SequentialRNN(rnn_enc, PoolingLinearClassifier(layers, drops))

3.3 Преимущества и недостатки модели

преимущество:

По сравнению с другими методами трансферного обучения (ELMo) он больше подходит для решения следующих задач:

- Неанглийские языки, несколько помеченных данных обучения

- Новые задачи НЛП без современных моделей

- только некоторые задачи с данными тега

недостаток:

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

3.4 Применимые задачи

  • Classification
  • Sequence labeling

4. OpenAI GPT

4.1 Принцип модели и архитектура

Оригинальная ссылка:Improving Language Understanding by Generative Pre-Training(неопубликовано)

OpenAI Transformer — это класс языковых моделей на основе Transformer, которые можно переносить на различные задачи НЛП. Его основная идея такая же, как и в ULMFiT, которая заключается в применении предварительно обученных языковых моделей к различным задачам без максимально возможного изменения структуры модели. Разница в том, что OpenAI Transformer выступает за использование структуры Transformer, а ULMFiT использует языковую модель на основе RNN. Структура сети, используемая в этой статье, выглядит следующим образом:


Процесс обучения модели делится на два этапа:

1. Unsupervised pre-training

Цель первого этапа — предварительно обучить языковую модель с учетом набора токенов.U = {u_{1}, ..., u_{n}}целевая функция состоит в том, чтобы максимизировать функцию правдоподобия:

L_{1}(U) = \sum_{i}logP(u_{i}|u_{i-k}, ..., u_{i-1};\theta) \\

Модель применяет многоголовое самовнимание, а затем добавляет слой прямого распространения с учетом положения и, наконец, выводит распределение:

h_{0}=UW_{e}+W_{p} \\

h_{l} = transformer_block(h_{l-1})  \\

P(u) = softmax(h_{n}W_{e}^{T}) \\

2. Supervised fine-tuning

С предварительно обученной языковой моделью для помеченного обучающего набораC, учитывая входную последовательностьx^{1}, ..., x^{m}и этикеткиy, который можно получить через языковую модельh_{l}^{m}, после выходного слояyСделать прогноз:

P(y|x^{1},...,x^{m})=softmax(h_{l}^{m}W_{y})  \\

Тогда целевая функция:

L_{2}(C)= \sum_{(x,y)}logP(y|x^{1}...,x^{m}) \\

Целевая функция всей задачи:

L_{3}(C)= L_{2}(C)+\lambda * L_{1}(C) \\

4.2 Меры предосторожности при обучении моделей

- Исходный код версии TFРазобрать

# location: finetune-transformer-lm/train.py

def model(X, M, Y, train=False, reuse=False):
    with tf.variable_scope('model', reuse=reuse):
        # n_special=3,作者把数据集分为三份
        # n_ctx 应该是 n_context
        we = tf.get_variable("we", [n_vocab+n_special+n_ctx, n_embd], initializer=tf.random_normal_initializer(stddev=0.02))
        we = dropout(we, embd_pdrop, train)

        X = tf.reshape(X, [-1, n_ctx, 2])
        M = tf.reshape(M, [-1, n_ctx])

        # 1. Embedding
        h = embed(X, we)

        # 2. transformer block
        for layer in range(n_layer):
            h = block(h, 'h%d'%layer, train=train, scale=True)

        # 3. 计算语言模型loss
        lm_h = tf.reshape(h[:, :-1], [-1, n_embd])
        lm_logits = tf.matmul(lm_h, we, transpose_b=True)
        lm_losses = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=lm_logits, labels=tf.reshape(X[:, 1:, 0], [-1]))
        lm_losses = tf.reshape(lm_losses, [shape_list(X)[0], shape_list(X)[1]-1])
        lm_losses = tf.reduce_sum(lm_losses*M[:, 1:], 1)/tf.reduce_sum(M[:, 1:], 1)

        # 4. 计算classifier loss
        clf_h = tf.reshape(h, [-1, n_embd])
        pool_idx = tf.cast(tf.argmax(tf.cast(tf.equal(X[:, :, 0], clf_token), tf.float32), 1), tf.int32)
        clf_h = tf.gather(clf_h, tf.range(shape_list(X)[0], dtype=tf.int32)*n_ctx+pool_idx)

        clf_h = tf.reshape(clf_h, [-1, 2, n_embd])
        if train and clf_pdrop > 0:
            shape = shape_list(clf_h)
            shape[1] = 1
            clf_h = tf.nn.dropout(clf_h, 1-clf_pdrop, shape)
        clf_h = tf.reshape(clf_h, [-1, n_embd])
        clf_logits = clf(clf_h, 1, train=train)
        clf_logits = tf.reshape(clf_logits, [-1, 2])

        clf_losses = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=clf_logits, labels=Y)
        return clf_logits, clf_losses, lm_losses

4.3 Преимущества и недостатки модели

преимущество:

  1. RNN захватывает меньше информации, в то время как Transformer захватывает более широкий диапазон информации.
  2. Скорость вычислений выше, чем у рекуррентной нейронной сети, легко распараллелить
  3. Экспериментальные результаты показывают, что Transformer лучше, чем сети ELMo и LSTM.

недостаток:

Некоторые типы задач требуют корректировки структуры входных данных

4.4 Применимые задачи

  • Natural Language Inference
  • Question Answering and commonsense reasoning
  • Classification
  • Semantic Similarity

5. Резюме

От Wrod Embedding к OpenAI Transformer, перенос обучения в НЛП с начального использования word2vec, GLoVe для представления вектора слов, к ELMo, обеспечивающему распределение веса для первых нескольких слоев, к ULMFiT и тонкой настройке всей модели предварительного обучения OpenAI Transformer, которая значительно улучшает эффект основных задач НЛП. В то же время ряд исследований также показал, что использование языковой модели в качестве модели для предварительного обучения позволяет не только фиксировать грамматическую информацию между словами, но и фиксировать семантическую информацию, предоставляя абстрактную информацию высокого уровня для последующих сетевых слоев. Кроме того, в некоторых аспектах модель на основе преобразователя также демонстрирует лучшие эффекты, чем модель RNN.

Наконец, есть еще много попыток выполнить конкретные задачи.Вы можете использовать вышеуказанные методы, чтобы сделать базовую модель, а затем настроить структуру сети, чтобы улучшить эффект.