Skip to content

Files

Latest commit

 

History

History
207 lines (158 loc) · 9.22 KB

activations.md

File metadata and controls

207 lines (158 loc) · 9.22 KB

Функции активации

Sigmoid

Источник

Исторически одна из первых функций активации. Рассматривалась в том числе и как гладкая аппроксимация порогового правила, эмулирующая активацию естественного нейрона. σ ( x ) = 1 1 + e x σ : R ( 0 , 1 )

sigmoid plot

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

Проблемы:

  • На концах функции (значения рядом с 0 и 1) производная практически равна 0, что приводит к затуханию градиентов.
  • область значений смещена относительно нуля;
  • exp вычислительно дорогая операция (ReLU быстрее в 4-6 раз)

Backward

d σ d x = e x p ( x ) ( 1 + e x p ( x ) ) 2 = 1 1 + e x p ( x ) ( 1 + e x p ( x ) ) 2 =

= 1 1 + e x p ( x ) ( 1 1 + e x p ( x ) ) 2 = σ ( 1 σ )

Code

class Sigmoid(Module):
    def forward(self, input):
        self.output = self.__class__._sigmoid(input)
        return self.output

    def backward(self, input, grad_output):
        sigma = self.output
        grad_input = np.multiply(grad_output, sigma*(1 - sigma))
        return grad_input
        
    @staticmethod
    def _sigmoid(x):
        return 1/(1 + np.exp(-x))

Tanh, гиперболический тангенс

Источник

Tanh решает проблему несимметричности Sigmoid и также может быть записан через неё t a n h ( x ) = 2 × α ( 2 x ) 1 . tanh ( x ) = exp ( x ) exp ( x ) exp ( x ) + exp ( x ) tanh : R ( 1 , 1 )

tanh plot

Плюсы:

  • Имеет симметричную область значений относительно нуля (в отличие от сигмоиды)
  • Имеет ограниченную область (-1, 1)

Минусы:

  • Проблема затухания градиентов на концах функции (близи значений -1 и 1), там производная почти равна 0
  • требуется вычисление exp, что вычислительно дорого

Backward

tanh ( x ) = sinh ( x ) cosh ( x )

tanh ( x ) = 1 cosh 2 ( x )

Из основного тождества cosh 2 ( x ) sinh 2 ( x ) = 1 имеем:

1 t a n h 2 ( x ) = 1 cosh 2 ( x )

Code

class Tanh(Module):
    def forward(self, input):
        self.output = np.tanh(input)
        return self.output

    def backward(self, input, grad_output):
        th = self.output
        grad_input = np.multiply(grad_output, (1 - th*th))
        return grad_input

ReLU, Rectified linear unit

Источник

ReLU представляет собой простую кусочно-линейную функцию. Одна из наиболее популярных функций активации. В нуле производная доопределяется нулевым значением. ReLU ( x ) = max ( 0 , x ) ReLU : R [ 0 , + )

relu plot

Плюсы: + сходится быстро (относительно sigmoid из-за отсутсвие проблемы с затуханием градиентов) + вычислительная простота активции и производной (Прирост в скорости относительно сигмойды в 4-6 раз) + не saturated nonlinear

Минусы: - для отрицательных значений производная равна нулю, что может привести к затуханию градиента; - область значений является смещённой относительно нуля.

Backward

Пусть f ( x ) = ReLU ( x ) , тогда

d f d x = { 0 , x 0 1 , x > 0

Code

class ReLU(Module):
	"""Rectified linear unit. Activation function."""
	
    def forward(self, input):
        self.output = np.maximum(input, 0)
        return self.output

    def backward(self, input, grad_output):
        grad_input = np.multiply(grad_output, input > 0)
        return grad_input

Leaky ReLU

Источник

Модификация ReLU устраняющая проблему смерти градиентов при x < 0 , тем самым меньше провоцируя затуханием градинета. Гиперпараметр $α$ обеспечивает небольшой уклон слева от нуля, что позволяет получить более симметричную относительно нуля область значений (чаще всего α = 0.01 ). LReLU ( x ) = max ( α x , x ) , 0 < α 1 LReLU : R ( , + ) leaky relu plot

Backward

Пусть f ( x ) = LReLU ( x ) , тогда

d f d x = { α , x 0 1 , x > 0

Code

class LeakyReLU(Module):

    def __init__(self, slope=0.01):
        super().__init__()
        self.slope = slope

    def forward(self, input):
        self.output = (input > 0)*input + (input <= 0)*self.slope*input
        return self.output

    def backward(self, input, grad_output):
        grad_input = np.multiply(
	        grad_output, (input > 0) + (input <= 0)*self.slope
	        )
        return grad_input

Softmax

Источник 1, Источник 2

Softmax также известна, как softargmax или normalized exponential function. Softmax преобразует вектор из K вещественных чисел в вероятностное распределение K возможных исходов. Чаще всего softmax встречается, как активация на последнем слое в задачах многоклассовой классификации.

σ ( z ) i = e z i e z j , i = 1 , , K

σ : R K ( 0 , 1 ) K

Сумма элементов выходного вектор равна 1. Softmax является аппроксимацией функции argmax.

Backward

Если мы хотим продифференциировать σ i , то мы можем продифференцировать её по K переменным. Пусть p i = σ ( z ) i

p i z i = e z i e z j e 2 z i ( e z j ) 2 = e z i e z j e 2 z i ( e z j ) 2 = p i ( 1 p i )

для всех i j , то:

p i z j = e z i e z j ( e z j ) 2 = e z i e z j e z j e z j = p i p j

Пусть l - некоторая функция, принимающая на вход выход softmax (например функция потерь). Тогда используя правило дифференцирование сложной функции (chain rule) получаем:

l z i = j = 1 K l p j p j z i = p i ( 1 p i ) l p i i j p i p j l p j =

= p i l p i j = 1 K p i p j l p j

Code

class Softmax(Module):
    def forward(self, input):
        self.output = self.softmax = self._softmax(input)
        return self.output

    def backward(self, input, grad_output):
        p = self.softmax
        grad_input = p * ( grad_output - (grad_output * p).sum(axis=1)[:, None] )
        return grad_input

    def _softmax(self, x):
        x = np.subtract(x, x.max(axis=1, keepdims=True))
        e_m = np.exp(x)
        sum_e = np.repeat(np.sum(e_m, axis=1), x.shape[-1]).reshape(*e_m.shape)
        return e_m/sum_e