| |
| |
| |
| |
| |
|
|
| import torch |
| import torch.nn as nn |
| from torch import Tensor |
| from typing import Union, Callable |
|
|
|
|
| class CustomGLU(nn.Module): |
| """Custom Gated Linear Unit activation. |
| Applies a modified gated linear unit :math:`a * f(b)` where :math:`a` is the first half |
| of the input matrices, :math:`b` is the second half, and :math:`f` is a provided activation |
| function (i.e. sigmoid, swish, etc.). |
| |
| Args: |
| activation (nn.Module): The custom activation to apply in the Gated Linear Unit |
| dim (int): the dimension on which to split the input. Default: -1 |
| |
| Shape: |
| - Input: :math:`(\ast_1, N, \ast_2)` where `*` means, any number of additional |
| dimensions |
| - Output: :math:`(\ast_1, M, \ast_2)` where :math:`M=N/2` |
| |
| Examples:: |
| >>> m = CustomGLU(nn.Sigmoid()) |
| >>> input = torch.randn(4, 2) |
| >>> output = m(input) |
| """ |
| def __init__(self, activation: nn.Module, dim: int = -1): |
| super(CustomGLU, self).__init__() |
| self.dim = dim |
| self.activation = activation |
|
|
| def forward(self, x: Tensor): |
| assert x.shape[self.dim] % 2 == 0 |
| a, b = torch.chunk(x, 2, dim=self.dim) |
| return a * self.activation(b) |
|
|
|
|
| class SwiGLU(CustomGLU): |
| """SiLU Gated Linear Unit activation. |
| Applies SiLU Gated Linear Unit :math:`a * SiLU(b)` where :math:`a` is |
| the first half of the input matrices, :math:`b` is the second half. |
| |
| Args: |
| dim (int): the dimension on which to split the input. Default: -1 |
| """ |
| def __init__(self, dim: int = -1): |
| super(SwiGLU, self).__init__(nn.SiLU(), dim) |
|
|
|
|
| class GeGLU(CustomGLU): |
| """GeLU Gated Linear Unit activation. |
| Applies GeLU Gated Linear Unit :math:`a * GELU(b)` where :math:`a` is |
| the first half of the input matrices, :math:`b` is the second half. |
| |
| Args: |
| dim (int): the dimension on which to split the input. Default: -1 |
| """ |
| def __init__(self, dim: int = -1): |
| super(GeGLU, self).__init__(nn.GELU(), dim) |
|
|
|
|
| class ReGLU(CustomGLU): |
| """ReLU Gated Linear Unit activation. |
| Applies ReLU Gated Linear Unit :math:`a * ReLU(b)` where :math:`a` is |
| the first half of the input matrices, :math:`b` is the second half. |
| |
| Args: |
| dim (int): the dimension on which to split the input. Default: -1 |
| """ |
| def __init__(self, dim: int = -1): |
| super(ReGLU, self).__init__(nn.ReLU(), dim) |
|
|
|
|
| def get_activation_fn( |
| activation: Union[str, Callable[[Tensor], Tensor]] |
| ) -> Union[str, Callable[[Tensor], Tensor]]: |
| """Helper function to map an activation string to the activation class. |
| If the supplied activation is not a string that is recognized, the activation is passed back. |
| |
| Args: |
| activation (str, or Callable[[Tensor], Tensor]): Activation to check |
| """ |
| if isinstance(activation, str): |
| if activation == "reglu": |
| return ReGLU() |
| elif activation == "geglu": |
| return GeGLU() |
| elif activation == "swiglu": |
| return SwiGLU() |
| return activation |
|
|