o
    Ni                     @   s`   d dl mZ d dlZd dlmZ ddlmZ dd ZG dd	 d	ej	j
ZG d
d dej	j
ZdS )    )UnionN)crf_log_likelihood   )compute_dsc_lossc                 C   s6   t | dkr| d | d d fS t | dkr| S td)N   r   r      z+Expected data to be a tuple of size 2 or 3.)len	TypeError)data r   H/home/ubuntu/.local/lib/python3.10/site-packages/tf2crf/model_wrapper.pyunpack_data	   s
   r   c                       s`   e Zd ZdZddeeef f fddZddd	Zdd
dZ	dd Z
edd Zdd Z  ZS )ModelWithCRFLossa  
    Wrapper around the base model for custom training logic.
    Args:
        base_model: The model including the CRF layer
        sparse_target: if the y label is sparse or one-hot, default True
        metric: the metric for training, default 'accuracy'. Warning: Currently tensorflow metrics like AUC need the output and y_true to be one-hot to cauculate, they are not supported.
    Taccuracymetricc                    sh   t    || _|| _|| _t|tr%|dkr!tjj	j
dd| _ntd| j| _tjj	jdd| _d S Nr   )namezunknown metric nameloss)super__init__
base_modelsparse_targetr   
isinstancestrtfkerasmetricsAccuracy
metrics_fn
ValueErrorMeanloss_tracker)selfr   r   r   	__class__r   r   r      s   

zModelWithCRFLoss.__init__Fc                 C      |r|  |S |  |d S Nr   r   r"   inputstrainingr   r   r   call)      
zModelWithCRFLoss.callc           	      C   s8   | ||d\}}}}t ||||d  }||t|fS )Nr*   r   )r   r   reduce_mean)	r"   xyr*   viterbi_sequence
potentialssequence_lengthchain_kernelcrf_lossr   r   r   compute_loss/   s   zModelWithCRFLoss.compute_lossc              	   C   s   t |\}}}| jrt|jdksJ ntj|dd}t  }| j||dd\}}}|tt	| j
|j }	W d    n1 sBw   Y  ||	| j}
| jt|
| j | j|	 | j||t||jd  d| j | jj| j iS Nr   axisTr-   r   r   r   r   r   shaper   argmaxGradientTaper6   cast
reduce_sumlossesdtypegradienttrainable_variables	optimizerapply_gradientszipr!   update_stater   sequence_maskresultr   )r"   r
   r/   r0   sample_weighttaper1   r3   r5   r   	gradientsr   r   r   
train_step5   s   
zModelWithCRFLoss.train_stepc                 C      | j | jgS Nr!   r   r"   r   r   r   r   E      zModelWithCRFLoss.metricsc           	   	   C   s   t |\}}}| jrt|jdksJ ntj|dd}| j||dd\}}}|tt| j	|j
 }| j| | j||t||jd  d| j d| jj | j iS 	Nr   r8   r9   Tr-   r   loss_valval_r   r   r   r<   r   r=   r6   r?   r@   rA   rB   r!   rH   r   rI   rJ   r   )	r"   r
   r/   r0   rK   r1   r3   r5   r   r   r   r   	test_stepI   s   "zModelWithCRFLoss.test_step)Tr   F__name__
__module____qualname____doc__r   r   objectr   r+   r6   rN   propertyr   rX   __classcell__r   r   r#   r   r      s    


r   c                       s`   e Zd ZdZddeeef f fddZdd	d
ZdddZ	dd Z
edd Zdd Z  ZS )ModelWithCRFLossDSCLossa  
        Wrapper around the base model for custom training logic. And DSC loss to help improve the performance of NER task.
        Args:
            base_model: The model including the CRF layer
            sparse_target: if the y label is sparse or one-hot, default True
            metric: the metric for training, default 'accuracy'. Warning: Currently tensorflow metrics like AUC need the output and y_true to be one-hot to cauculate, they are not supported.
            alpha: parameter for DSC loss
        Tr   333333?r   c                    sn   t    || _|| _|| _t|tr%|dkr!tjj	j
dd| _ntd| j| _tjj	jdd| _|| _d S r   )r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   alpha)r"   r   r   r   rd   r#   r   r   r   a   s   


z ModelWithCRFLossDSCLoss.__init__Fc                 C   r%   r&   r'   r(   r   r   r   r+   p   r,   zModelWithCRFLossDSCLoss.callc                 C   sn   | ||d\}}}}t ||||d  }	t||| j}
|d ur+|	|d  }	|
|d  }
||t|	t|
fS )Nr-   r   r   )r   r   rd   r   r.   )r"   r/   r0   rK   r*   r1   r2   r3   r4   r5   ds_lossr   r   r   r6   v   s   z$ModelWithCRFLossDSCLoss.compute_lossc              	   C   s   t |\}}}| jrt|jdksJ ntj|dd}t $}| j|||dd\}}}}	||	 tt	| j
|j }
W d    n1 sFw   Y  ||
| j}| jt|| j | j|
 | j||t||jd  d| j | jj| j iS r7   r;   )r"   r
   r/   r0   rK   rL   r1   r3   r5   re   r   rM   r   r   r   rN      s   
 z"ModelWithCRFLossDSCLoss.train_stepc                 C   rO   rP   rQ   rR   r   r   r   r      rS   zModelWithCRFLossDSCLoss.metricsc           
   	   C   s   t |\}}}| jrt|jdksJ ntj|dd}| j|||dd\}}}}|| tt| j	|j
 }	| j|	 | j||t||jd  d| j d| jj | j iS rT   rW   )
r"   r
   r/   r0   rK   r1   r3   r5   re   r   r   r   r   rX      s   "z!ModelWithCRFLossDSCLoss.test_step)Tr   rc   rY   rZ   r   r   r#   r   rb   W   s    	



rb   )typingr   
tensorflowr   tensorflow_addons.text.crfr   other_lossesr   r   r   Modelr   rb   r   r   r   r   <module>   s    	E