o
    æS™iŸ3  ã                   @   sö   d Z ddlZddlmZmZ ddlZddlmZ ddlm  m	Z
 ddlmZ dejdejd	ejfd
d„Zdefdd„Zd%dedefdd„Zdefdd„Zdefdd„Zd&dedefdd„ZG dd „ d ejƒZG d!d"„ d"ejƒZG d#d$„ d$ejƒZdS )'z(Core vector quantization implementation.é    N)Ú	rearrangeÚrepeat)Únné   )ÚdistribÚvalÚdÚreturnc                 C   s   | d ur| S |S ©N© )r   r   r   r   úP/home/ubuntu/.local/lib/python3.10/site-packages/encodec/quantization/core_vq.pyÚdefault,   s   r   Údecayc                 C   s   | j  |¡j|d| d d S )Né   )Úalpha)ÚdataÚmul_Úadd_)Ú
moving_avgÚnewr   r   r   r   Úema_inplace0   s   r   çñhãˆµøä>Ún_categoriesÚepsilonc                 C   s   | | |   ¡ ||   S r
   )Úsum)Úxr   r   r   r   r   Úlaplace_smoothing4   s   r   Úshapec                  G   s   t  | ¡}tj |¡ |S r
   )ÚtorchÚemptyr   ÚinitÚkaiming_uniform_)r   Útr   r   r   Úuniform_init8   s   
r#   Únumc                 C   sT   | j d | j}}||krtj||dd |… }| | S tjd||f|d}| | S )Nr   ©Údevice)r   r&   r   ÚrandpermÚrandint)Úsamplesr$   Únum_samplesr&   Úindicesr   r   r   Úsample_vectors>   s   þr,   é
   Únum_clustersÚ	num_itersc              	   C   sÎ   | j d | j}}t| |ƒ}t|ƒD ]P}t| dƒt|dƒ }|d jdd }|jddj}	tj	|	|d}
|
dk}|
 
|d¡}|	j|||d	}| dt|	d
|d| ¡ ||d  }t |d ||¡}q||
fS )Néÿÿÿÿzn d -> n () dzc d -> () c dr   ©Údim)Ú	minlengthr   r   )Údtypezn -> n d)r   ©.N)r   r4   r,   Úranger   r   Úmaxr+   r   ÚbincountÚmasked_fillÚ	new_zerosÚscatter_add_r   Úwhere)r)   r.   r/   r2   r4   ÚmeansÚ_ÚdiffsÚdistsÚbucketsÚbinsÚ	zero_maskÚbins_min_clampedÚ	new_meansr   r   r   ÚkmeansI   s    

ÿrF   c                       s¢   e Zd ZdZ					d$deded	ed
edededef‡ fdd„Zejj	dd„ ƒZ
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd d!„ Zd"d#„ Z‡  ZS )%ÚEuclideanCodebookaJ  Codebook with Euclidean distance.
    Args:
        dim (int): Dimension.
        codebook_size (int): Codebook size.
        kmeans_init (bool): Whether to use k-means to initialize the codebooks.
            If set to true, run the k-means algorithm on the first training batch and use
            the learned centroids as initialization.
        kmeans_iters (int): Number of iterations used for k-means algorithm at initialization.
        decay (float): Decay for exponential moving average over the codebooks.
        epsilon (float): Epsilon value for numerical stability.
        threshold_ema_dead_code (int): Threshold for dead code expiration. Replace any codes
            that have an exponential moving average cluster size less than the specified threshold with
            randomly selected vector from the current batch.
    Fr-   ç®Gáz®ï?r   r   r2   Úcodebook_sizeÚkmeans_initÚkmeans_itersr   r   Úthreshold_ema_dead_codec           
         sˆ   t ƒ  ¡  || _|stntj}|||ƒ}	|| _|| _|| _|| _	|  
dt | g¡¡ |  
dt |¡¡ |  
d|	¡ |  
d|	 ¡ ¡ d S )NÚinitedÚcluster_sizeÚembedÚ	embed_avg)ÚsuperÚ__init__r   r#   r   ÚzerosrI   rK   r   rL   Úregister_bufferÚTensorÚclone)
Úselfr2   rI   rJ   rK   r   r   rL   Úinit_fnrO   ©Ú	__class__r   r   rR   q   s   


zEuclideanCodebook.__init__c                 C   st   | j rd S t|| j| jƒ\}}| jj |¡ | jj | ¡ ¡ | j	j |¡ | j j t
 dg¡¡ t |  ¡ ¡ d S )NT)rM   rF   rI   rK   rO   r   Úcopy_rP   rV   rN   r   rU   r   Úbroadcast_tensorsÚbuffers)rW   r   rO   rN   r   r   r   Úinit_embed_‹   s   zEuclideanCodebook.init_embed_c                 C   s.   t  |d t|| jƒ| j¡}| jj |¡ d S )Nr5   )r   r<   r,   rI   rO   r   r[   )rW   r)   ÚmaskÚmodified_codebookr   r   r   Úreplace_˜   s   ÿzEuclideanCodebook.replace_c                 C   sR   | j dkrd S | j| j k }t |¡sd S t|dƒ}| j||d t |  ¡ ¡ d S )Nr   ú... d -> (...) d)r_   )	rL   rN   r   Úanyr   ra   r   r\   r]   )rW   Úbatch_samplesÚexpired_codesr   r   r   Úexpire_codes_ž   s   


zEuclideanCodebook.expire_codes_c                 C   s   t |dƒ}|S )Nrb   )r   )rW   r   r   r   r   Ú
preprocessª   ó   
zEuclideanCodebook.preprocessc                 C   sR   | j  ¡ }| d¡jdddd| |  | d¡jddd  }|jddj}|S )Nr   r   T)Úkeepdimr   r0   r1   )rO   r"   Úpowr   r7   r+   )rW   r   rO   ÚdistÚ	embed_indr   r   r   Úquantize®   s   

ÿþÿzEuclideanCodebook.quantizec                 C   s   |j |d d… Ž S )Nr0   )Úview)rW   rl   r   r   r   r   Úpostprocess_emb¸   s   z!EuclideanCodebook.postprocess_embc                 C   s   t  || j¡}|S r
   )ÚFÚ	embeddingrO   ©rW   rl   rm   r   r   r   Ú
dequantize»   s   zEuclideanCodebook.dequantizec                 C   s*   |j }|  |¡}|  |¡}|  ||¡}|S r
   )r   rg   rm   ro   )rW   r   r   rl   r   r   r   Úencode¿   s
   

zEuclideanCodebook.encodec                 C   s   |   |¡}|S r
   )rs   rr   r   r   r   ÚdecodeÉ   rh   zEuclideanCodebook.decodec           
      C   sÞ   |j |j}}|  |¡}|  |¡ |  |¡}t || j¡ |¡}|  	||¡}|  
|¡}| jrk|  |¡ t| j| d¡| jƒ | ¡ | }t| j| ¡ | jƒ t| j| j| jƒ| j ¡  }| j| d¡ }	| jj |	¡ ||fS )Nr   r   )r   r4   rg   r^   rm   rp   Úone_hotrI   Útypero   rs   Útrainingrf   r   rN   r   r   r"   rP   r   r   Ú	unsqueezerO   r   r[   )
rW   r   r   r4   rl   Úembed_onehotrm   Ú	embed_sumrN   Úembed_normalizedr   r   r   ÚforwardÍ   s&   




ÿÿzEuclideanCodebook.forward)Fr-   rH   r   r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚintÚfloatrR   r   ÚjitÚignorer^   ra   rf   rg   rm   ro   rs   rt   ru   r}   Ú__classcell__r   r   rY   r   rG   b   sB    øþýüûúùø


rG   c                       s€   e Zd ZdZ							dd	ed
edeje dedededededef‡ fdd„Z	e
dd„ ƒZdd„ Zdd„ Zdd„ Z‡  ZS )ÚVectorQuantizationa€  Vector quantization implementation.
    Currently supports only euclidean distance.
    Args:
        dim (int): Dimension
        codebook_size (int): Codebook size
        codebook_dim (int): Codebook dimension. If not defined, uses the specified dimension in dim.
        decay (float): Decay for exponential moving average over the codebooks.
        epsilon (float): Epsilon value for numerical stability.
        kmeans_init (bool): Whether to use kmeans to initialize the codebooks.
        kmeans_iters (int): Number of iterations used for kmeans initialization.
        threshold_ema_dead_code (int): Threshold for dead code expiration. Replace any codes
            that have an exponential moving average cluster size less than the specified threshold with
            randomly selected vector from the current batch.
        commitment_weight (float): Weight for commitment loss.
    NrH   r   Té2   r   ç      ð?r2   rI   Úcodebook_dimr   r   rJ   rK   rL   Úcommitment_weightc
              	      s~   t ƒ  ¡  t||ƒ}
|
|k}|rt ||
¡nt ¡ | _|r#t |
|¡nt ¡ | _|| _|	| _	t
|
||||||d| _|| _d S )N)r2   rI   rJ   rK   r   r   rL   )rQ   rR   r   r   ÚLinearÚIdentityÚ
project_inÚproject_outr   r‹   rG   Ú	_codebookrI   )rW   r2   rI   rŠ   r   r   rJ   rK   rL   r‹   Ú_codebook_dimÚrequires_projectionrY   r   r   rR   ù   s   

ý
zVectorQuantization.__init__c                 C   s   | j jS r
   )r   rO   )rW   r   r   r   Úcodebook  s   zVectorQuantization.codebookc                 C   s$   t |dƒ}|  |¡}| j |¡}|S )Núb d n -> b n d)r   rŽ   r   rt   )rW   r   Úembed_inr   r   r   rt     s   

zVectorQuantization.encodec                 C   s$   | j  |¡}|  |¡}t|dƒ}|S )Núb n d -> b d n)r   ru   r   r   rr   r   r   r   ru     s   

zVectorQuantization.decodec                 C   sž   |j }t|dƒ}|  |¡}|  |¡\}}| jr|||  ¡  }tjdg|| jd}| jr@| jdkr@t	 
| ¡ |¡}||| j  }|  |¡}t|dƒ}|||fS )Nr”   ç        )r&   Úrequires_gradr   r–   )r&   r   rŽ   r   rx   Údetachr   Útensorr‹   rp   Úmse_lossr   )rW   r   r&   rm   rl   ÚlossÚcommit_lossr   r   r   r}   %  s   





zVectorQuantization.forward)NrH   r   Trˆ   r   r‰   )r~   r   r€   r   r‚   ÚtpÚOptionalrƒ   ÚboolrR   Úpropertyr“   rt   ru   r}   r†   r   r   rY   r   r‡   é   sB    öþýüûúùø	÷
ö
r‡   c                       sn   e Zd ZdZ‡ fdd„Zddeje fdd„Zdde	j
deje d	e	j
fd
d„Zde	j
d	e	j
fdd„Z‡  ZS )ÚResidualVectorQuantizationzrResidual vector quantization implementation.
    Follows Algorithm 1. in https://arxiv.org/pdf/2107.03312.pdf
    c                   s,   t ƒ  ¡  t ‡ fdd„t|ƒD ƒ¡| _d S )Nc                    s   g | ]	}t d i ˆ ¤Ž‘qS )r   )r‡   )Ú.0r>   ©Úkwargsr   r   Ú
<listcomp>B  s    z7ResidualVectorQuantization.__init__.<locals>.<listcomp>)rQ   rR   r   Ú
ModuleListr6   Úlayers)rW   Únum_quantizersr¥   rY   r¤   r   rR   ?  s   

ÿz#ResidualVectorQuantization.__init__NÚn_qc                 C   s‚   d}|}g }g }|pt | jƒ}| jd |… D ]}||ƒ\}}	}
|| }|| }| |	¡ | |
¡ qttj||fƒ\}}|||fS )Nr—   )Úlenr¨   ÚappendÚmapr   Ústack)rW   r   rª   Úquantized_outÚresidualÚ
all_lossesÚall_indicesÚlayerÚ	quantizedr+   rœ   Ú
out_lossesÚout_indicesr   r   r   r}   E  s   

z"ResidualVectorQuantization.forwardr   r	   c           	      C   s^   |}g }|p
t | jƒ}| jd |… D ]}| |¡}| |¡}|| }| |¡ qt |¡}|S r
   )r«   r¨   rt   ru   r¬   r   r®   )	rW   r   rª   r°   r²   r³   r+   r´   r¶   r   r   r   rt   Y  s   


z!ResidualVectorQuantization.encodeÚ	q_indicesc                 C   sB   t jd|jd}t|ƒD ]\}}| j| }| |¡}|| }q|S )Nr—   r%   )r   rš   r&   Ú	enumerater¨   ru   )rW   r·   r¯   Úir+   r³   r´   r   r   r   ru   e  s   


z!ResidualVectorQuantization.decoder
   )r~   r   r€   r   rR   rž   rŸ   r‚   r}   r   rU   rt   ru   r†   r   r   rY   r   r¢   ;  s    "r¢   )r   )r-   )r   Útypingrž   Úeinopsr   r   r   r   Útorch.nn.functionalÚ
functionalrp   Ú r   ÚAnyr   rƒ   r   r‚   r   r#   r,   rF   ÚModulerG   r‡   r¢   r   r   r   r   Ú<module>   s"    R