import torch
import torch.nn as nn
import torch.nn.functional as F
from torch import Tensor
[docs]class CoLU(nn.Module):
r"""
Applies the Collapsing Linear Unit activation function:
:math:`\text{CoLU}(x) = \frac{x}{1-x \cdot e^{-(x + e^x)}}`
See: https://doi.org/10.48550/arXiv.2112.12078
Args:
inplace (bool, optional): can optionally do the operation in-place. Default: ``False``
Shape:
- Input: :math:`(*)`, where :math:`*` means any number of dimensions.
- Output: :math:`(*)`, same shape as the input.
Examples::
>>> m = nn.CoLU()
>>> x = torch.randn(2)
>>> output = m(x)
>>> m = nn.CoLU(inplace=True)
>>> x = torch.randn(2)
>>> m(x)
"""
def __init__(self, inplace=False):
super(CoLU, self).__init__()
self.inplace = inplace
[docs] def forward(self, x) -> Tensor:
if self.inplace:
return x.div_(1 - x * torch.exp(-1 * (x + torch.exp(x))))
else:
return x / (1 - x * torch.exp(-1 * (x + torch.exp(x))))
[docs]class ScaledSoftSign(torch.nn.Module):
r"""
Applies the ScaledSoftSign activation function:
:math:`\text{ScaledSoftSign}(x) = \frac{\alpha \cdot x}{\beta + \|x\|}`
See: https://doi.org/10.20944/preprints202301.0463.v1
Args:
alpha (float, optional): The initial value of the alpha parameter.
beta (float, optional): The initial value of the beta parameter.
Shape:
- Input: :math:`(*)`, where :math:`*` means any number of dimensions.
- Output: :math:`(*)`, same shape as the input.
Examples:
>>> m = ScaledSoftSign(alpha=0.5, beta=1.0)
>>> x = torch.randn(2, 3)
>>> output = m(x)
>>> m = ScaledSoftSign(inplace=True)
>>> x = torch.randn(2, 3)
>>> m(x)
"""
def __init__(self, alpha: float = 1.0, beta: float = 1.0):
super(ScaledSoftSign, self).__init__()
self.alpha = torch.nn.Parameter(Tensor(alpha))
self.beta = torch.nn.Parameter(Tensor(beta))
[docs] def forward(self, x) -> Tensor:
abs_x = x.abs()
alpha_x = self.alpha * x
denom = self.beta + abs_x
result = alpha_x / denom
return result
[docs]class Phish(torch.nn.Module):
r"""
Applies the Phish activation function:
:math:`\text{Phish}(x) = x \odot \tanh (\text{GELU} (x))`
See: `Phish: A Novel Hyper-Optimizable Activation Function`_.
Shape:
- Input: :math:`(*)`, where :math:`*` means any number of dimensions.
- Output: :math:`(*)`, same shape as the input.
Examples:
>>> m = Phish()
>>> x = torch.randn(2, 3)
>>> output = m(x)
.. _`Phish: A Novel Hyper-Optimizable Activation Function`:
https://www.semanticscholar.org/paper/Phish%3A-A-Novel-Hyper-Optimizable-Activation-Naveen/43eb5e22da6092d28f0e842fec53ec1a76e1ba6b
"""
def __init__(self):
super(Phish, self).__init__()
[docs] def forward(self, x) -> Tensor:
x *= F.tanh(F.gelu(x))
return x
if __name__ == "__main__":
pass