Несбалансированные наборы данных — распространенная проблема в задачах классификации, когда количество экземпляров в одном классе значительно меньше, чем количество экземпляров в другом классе. Это приведет к предвзятым моделям, которые плохо работают с классом меньшинства.
Взвешенная функция потерь — это модификация стандартной функции потерь, используемой при обучении модели. Веса используются для назначения более высокого штрафа за неправильную классификацию класса меньшинства. Идея состоит в том, чтобы сделать модель более чувствительной к классу меньшинства за счет увеличения стоимости неправильной классификации этого класса.
Наиболее распространенный способ реализации взвешенной функции потерь — присвоить больший вес классу меньшинства и меньший вес классу большинства. Веса могут быть обратно пропорциональны частоте классов, так что класс меньшинства получает больший вес, а класс большинства получает меньший вес.
В этом посте я покажу вам, как добавить веса к общим функциям потерь pytorch.
Бинарная классификация
Функция torch.nn.BCEWithLogitsLoss
— это обычно используемая функция потерь для задач бинарной классификации, где выход модели представляет собой значение вероятности от 0 до 1. Она сочетает в себе сигмовидную функцию активации с бинарной кросс-энтропийной потерей.
Для несбалансированных наборов данных, где количество экземпляров в одном классе значительно меньше, чем в другом, функцию torch.nn.BCEWithLogitsLoss
можно изменить, добавив параметр веса в функцию потерь. Параметр веса позволяет назначать разные веса для положительных и отрицательных классов.
Параметр веса представляет собой тензор размера [batch_size]
, который содержит значение веса для каждого образца в пакете.
Вот пример:
import torch import torch.nn as nn # Define the BCEWithLogitsLoss function with weight parameter weight = torch.tensor([0.1, 0.9]) # higher weight for positive class criterion = nn.BCEWithLogitsLoss(weight=weight) # Generate some random data for the binary classification problem input = torch.randn(3, 1) target = torch.tensor([[0.], [1.], [1.]]) # Compute the loss with the specified weight loss = criterion(input, target) print(loss)
мы устанавливаем вес положительного класса на 0,9 и вес отрицательного класса на 0,1. input
тензор содержит логиты, предсказанные моделью. target
тензор содержит метки истинности для задачи бинарной классификации.
Примечание. Установите веса вручную на 0,1 и 0,9, исходя из предположения, что положительный класс имеет только 10% образцов.
Чтобы рассчитать веса, вы можете вычислить вес для каждого класса следующим образом:
weight_for_class_i = total_samples / (num_samples_in_class_i * num_classes)
где total_samples
— общее количество выборок в наборе данных, num_samples_in_class_i
— количество выборок в классе i, а num_classes
— общее количество классов (в случае двоичной классификации num_classes
равно 2).
Если у вас есть проблема бинарной классификации с 1000 выборками, где 900 выборок относятся к классу 0, а 100 — к классу 1, рассчитывайте веса следующим образом:
weight_for_class_0 = 1000 / (900 * 2) = 0.5556 weight_for_class_1 = 1000 / (100 * 2) = 5.0000
и весовой параметр torch.nn.BCEWithLogitsLoss
для тензора весов размера 2:
import torch import torch.nn as nn weight = torch.tensor([0.5556, 5.0000]) # higher weight for class 1 criterion = nn.BCEWithLogitsLoss(weight=weight)
Примечание. Конкретная формула и метод расчета весов могут зависеть от проблемы и набора данных, и могут быть рассмотрены другие подходы, такие как использование методов повторной выборки или других функций потерь, предназначенных для обработки дисбаланса классов.
В дополнение к параметру weight
, torch.nn.BCEWithLogitsLoss
также имеет параметр pos_weight
, который представляет собой более простой способ указать вес для положительного класса в задаче бинарной классификации.
Параметр pos_weight
— это скаляр, представляющий вес для положительного класса. Это эквивалентно установке для параметра weight
значения [1, pos_weight]
, где вес для отрицательного класса равен 1.
import torch import torch.nn as nn # Define the BCEWithLogitsLoss function with pos_weight parameter pos_weight = torch.tensor([3.0]) # higher weight for positive class criterion = nn.BCEWithLogitsLoss(pos_weight=pos_weight) # Generate some random data for the binary classification problem input = torch.randn(3, 1) target = torch.tensor([[0.], [1.], [1.]]) # Compute the loss with the specified pos_weight loss = criterion(input, target) print(loss)
Установите для параметра pos_weight
значение 3.0, что означает, что вес для положительного класса в 3 раза больше, чем для отрицательного класса. Мы вычисляем убыток, используя функцию criterion
с указанным pos_weight
.
Если вы укажете оба параметра weight
и pos_weight
, параметр pos_weight
имеет приоритет над весом для положительного класса.
Если вы установите для pos_weight
значение, отличное от 1,0, вес для положительного класса в тензоре weight
будет игнорироваться.
Мультиклассовая классификация
Cross-Entropy Loss обычно используется в задачах классификации нескольких классов. Он вычисляет отрицательное логарифмическое правдоподобие предсказанного распределения классов по сравнению с истинным распределением классов. При работе с несбалансированными наборами данных некоторые классы могут иметь больше или меньше выборок, чем другие, и это может привести к смещению прогнозов модели в сторону более частых классов.
Чтобы решить эту проблему, можно использовать параметр weight
в torch.nn.CrossEntropyLoss
для применения веса к каждому классу. Веса могут быть указаны в виде одномерного тензора или списка и должны иметь ту же длину, что и количество классов. Тогда потери рассчитываются следующим образом:
loss(x, y) = -weight[y] * log(exp(x[y]) / sum(exp(x)))
где x
— результат модели, y
— целевой класс, exp
— экспоненциальная функция, а sum(exp(x))
— сумма экспонент по всем классам. Вес для истинного класса умножается на отрицательную логарифмическую вероятность истинного класса, поэтому потеря взвешивается для недопредставленных классов.
Вот пример использования параметра weight
в torch.nn.CrossEntropyLoss
для задачи классификации с тремя несбалансированными классами.
Предположим, у нас есть набор данных с 1000 выборками, а целевая переменная имеет три класса: класс A, класс B и класс C. Распределение выборок в наборе данных выглядит следующим образом:
- Класс А: 100 образцов
- Класс B: 800 образцов
- Класс C: 100 образцов
Чтобы устранить дисбаланс классов, мы можем присвоить каждому классу вес, обратно пропорциональный его частоте. Вес каждого класса можно рассчитать следующим образом:
- Класс А: 1000/100 = 10
- Класс В: 1000/800 = 1,25
- Класс С: 1000 / 100 = 10
Мы можем создать тензор весов, отражающий эти веса, следующим образом:
import torch weights = torch.tensor([10, 1.25, 10])
И используйте этот весовой тензор в torch.nn.CrossEntropyLoss
следующим образом:
loss_fn = torch.nn.CrossEntropyLoss(weight=weights)
Когда мы используем эту функцию потерь для обучения модели, классы A и C будут вносить больший вклад в потери, чем класс B, из-за взвешенного эффекта тензора веса. Это помогает сбалансировать влияние различных классов на обучение модели и может улучшить производительность модели в недостаточно представленных классах.
В PyTorch параметр torch.nn.CrossEntropyLoss
, label_smoothing
используется для сглаживания целевых значений с горячим кодированием, чтобы побудить модель быть менее уверенной в своих прогнозах и предотвратить переоснащение обучающих данных.
Это сглаживание достигается добавлением небольшого значения (т. е. коэффициента сглаживания) к недиагональным элементам целевых значений с горячим кодированием и вычитанием этого же значения из диагональных элементов. Это приводит к снижению достоверности прогнозов модели и побуждает ее исследовать более широкий спектр решений.
Параметр label_smoothing
принимает значение от 0 до 1, 0 означает, что сглаживание не применяется, а 1 означает, что применяется максимальное сглаживание. Типичное значение label_smoothing
составляет около 0,1. Тогда потери рассчитываются следующим образом:
loss(x, y) = -((1 - label_smoothing) * log(exp(x[y]) / sum(exp(x))) + (label_smoothing / K))
x — результат модели, y — целевой класс, exp — экспоненциальная функция, sum(exp(x)) — сумма экспонент по всем классам, а K — количество классов. Коэффициент сглаживания умножается на равномерную априорную вероятность для каждого класса, которая равна 1/K, и получается более обобщенная модель.
Оба параметра label_smoothing
и weight
можно использовать для решения проблем, связанных с дисбалансом классов и переоснащением в задачах классификации нескольких классов. Однако эти два параметра работают по-разному и имеют разные варианты использования.
Параметр weight
используется для применения веса к каждому классу при расчете потерь, что может быть полезно при работе с несбалансированными наборами данных. Вес для истинного класса умножается на отрицательное логарифмическое правдоподобие истинного класса, поэтому потери для недопредставленных классов увеличиваются. Параметр weight
не влияет на прогнозируемые вероятности или уверенность модели в своих прогнозах, а регулирует вес, присвоенный каждому классу при расчете потерь.
Параметр label_smoothing
используется для сглаживания целевых значений с горячим кодированием, чтобы побудить модель быть менее уверенной в своих прогнозах и предотвратить переоснащение обучающих данных. Сглаживание достигается добавлением небольшого значения (т. е. коэффициента сглаживания) к недиагональным элементам целевых значений с однократным кодированием и вычитанием этого же значения из диагональных элементов. Это приводит к снижению достоверности прогнозов модели и побуждает ее исследовать более широкий спектр решений. Параметр label_smoothing
не влияет на вес, присвоенный каждому классу при расчете убытков, а корректирует целевые значения, используемые при расчете убытков.
В общем, параметр weight
полезен при работе с несбалансированными наборами данных, где стоимость неправильной классификации не одинакова для всех классов. С другой стороны, параметр label_smoothing
полезен при работе с переобучением и высоконадежными прогнозами, когда модель слишком уверена в своих прогнозах и не исследует широкий спектр решений.
оба параметра weight
и label_smoothing
можно использовать вместе для решения проблем дисбаланса классов и переобучения в задачах классификации с несколькими классами.
Однако два параметра не всегда могут использоваться вместе, и их использование зависит от конкретных характеристик набора данных и рассматриваемой проблемы. Важно поэкспериментировать с различными комбинациями гиперпараметров, включая label_smoothing
и weight
, чтобы определить наилучший подход к данной проблеме.
Многоуровневая классификация
Классификация с несколькими метками — это тип задачи классификации, когда объект или экземпляр могут одновременно принадлежать к одному или нескольким классам. Другими словами, вместо того, чтобы назначать каждому экземпляру одну метку, ему можно назначить несколько меток. Это отличается от традиционных задач классификации, где каждому экземпляру присваивается одна метка.
Бинарная перекрестная энтропийная потеря обычно используется в задачах бинарной классификации, но также может использоваться в классификации с несколькими метками, рассматривая каждую метку как отдельную задачу бинарной классификации. Он измеряет разницу между предсказанными вероятностями и фактическими метками для каждого класса отдельно.
мы можем установить параметр weight
, и pos_weight
подобно двоичной классификации.
В итоге
Несбалансированные наборы данных — распространенная проблема в машинном обучении, когда один класс данных может быть значительно более распространенным, чем другой. Это может привести к проблемам при попытке обучить модель классификации, поскольку модель может стать смещенной в сторону более распространенного класса. Одно из решений этой проблемы проблема заключается в использовании функции взвешенных потерь во время обучения. Функция взвешенных потерь присваивает более высокий вес ошибкам, сделанным в классе меньшинства, тем самым помогая модели уделять больше внимания этим образцам. Используя функцию взвешенных потерь, модель может научиться лучше различать классы меньшинства и большинства, что приводит к повышению производительности несбалансированных наборов данных.
Если этот пост был вам полезен, пожалуйста, хлопайте👏 и подписывайтесь на меня😊.