Обучение Transformer в OpenNMT-tf: Инициализация модели

Процесс инициализации является критически важным первым шагом в обучении модели, закладывая основу для последующих этапов обучения. Эта сложная процедура включает несколько ключевых шагов, каждый из которых выполняется последовательно, чтобы гарантировать, что модель правильно настроена и функциональна. Благодаря этой структурированной инициализации модель не только подготовлена ​​к обучению, но и оптимизирована для производительности, закладывая основу для эффективного обучения и точных прогнозов.

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

Обучение Transformer

Инициализация

Обучение модели начинается с инициализации этого процесса. Следующие шаги происходят последовательно при запуске обучения:

  • файл конфигурации считывается и финализируется (файлы auto_config и user config объединяются);

├── config = self._finalize_config() модуль runner.py

├── def _finalize_config() модуль runner.py

├── def auto_config() модуль transformer.py

  • Устанавливается тип расчета tensorflow;

При обучении со смешанной точностью (FP16) set_global_policy («mixed_float16») передается в tensorflow.

├── mixed_precision = self._mixed_precision и misc.enable_mixed_precision() модуль runner.py

├── def enable_mixed_precision() модуль misc.py

  • Инициализируется модель Transformer (или другой тип модели, определенный пользователем);

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

Если инициализировать модель до инициализации типа расчета, значение в атрибутах модели не изменится и будет по умолчанию float32:

_dtype_policy: <Policy “float32”>

_compute_dtype_object: <dtype: 'float32'>

├── model = self._init_model (config) модуль runner.py

├── def _init_model() модуль runner.py

  • оптимизатор модели определен и инициализирован.

Из автоконфигурации модели Transformer берется имя оптимизатора, которое по умолчанию установлено на LazyAdam. Этот оптимизатор реализован в библиотеке TensorFlow Addons.

Функция затухания NoamDecay инициализируется следующими параметрами:

━ 1) scale - задается значение из параметра Learning rate файла конфигурации обучения (в нашем примере значение равно 2);

━ 2) model_dim - задается значение из параметра num_units (размер Rnn) файла конфигурации обучения (в нашем примере значение равно 4);

━ 3) warmup_steps - задается значение из параметра Warmup steps файла конфигурации обучения (в нашем примере значение равно 8000).

Класс-оболочка ScheduleWrapper инициализируется для дополнения поведения планировщика скорости обучения следующими параметрами:

━ 1) schedule— инициализируется выше функции затухания NoamDecay;

━ 2) step_start — задается значение из параметра start_decay_steps файла конфигурации обучения (значение по умолчанию 0 );

━ 3) step_duration — задается значение из параметра decay_step_duration файла конфигурации обучения (значение по умолчанию 1 );

━ 4) minimum_learning_rate — задается значение из параметра Minimum learning rate файла конфигурации обучения (в нашем примере значение равно 0,0001).

Класс оптимизатора LazyAdam инициализируется следующими параметрами:

━ 1) l earning_rate - класс ScheduleWrapper, инициализированный выше;

━ 2) kwargs - словарь бета-коэффициентов из параметра optimizer_params файла конфигурации обучения (в нашем примере {'beta_1': 0.9, 'beta_2': 0.998} );

━ 3) при обучении со смешанной точностью (FP16) класс LazyAdam наследуется от класса tf.keras. mixed_precision . LossScaleOptimizer, который инициализирует следующие параметры:

  • initial_scale = 32 768 - значение, на которое будет скорректировано значение, полученное из функции потерь;
  • dynamic_growth_steps = 2 000 - как часто обновлять значение, до которого будет скорректировано значение функции потерь.

├── optimizer = model.get_optimizer() модуль runner.py

├── def get_optimizer() модуль model.py

├── def make_learning_rate_schedule() модуль schedules/lr_schedules.py

├── def init() class NoamDecay (tf.keras.optimizers.schedules.LearningRateSchedule) модуль schedules/lr_schedules.py

├── def init() class ScheduleWrapper schedules/lr_schedules.py

├── ef make_optimizer() модуль optimizers/utils.py

  • установлен на batch_size_multiple;

Если активирована функция смешанной точности или Jit-компиляции, batch_size_multiple будет равен 8, в противном случае — 1.

├── batch_size_multiple = (...) модуль runner.py

  • создана функция создания и преобразования набора данных;

├── dataset_fn = (...) модуль runner.py

  • если передано значение effective_batch_size, вычисляется значение, при котором будет обновляться градиент;

├── accum_steps = _count_batch_accum() модуль runner.py

├── def _count_batch_accum() модуль runner.py

  • Инициализируются эмбеддинги для source и для target;

Размерность вложений будет определяться размером словаря и размером параметра num_units (размер Rnn ), где m — количество токенов в словаре, n — значение num_units. (Изображение 1 — matrix_m_n )

Вложения инициализируются через объект tf.keras.Layer, функцию add_weight, которая вызывается через функцию def build() класса WordEmbedder.

├── source_inputter = inputters.WordEmbedder(embedding_size=num_units)

├── def build()

├── target_inputter = inputters.WordEmbedder(embedding_size=num_units)

├── def build()

Например, для словаря размером 700 токенов и num_units (размер Rnn) со значением 8 будет сгенерирована матрица, содержащая 700 строк по 8 чисел в каждой. Вложения будут выглядеть примерно так:

Значения, представленные в матрице внедрения, формируются по определенному механизму. Например, для матрицы размерностью 700x8:

У нас будет матрица размерностью 700 x 8, где значения будут от -0,0920 до 0,0920, взятые случайным образом из равномерного распределения. Описанный выше механизм называется инициализацией Ксавье. Реализация в tensorflow:

├── class GlorotNormal().init()

├── class VarianceScaling().call()

  • инициализируются веса (слои) модели;

├── encoder = SelfAttentionEncoder() модуль transformer.py

├── self.layer_norm = common.LayerNorm() модуль self_attention_encoder.py

├── LayerNorm() модуль common.py

├── SelfAttentionEncoderLayer() модуль self_attention_encoder.py

├── self.self_attention = MultiHeadAttention() модуль layers/transformer.py

├── def build() модуль layers/transformer.py

├── TransformerLayerWrapper(self.self_attention) модуль layers/transformer.py

├── self.ffn = FeedForwardNetwork() модуль layers/transformer.py

├── TransformerLayerWrapper(self.ffn) модуль layers/transformer.py

├── decoder = SelfAttentionDecoder() модуль transformer.py

├── self.layer_norm = common.LayerNorm() модуль self_attention_decoder.py

├── LayerNorm() модуль common.py

├── SelfAttentionDecoderLayer() модуль self_attention_decoder.py

├── self.self_attention = MultiHeadAttention() модуль layers/transformer.py

├── def build() модуль layers/transformer.py

├── TransformerLayerWrapper(self.self_attention) модуль layers/transformer.py

├── attention = MultiHeadAttention() модуль layers/transformer.py

├── TransformerLayerWrapper(attention) модуль layers/transformer.py

├── self.ffn = FeedForwardNetwork() модуль layers/transformer.py

├── TransformerLayerWrapper(self.ffn) модуль layers/transformer.py

Как изначально выглядит модель, веса и их значения показаны на примере небольшой размерности сети:

  • vocab: 26
  • num_units: 4
  • num_layers: 1
  • num_heads: 2
  • ffn_inner_dim: 1
  • maximum_relative_position: 8

Модель можно схематически изобразить следующим образом. (Изображение 2 - модель)

Ядерные (т.е. основные) веса модели инициализируются с помощью механизма «Инициализация Ксавье», описанного выше. Запросы, ключи, значения и выходные слои инициализируются через tf.keras.layers.Dense с добавлением вектора смещения 'use_bias': True. Веса FeedForwardNetwork также инициализируются через tf.keras.layers.Dense с активацией линейного слоя tf.nn.relu. Слой нормализации инициализируется через tf.keras.layers.LayerNormalization, где бета-измерение будет представлено нулями, а гамма-измерение — единицами.

Нормализация слоя (нормализация слоя, LN) — это метод глубокого обучения, используемый для стабилизации процесса обучения и повышения производительности нейронных сетей. Он решает проблему внутреннего ковариационного сдвига (ICS), когда распределение активаций внутри слоя изменяется в процессе обучения, что затрудняет эффективное обучение сети. Статья, в которой была представлена ​​методика нормализации слоя Layer Normalization

При инициализации модели должно выполняться следующее условие: num_units % num_heads, т.е. размерность эмбеддингов (и соответственно запросов, ключей и значений) должна быть кратна количеству голов в MultiHeadAttention.

По сути, матрицы queries, keys и values делятся на указанное в параметре num_heads число и формируются матрицы меньшего размера, количество которых равно num_units // num_heads. Алгоритм реализован в функции split_heads модуля transformer.py. (Изображение 3 - Multi Head Attention)

Рассмотрим алгоритм разбиения матриц queries, keys и values по количеству голов. Для простоты восприятия примем размерность num_units равной 4, а количество голов num_heads равным 2.

Например, у нас есть партия токенов:

Для каждого токена из матрицы встраивания извлекается векторное представление токена (механизм описан ниже) и формируется матрица векторов. Вычисляется размерность батча: input_shapes = [2, 3, 4]. В пакетах есть 2 последовательности, каждая последовательность имеет 3 токена, каждый токен представлен вектором размерности 4. Следующий шаг — изменение размерности матрицы входов:

- outputs = tf.reshape(inputs, [shape[0], shape[1], num_heads, shape[2] // num_heads]) → tf.reshape(inputs, [2, 3, 2, 4 // 2])

- outputs = tf.transpose(outputs, perm=[0, 2, 1, 3])

После изменения размерности мы получаем матрицы меньшей размерности. (Изображение 4 — Матрица изменения формы)

Это конец процесса инициализации модели. После этого начинается сам процесс обучения.

Заключение

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


Вас ждет еще больше увлекательного чтения

Машинный перевод в военной сфере

Машинный перевод в военной сфере

April 16, 2025

Преобразование текста в речь для колл-центров

Преобразование текста в речь для колл-центров

January 8, 2025

ИИ-контент vs. человеческий подход: поиск оптимального баланса

ИИ-контент vs. человеческий подход: поиск оптимального баланса

December 18, 2024

×