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

Инициализация
Обучение модели начинается с инициализации этого процесса. Следующие шаги происходят последовательно при запуске обучения:
- файл конфигурации считывается и финализируется (файлы 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 — Матрица изменения формы)

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