
    GJj .                         d dl mZ d dlmZ d dlmZ  G d de      Z G d de      Z G d d	e      Z	 G d
 de      Z
 G d de      Zy)    )TupleN)Modulec                   t     e Zd ZdZ	 	 d
dededef fdZd Zde	j                  de	j                  fd	Z xZS )InstanceNorma  Applies instance normalization [1] on the inputs.

    Computes

    .. math::

        y = \frac{x - \mathrm{E}[x]}{ \sqrt{\mathrm{Var}[x] + \epsilon}} * \gamma + \beta,

    where :math:`\gamma` and :math:`\beta` are learned per feature dimension
    parameters initialized at 1 and 0 respectively. Both are of size :attr:`dims`,
    if :attr:`affine` is ``True``.

    Args:
        dims (int): The number of features of the input.
        eps (float): A value added to the denominator for numerical stability. Default: ``1e-5``.
        affine (bool): Default: ``False``.

    Shape:
      - Input: :math:`(..., C)` where :math:`C` is equal to :attr:`dims`.
      - Output: Same shape as the input.

    Examples:
        >>> import mlx.core as mx
        >>> import mlx.nn as nn
        >>> x = mx.random.normal((8, 4, 4, 16))
        >>> inorm = nn.InstanceNorm(dims=16)
        >>> output = inorm(x)

    References:
        [1]: https://arxiv.org/abs/1607.08022
    dimsepsaffinec                     t         |           |r6t        j                  |f      | _        t        j
                  |f      | _        || _        || _        y N)	super__init__mxonesweightzerosbiasr   r   )selfr   r   r	   	__class__s       e/Users/ahmed/devFolder/claude-voice/.venv/lib/python3.12/site-packages/mlx/nn/layers/normalization.pyr   zInstanceNorm.__init__*   sE     	''4'*DK$)DI	    c                 B    | j                    d| j                   dd| v  S N, eps=	, affine=r   r   r   r   s    r   _extra_reprzInstanceNorm._extra_repr7   '    ))F488*Ih$6F5GHHr   xreturnc                 :   t        t        d|j                  dz
              }t        j                  ||d      }t        j
                  ||d      }||z
  t        j                  || j                  z         z  }d| v r| j                  |z  | j                  z   S |S )N   Taxiskeepdimsr   )
tuplerangendimr   meanvarrsqrtr   r   r   r   r   reduction_axesr)   r*   s        r   __call__zInstanceNorm.__call__:   s    uQ
34wwq~=ffQ^d;X#.1108D0@a$))+GaGr   )h㈵>F)__name__
__module____qualname____doc__intfloatboolr   r   r   arrayr.   __classcell__r   s   @r   r   r   	   sV    F 	  	IH"(( Hrxx Hr   r   c            	       D     e Zd ZdZ	 d	dedededef fdZd Zd Z	 xZ
S )
	LayerNorma  Applies layer normalization [1] on the inputs.

    Computes

    .. math::

        y = \frac{x - E[x]}{\sqrt{Var[x]} + \epsilon} \gamma + \beta,

    where :math:`\gamma` and :math:`\beta` are learned per feature dimension
    parameters initialized at 1 and 0 respectively.

    [1]: https://arxiv.org/abs/1607.06450

    Args:
        dims (int): The feature dimension of the input to normalize over
        eps (float): A small additive constant for numerical stability
        affine (bool): If True learn an affine transform to apply after the
            normalization
        bias (bool): If True include a translation to the affine
            transformation. If set to False the transformation is not really affine
            just scaling.
    r   r   r	   r   c                     t         |           |r8t        j                  |f      | _        |rt        j
                  |f      | _        || _        || _        y r   )	r   r   r   r   r   r   r   r   r   )r   r   r   r	   r   r   s        r   r   zLayerNorm.__init__]   sH     	''4'*DKHHdW-		r   c                 B    | j                    d| j                   dd| v  S r   r   r   s    r   r   zLayerNorm._extra_reprh   r   r   c                     d| v r| j                   nd }d| v r| j                  nd }t        j                  j	                  |||| j
                        S )Nr   r   )r   r   r   fast
layer_normr   )r   r   r   r   s       r   r.   zLayerNorm.__call__k   sD     (D 0d"dNtyyww!!!VT488<<r   )r/   TT)r0   r1   r2   r3   r4   r5   r6   r   r   r.   r8   r9   s   @r   r;   r;   E   s?    0 OS		#	48	GK	I=r   r;   c                   :     e Zd ZdZddedef fdZd Zd Z xZ	S )RMSNorma  Applies Root Mean Square normalization [1] to the inputs.

    Computes

    ..  math::

        y = \frac{x}{\sqrt{E[x^2] + \epsilon}} \gamma

    where :math:`\gamma` is a learned per feature dimension parameter initialized at
    1.

    Note the accumulation for the mean is done in 32-bit precision.

    [1]: https://arxiv.org/abs/1910.07467

    Args:
        dims (int): The feature dimension of the input to normalize over
        eps (float): A small additive constant for numerical stability
    r   r   c                 f    t         |           t        j                  |f      | _        || _        y r   )r   r   r   r   r   r   )r   r   r   r   s      r   r   zRMSNorm.__init__   s'    ggtg&r   c                 R    | j                   j                  d    d| j                   S )Nr   r   )r   shaper   r   s    r   r   zRMSNorm._extra_repr   s'    ++##A&'vdhhZ88r   c                 ^    t         j                  j                  || d   | j                        S Nr   )r   r?   rms_normr   )r   r   s     r   r.   zRMSNorm.__call__   s#    ww4>488<<r   )r/   )
r0   r1   r2   r3   r4   r5   r   r   r.   r8   r9   s   @r   rB   rB   q   s%    (S u 
9=r   rB   c                   X     e Zd ZdZ	 	 	 ddededededef
 fdZd Zd	 Z	d
 Z
d Z xZS )	GroupNorma  Applies Group Normalization [1] to the inputs.

    Computes the same normalization as layer norm, namely

    .. math::

        y = \frac{x - E[x]}{\sqrt{Var[x]} + \epsilon} \gamma + \beta,

    where :math:`\gamma` and :math:`\beta` are learned per feature dimension
    parameters initialized at 1 and 0 respectively. However, the mean and
    variance are computed over the spatial dimensions and each group of
    features. In particular, the input is split into num_groups across the
    feature dimension.

    The feature dimension is assumed to be the last dimension and the dimensions
    that precede it (except the first) are considered the spatial dimensions.

    [1]: https://arxiv.org/abs/1803.08494

    Args:
        num_groups (int): Number of groups to separate the features into
        dims (int): The feature dimensions of the input to normalize over
        eps (float): A small additive constant for numerical stability
        affine (bool): If True learn an affine transform to apply after the
            normalization.
        pytorch_compatible (bool): If True perform the group normalization in
            the same order/grouping as PyTorch.
    
num_groupsr   r   r	   pytorch_compatiblec                     t         |           |r6t        j                  |f      | _        t        j
                  |f      | _        || _        || _        || _	        || _
        y r   )r   r   r   r   r   r   r   rK   r   r   rL   )r   rK   r   r   r	   rL   r   s         r   r   zGroupNorm.__init__   sT     	$)DI''4'*DK$	"4r   c           	      v    | j                    d| j                   d| j                   dd| v  d| j                   	S )Nz, r   r   r   z, pytorch_compatible=)rK   r   r   rL   r   s    r   r   zGroupNorm._extra_repr   sI    r$))F488* =$&''<T=T=T<UW	
r   c                    | j                   }|j                  ^}}}||z  }|j                  |d||      }|j                  dddd      j                  ||d      }t        j
                  j                  || j                  d d       }|j                  ||d|      } |j                  dddd      j                  |g|| }|S )Nr      r"      )r   r   r   )rK   rE   reshape	transposer   r?   r@   r   )r   r   rK   batchrestr   
group_sizes          r   _pytorch_compatible_group_normz(GroupNorm._pytorch_compatible_group_norm   s    __
WWdZ'
 IIeRZ8KK1a#++E:rB GGqdhht$GIIeZZ8+AKK1a#++E?D?$?r   c                 >   | j                   }|j                  ^}}}|j                  |d|      }t        j                  |dd      }t        j
                  |dd      }||z
  t        j                  || j                  z         z  } |j                  |g|| }|S )NrP   r"   Tr#   )rK   rE   rS   r   r)   r*   r+   r   )r   r   rK   rU   rV   r   meansr*   s           r   _group_normzGroupNorm._group_norm   s    __
WWd IIeR, D1ffQQ.Y"((3>22AIIe)d)D)r   c                     | j                   r| j                  n| j                  } ||      }d| v r| j                  |z  | j                  z   S |S rG   )rL   rX   r[   r   r   )r   r   
group_norms      r   r.   zGroupNorm.__call__   sT     && //!! 	
 qM08D0@a$))+GaGr   )r/   TF)r0   r1   r2   r3   r4   r5   r6   r   r   rX   r[   r.   r8   r9   s   @r   rJ   rJ      s^    B #(55 5 	5
 5 !5"
 Hr   rJ   c                        e Zd ZdZ	 	 	 	 ddededededef
 fdZ fdZd	 Z	d
e
j                  dee
j                  e
j                  f   fdZd
e
j                  de
j                  fdZ xZS )	BatchNormaW  Applies Batch Normalization over a 2D or 3D input.

    Computes

    .. math::

        y = \frac{x - E[x]}{\sqrt{Var[x]} + \epsilon} \gamma + \beta,

    where :math:`\gamma` and :math:`\beta` are learned per feature dimension
    parameters initialized at 1 and 0 respectively.

    The input shape is specified as ``NC`` or ``NLC``, where ``N`` is the
    batch, ``C`` is the number of features or channels, and ``L`` is the
    sequence length. The output has the same shape as the input. For
    four-dimensional arrays, the shape is ``NHWC``, where ``H`` and ``W`` are
    the height and width respectively.

    For more information on Batch Normalization, see the original paper `Batch
    Normalization: Accelerating Deep Network Training by Reducing Internal
    Covariate Shift <https://arxiv.org/abs/1502.03167>`_.

    Args:
        num_features (int): The feature dimension to normalize over.
        eps (float, optional): A small additive constant for numerical
            stability. Default: ``1e-5``.
        momentum (float, optional): The momentum for updating the running
            mean and variance. Default: ``0.1``.
        affine (bool, optional): If ``True``, apply a learned affine
            transformation after the normalization. Default: ``True``.
        track_running_stats (bool, optional): If ``True``, track the
            running mean and variance. Default: ``True``.

    Examples:
        >>> import mlx.core as mx
        >>> import mlx.nn as nn
        >>> x = mx.random.normal((5, 4))
        >>> bn = nn.BatchNorm(num_features=4, affine=True)
        >>> output = bn(x)
    num_featuresr   momentumr	   track_running_statsc                 z   t         |           || _        || _        || _        || _        |r6t        j                  |f      | _        t        j                  |f      | _
        | j
                  rLt        j                  |f      | _        t        j                  |f      | _        | j                  ddgd       y y )Nrunning_meanrunning_varFkeysrecurse)r   r   r`   r   ra   rb   r   r   r   r   r   rd   re   freeze)r   r`   r   ra   r	   rb   r   s         r   r   zBatchNorm.__init__  s     	( #6 ''</2DK,1DI## ", 9D!ww7DKKnm<eKL $r   c                 N    t        |   |i | | j                  ddgd       y)zZWrap unfreeze to make sure that running_mean and var are always
        frozen parameters.rd   re   Frf   N)r   unfreezeri   )r   argskwargsr   s      r   rk   zBatchNorm.unfreeze1  s,     	$)&).-8%Hr   c           	      v    | j                    d| j                   d| j                   dd| v  d| j                   	S )Nr   z, momentum=r   r   z, track_running_stats=)r`   r   ra   rb   r   s    r   r   zBatchNorm._extra_repr7  sN      !z 2iD0@/A B##'#;#;"<>	
r   r   r    c                     t        t        d|j                  dz
              }t        j                  ||      }t        j
                  ||      }||fS )z
        Calculate the mean and variance of the input tensor across the batch
        and spatial dimensions.

        Args:
            x (array): Input tensor.

        Returns:
            tuple: Tuple containing mean and variance.
        r   r"   )r$   )r&   r'   r(   r   r)   r*   r,   s        r   _calc_statszBatchNorm._calc_stats>  sG     uQ
34wwq~.ffQ^,Syr   c                 0   |j                   dk  s|j                   dkD  rt        d|j                          | j                  |      \  }}| j                  rS| j                  rG| j
                  }d|z
  | j                  z  ||z  z   | _        d|z
  | j                  z  ||z  z   | _        n$| j                  r| j                  }| j                  }||z
  t        j                  || j                  z         z  }d| v r| j                  |z  | j                  z   S |S )z
        Forward pass of BatchNorm.

        Args:
            x (array): Input tensor.

        Returns:
            array: Normalized output tensor.
        rQ      z<Expected input tensor to have 2, 3 or 4 dimensions, but got r"   r   )r(   
ValueErrorrp   trainingrb   ra   rd   re   r   r+   r   r   r   )r   r   r)   r*   mus        r   r.   zBatchNorm.__call__P  s    66A:!NqvvhW  $$Q'	c==T55B!"R4+<+< <rDy HD !B$*:*::R#XED%%$$D""CX#.1108D0@a$))+GaGr   )r/   g?TT)r0   r1   r2   r3   r4   r5   r6   r   rk   r   r   r7   r   rp   r.   r8   r9   s   @r   r_   r_      s    &V $(MM M 	M
 M "M0I
RXX %"((0B*C $H"(( Hrxx Hr   r_   )typingr   mlx.corecorer   mlx.nn.layers.baser   r   r;   rB   rJ   r_    r   r   <module>r{      sZ      %9H6 9Hx)= )=X=f =B[H [H|{H {Hr   