o
    ¡¿¯i†  ã                   @   s,   d Z ddlZddlZG dd„ dejjƒZdS )zGTN CTC implementation.é    Nc                   @   s6   e Zd ZdZedd„ ƒZeddd„ƒZedd	„ ƒZd
S )ÚGTNCTCLossFunctionzGTN CTC module.c                 C   sØ   t  d¡}t| ƒ}d| d }t|ƒD ]Q}|d d }| |dk||d kp+||d k¡ |d r5| | n|}| |||¡ |dkrK| |d ||¡ |d rd|dkrd|| |d  krd| |d ||¡ q| d¡ |S )zÈBuild gtn graph.

        :param list target: single target sequence
        :param int blank_idx: index of blank token
        :return: gtn graph of target sequence
        :rtype: gtn.Graph
        Fé   é   r   )ÚgtnÚGraphÚlenÚrangeÚadd_nodeÚadd_arcÚarc_sort)ÚtargetÚ	blank_idxÚg_criterionÚLÚSÚsÚidxÚlabel© r   úW/home/ubuntu/.local/lib/python3.10/site-packages/espnet/nets/pytorch_backend/gtn_ctc.pyÚcreate_ctc_graph   s   
	$ €
z#GTNCTCLossFunction.create_ctc_graphr   Únonec           
   	      s    ˆj \}}‰ dg| ‰dg| ‰dg| ‰‡ ‡‡‡‡‡‡‡‡f	dd„}t |t|ƒ¡ ˆˆˆˆj ˆf| _t ‡‡fdd„t|ƒD ƒ¡}	t ˆjrM|	 	¡ ¡S |	¡S )a,  Forward computation.

        :param torch.tensor log_probs: batched log softmax probabilities (B, Tmax, oDim)
        :param list targets: batched target sequences, list of lists
        :param int blank_idx: index of blank token
        :return: ctc loss value
        :rtype: torch.Tensor
        Nc                    sÌ   ˆ|  }t  |ˆ ˆj¡}ˆ|  d |…  ¡  ¡ }| | ¡ ¡ t ˆ|  ˆ¡}t  	t  
t  ||¡¡¡}d}ˆdkrJtˆ|  ƒ}|dkrGd| n|}nˆdkrXtdtˆƒ d ƒ‚|ˆ| < |ˆ| < |ˆ| < d S )Ng      ð?Úmeanr   r   zinvalid value for reduction 'ú')r   Úlinear_graphÚrequires_gradÚcpuÚ
contiguousÚset_weightsÚdata_ptrr   r   ÚnegateÚforward_scoreÚ	intersectr   Ú
ValueErrorÚstr)ÚbÚTÚg_emissionsÚcpu_datar   Úg_lossÚscaler   ©	ÚCr   Úemissions_graphsÚilensÚ	log_probsÚlossesÚ	reductionÚscalesÚtargetsr   r   Úprocess7   s"   ÿz+GTNCTCLossFunction.forward.<locals>.processc                    s    g | ]}ˆ |   ¡ ˆ|  ‘qS r   )Úitem)Ú.0r%   )r0   r2   r   r   Ú
<listcomp>T   s     z.GTNCTCLossFunction.forward.<locals>.<listcomp>)
Úshaper   Úparallel_forr   Úauxiliary_dataÚtorchÚtensorr   Úis_cudaÚcuda)
Úctxr/   r3   r.   r   r1   ÚBÚ_r4   Úlossr   r+   r   Úforward(   s   



zGTNCTCLossFunction.forwardc                    sx   | j \‰‰‰}‰|\}}‰ t ||ˆ f¡‰‡ ‡‡‡‡‡fdd„}t |t|ƒ¡ |jr/ˆ ¡ ‰ˆ|| 9 ‰ˆddddfS )zÄBackward computation.

        :param torch.tensor grad_output: backward passed gradient value
        :return: cumulative gradient output
        :rtype: (torch.Tensor, None, None, None)
        c                    sX   ˆ|  }t  ˆ|  d¡ ˆ|  }| ¡  ¡ }t |¡ d|ˆ ¡ˆ|   ˆ|  d |…< d S )NFr   )r   ÚbackwardÚgradÚweights_to_numpyr;   Ú
from_numpyÚview)r%   r&   Ú	emissionsrE   ©r,   r-   r.   Ú
input_gradr0   r2   r   r   r4   c   s
   ,z,GTNCTCLossFunction.backward.<locals>.processN)r:   r;   Úzerosr   r9   r   r=   r>   )r?   Úgrad_outputÚin_shaper@   r&   r4   r   rJ   r   rD   W   s   
ûzGTNCTCLossFunction.backwardN)r   r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ústaticmethodr   rC   rD   r   r   r   r   r   
   s    
.r   )rR   r   r;   ÚautogradÚFunctionr   r   r   r   r   Ú<module>   s   