Softmax — это математическая функция, которая берёт вектор произвольных вещественных чисел и преобразует его в вектор вероятностей. Каждое значение на выходе лежит в диапазоне от 0 до 1, а их сумма всегда равна единице. Благодаря этому выходные значения можно интерпретировать как уверенность модели в принадлежности объекта к каждому из классов.
В контексте нейросетей softmax почти всегда стоит последним слоем. Он не меняет архитектуру сети, а лишь нормирует уже вычисленные логиты — «сырые» оценки, полученные после линейного преобразования.
Как это работает
Функция применяется покомпонентно к вектору логитов \(z = (z_1, z_2, \dots, z_K)\), где \(K\) — число классов. Сначала каждый логит возводится в экспоненту \(e^{z_i}\). Это гарантирует положительность результата. Затем каждое экспоненциальное значение делится на сумму всех таких значений по вектору.
Формула выглядит так:
\[ \text{softmax}(z)_i = \frac{e^{z_i}}{\sum_{j=1}^{K} e^{z_j}} \]
Экспонента сильно увеличивает разрыв между большими и малыми логитами. Если один логит заметно выше остальных, его вероятность после softmax будет близка к единице, а остальные — к нулю. Если логиты близки, распределение получится более равномерным.
Важная деталь: softmax инвариантен к сдвигу. Если ко всем логитам прибавить одно и то же число, результат не изменится. На этом свойстве основан трюк численной стабилизации — вычитание максимума из всех логитов перед экспоненцированием.
Зачем это нужно
Основная задача softmax — превратить неограниченные выходы сети в вероятностную интерпретацию. Это критично для многоклассовой классификации: распознавания объектов на изображениях, определения темы текста, тегирования, выбора следующего токена в языковых моделях.
Без softmax выходы сети остаются произвольными числами, которые нельзя сравнивать как вероятности и напрямую оптимизировать с помощью кросс-энтропии. Softmax делает выход совместимым с функцией потерь и позволяет применять стандартные методы обучения.
Кроме того, softmax используется не только в финальном слое. Например, в механизме внимания (attention) он нормирует веса, с которыми модель «смотрит» на разные части входных данных.
Примеры
- Классификация рукописных цифр (MNIST). Сеть с 10 выходными нейронами выдаёт логиты, например \([2.1, -0.5, 0.3, \dots]\). После softmax вероятность для цифры «0» может составить 0.78, для «1» — 0.05, для остальных — меньше.
- Языковая модель при генерации текста. После обработки контекста модель выдаёт логиты для каждого токена словаря (десятки тысяч значений). Softmax превращает их в вероятности, и следующий токен выбирается сэмплированием из этого распределения.
- Механизм self-attention в трансформерах. Для каждого запроса (query) вычисляются оценки сходства со всеми ключами (keys). Softmax нормирует эти оценки, чтобы веса внимания суммировались в единицу и модель могла «смешивать» значения (values) в нужной пропорции.
- Многоклассовая классификация в медицинской диагностике. Модель по снимку определяет вероятность наличия одного из нескольких заболеваний. Softmax даёт врачу не просто «метку», а распределение уверенности, что позволяет оценить риски.
Формула или метрика
Прямая формула softmax для \(K\) классов:
\[ \sigma(z)_i = \frac{e^{z_i}}{\sum_{j=1}^{K} e^{z_j}}, \quad i = 1, \dots, K \]
С температурой \(T\) формула принимает вид:
\[ \sigma(z, T)_i = \frac{e^{z_i / T}}{\sum_{j=1}^{K} e^{z_j / T}} \]
При \(T = 1\) это обычный softmax. При \(T > 1\) распределение становится более «гладким», при \(T \to 0\) — приближается к one-hot вектору (argmax).
Типичные ошибки
- Использование softmax для бинарной классификации. Для двух классов достаточно одного выхода с сигмоидой. Softmax с двумя нейронами технически работает, но избыточен и может замедлять обучение.
- Применение softmax перед функцией потерь, которая сама его включает. Многие фреймворки (PyTorch, TensorFlow) используют `CrossEntropyLoss` или `softmax_cross_entropy_with_logits`, которые ожидают на входе логиты, а не вероятности. Двойной softmax искажает градиенты.
- Игнорирование численной стабильности. Прямое вычисление \(e^{z_i}\) при больших логитах приводит к переполнению. Стандартное решение — вычитать максимум: \(e^{z_i — \max(z)}\).
- Слишком высокая температура при генерации текста. \(T > 1.5\) делает распределение почти равномерным, и модель начинает выдавать бессвязные последовательности. Слишком низкая \(T\) (близкая к 0) приводит к зацикливанию на одних и тех же фразах.
Как улучшить
- Вычитайте максимум перед экспонентой. Это не меняет математический результат, но предотвращает переполнение. Реализуйте softmax через `x — max(x)`.
- Подбирайте температуру осознанно. Для генерации текста начните с \(T = 0.7\)–\(0.9\). Для задач, где нужна максимальная точность (например, классификация), оставляйте \(T = 1\) или используйте argmax после softmax.
- Следите за размером словаря при языковом моделировании. Softmax по десяткам тысяч токенов — вычислительно дорогая операция. Исследуйте альтернативы: sampled softmax, hierarchical softmax, noise contrastive estimation.
- Не добавляйте softmax вручную, если фреймворк уже делает это внутри лосса. Проверьте документацию: в PyTorch `nn.CrossEntropyLoss` принимает логиты, а не вероятности.
- Для бинарной классификации используйте сигмоиду. Один выход с сигмоидой и бинарной кросс-энтропией проще, быстрее и численно устойчивее, чем два выхода с softmax.