Что такое функция активации в нейронных сетях?

Ответ

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

Ключевые функции и их применение:

  1. ReLU (Rectified Linear Unit): f(x) = max(0, x)

    • Плюсы: Вычислительно простая, не насыщается (решает проблему затухающего градиента).
    • Минусы: "Умирающий ReLU" (нейрон может перестать активироваться).
    • Использование: Стандартный выбор для скрытых слоев большинства архитектур.
  2. Sigmoid: f(x) = 1 / (1 + e^{-x})

    • Свойства: Сжимает выход в диапазон (0, 1).
    • Использование: Исторически использовалась повсеместно, сейчас в основном только в выходном слое для задач бинарной классификации (вероятность).
  3. Softmax: f(x_i) = e^{x_i} / Σ_j e^{x_j}

    • Свойства: Преобразует вектор в распределение вероятностей (сумма выходов = 1).
    • Использование: Исключительно для выходного слоя в задачах многоклассовой классификации.

Пример с NumPy:

import numpy as np

def relu(x):
    return np.maximum(0, x)

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def softmax(x):
    exp_x = np.exp(x - np.max(x))  # Стабильная версия (сдвиг)
    return exp_x / exp_x.sum(axis=0)

# Выход нейрона
z = np.array([2.0, 1.0, 0.1])
print("ReLU:", relu(z))
print("Sigmoid:", sigmoid(z))
print("Softmax:", softmax(z))  # Сумма = 1.0

Ответ 18+ 🔞

А, слушай, про функции активации! Ну это же, ёпта, самая соль всей этой нейросетевой кухни. Представь себе, что у тебя есть нейрон — такой маленький вычислительный уродец, который получает кучу сигналов, умножает их на какие-то веса, суммирует... И вот тут-то начинается самое интересное. Если бы он просто взял и выдал эту сумму на-гора, то вся твоя многослойная сеть, какой бы глубокой она ни была, превратилась бы в один большой, скучный, линейный кусок говна. Доверия ебать ноль к такой модели, она нихрена сложного не выучит. Всё, накрылась бы она медным тазом.

А вот функция активации — это как раз та самая нелинейная приправа, которая всё и меняет. Она этот скучный линейный результат пропускает через какую-нибудь хитрожопую формулу, и на выходе получается уже что-то сочное, с изгибом. Благодаря этому сеть и может учиться всяким замудрённым паттернам, которые в данных спрятаны.

Ну и кто у нас тут главные по активациям?

  1. ReLU (Выпрямитель, Rectified Linear Unit): f(x) = max(0, x)

    • Что делает: Всё, что меньше нуля, зануляет. Всё, что больше — пропускает как есть. Проще пареной репы.
    • Чем хорош: Быстрый, как угорелый. Не страдает от "затухающего градиента" — это когда на глубоких слоях обучающий сигнал просто сдыхает, и веса не обновляются. Тут такого нет.
    • Чем плох: Может "умереть". Если нейрон постоянно получает на вход отрицательные значения, он навсегда выдаёт ноль и перестаёт учиться. Но в целом, это стандарт де-факто для скрытых слоёв. Просто берёшь и ставишь везде.
  2. Сигмоида (Sigmoid): f(x) = 1 / (1 + e^{-x})

    • Что делает: Сжимает любое число в аккуратненький промежуток от 0 до 1. Получается такая плавная S-образная кривая.
    • История: Раньше её пихали везде, пока не поняли, что с ней учиться — терпения ноль ебать, особенно в глубоких сетях. Градиенты на неё затухают просто пиздец.
    • Где сейчас: В основном доживает свой век в самом последнем, выходном слое, если ты решаешь задачу бинарной классификации (да/нет, кот/собака). Потому что её выход можно интерпретировать как вероятность.
  3. Софтмакс (Softmax): f(x_i) = e^{x_i} / Σ_j e^{x_j}

    • Что делает: Это уже не для одного нейрона, а для целого слоя. Берёт вектор из чисел и превращает его в распределение вероятностей. Все выходы становятся положительными, и их сумма равна ровно единице. Удивление пиздец — как удобно!
    • Где используется: ТОЛЬКО ИСКЛЮЧИТЕЛЬНО на выходе, когда классов больше двух (типа распознать цифру от 0 до 9). Каждый выходной нейрон выдаст тебе вероятность того, что картинка — это его цифра.

Ну и как это в коде выглядит, ёбана? Смотри, тут всё просто, даже полупидор разберётся.

import numpy as np

def relu(x):
    return np.maximum(0, x)  # Всё, что меньше нуля — нахуй, остальное — ок.

def sigmoid(x):
    return 1 / (1 + np.exp(-x))  # Классика, но уже старая.

def softmax(x):
    exp_x = np.exp(x - np.max(x))  # Хитрый стабильный трюк, чтобы не взорваться
    return exp_x / exp_x.sum(axis=0)  # Делим каждое на сумму всех — вуаля, вероятности!

# Допустим, наш нейрон насчитал вот такой векторчик
z = np.array([2.0, 1.0, 0.1])
print("ReLU:", relu(z))      # Отрицательных нет, так что всё пропустит
print("Sigmoid:", sigmoid(z)) # Всё загонит между нулём и единицей
print("Softmax:", softmax(z)) # Главное — сумма будет ровно 1.0, можно на что-то делать ставки!

Вот и вся магия. Без этих нелинейных преобразований твоя нейросеть была бы просто хуй в пальто — выглядит сложно, а внутри пустота и линейность.