Должен ли изменяться распределение весов при тонкой настройке классификатора на основе трансформеров?

Вопрос или проблема

Я использую предобученную модель DistilBERT от Huggingface с пользовательской классификационной головой, которая почти такая же, как в референсной реализации:

class PretrainedTransformer(nn.Module):
    def __init__(
        self, target_classes):
        super().__init__()
        base_model_output_shape=768
        self.base_model = DistilBertModel.from_pretrained("distilbert-base-uncased")
        self.classifier = nn.Sequential(
            nn.Linear(base_model_output_shape, out_features=base_model_output_shape),
            nn.ReLU(),
            nn.Dropout(0.2),
            nn.Linear(base_model_output_shape, out_features=target_classes),
        )

        for layer in self.classifier:
            if isinstance(layer, nn.Linear):
                layer.weight.data.normal_(mean=0.0, std=0.02)
                if layer.bias is not None:
                    layer.bias.data.zero_()

    def forward(self, input_, y=None):
        X, length, attention_mask = input_
        base_output = self.base_model(X, attention_mask=attention_mask)[0]
        base_model_last_layer = base_output[:, 0]
        cls = self.classifier(base_model_last_layer)
        return cls

Во время обучения я использую линейный график разогрева LR с максимальным LR=5-e5 и потерю перекрестной энтропии.
В общем, модель способна обучаться на моем наборе данных и достигать высоких метрик точности/полноты.

Мой вопрос:

Должны ли распределения весов и смещений в классификационных слоях изменяться больше во время обучения? Кажется, что веса почти не меняются вообще, даже когда я не инициализирую их, как в коде (со средним=0.0 и std=0.02). Является ли это признаком того, что с моей моделью что-то не так, или это просто потому, что добавленные мною слои избыточны и модель не учится ничему новому?

Посмотрите на изображение весов из tensorboard:
веса классификационных слоев

Сложно судить, просто глядя на распределение весов. Вы будете в лучшем положении, если также проверите следующие вещи:

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

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

Проведение вышеуказанных 2 анализов укрепит ваше понимание текущей ситуации с обучением модели.

Ответ или решение

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

  1. Проверка уменьшения потерь во время обучения. Если ваша модель действительно обучается, потери (loss) должны уменьшаться по мере повышения количества эпох. Если потери не уменьшаются, это может указывать на проблему с обучением. Также важно проверять, как метрики, такие как точность (accuracy) и полнота (recall), изменяются в процессе обучения. Если эти метрики улучшаются, это означает, что модель успешно обучается, даже если веса в классификационном слое меняются незначительно.

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

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

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

  5. Мониторинг переменных во время обучения. Используйте такие инструменты, как TensorBoard, чтобы визуализировать изменения весов, градиентов и потерь во времени. Это поможет вам лучше понять процесс обучения и частоты обновлений весов.

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

Оцените материал
Добавить комментарий

Капча загружается...