Мульти-меточная многоклассовая бинарная числовая закодированная выходная информация не может быть взвешена в torch.nn.functional.cross_entropy.

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

У меня очень уникальная задача многометочной многоклассовой классификации. У меня есть нейронная сеть, которая выдает 6 логитов. Количество классов, которые мы пытаемся предсказать, составляет 2^6, то есть я кодирую свой вывод в двоичном формате. Причина этого в том, что если я просто сделаю последний слой torch.nn.Linear с 64 нейронами, моя модель становится слишком большой. Теперь я также работаю с очень несбалансированным набором данных, где некоторые метки встречаются чаще других. У меня есть вес torch.Tensor размером 64, который я пытаюсь передать аргументу weight функции torch.nn.functional.cross_entropy, но получаю ошибку:

RuntimeError: cross_entropy: weight tensor should be defined either for all 6 classes or no classes but got weight tensor of shape: [64]

Как мне назначить вес для каждой из 2^6 перестановок вывода?

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

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

Проблема с использованием torch.nn.functional.cross_entropy

Вы упомянули о том, что ваша модель выводит 6 логитов, и вы хотите использовать зерновую (бинарную) кодировку для представления 64 (2^6) классов. Однако функция torch.nn.functional.cross_entropy ожидает, что весовая тензор будет иметь тот же размер, что и количество классов в задаче классификации. Поскольку у вас 6 классов, функция ожидает веса в виде тензора размерности [6], а ваш тензор имеет размерность [64]. Именно это и вызывает ошибку.

Как задать веса для 2^6 комбинаций

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

  1. Аггрегация весов:

    • Вместо индивидуального назначения веса для всех 64 комбинаций, вы можете сгруппировать данные по классам и рассчитать вес для каждого из 6 классов.
    • При этом каждый класс будет иметь свой вес (для 0 и 1), который можете использовать в функции cross_entropy.
  2. Модификация меток:

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

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

Пример реализации пользовательской функции потерь

Вот пример того, как вы можете начать писать пользовательскую функцию потерь:

import torch

def custom_loss(output, target, weights):
    # Преобразование логитов в вероятности
    probability = torch.softmax(output, dim=1)

    # Вычисление потерь для каждого класса
    loss = -torch.sum(target * torch.log(probability + 1e-10), dim=1)

    # Применение весов к потерям
    weighted_loss = loss * weights

    return weighted_loss.mean()

Заключение

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

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

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