B
    /`\                 @   s  d dl Z d dlZd dlZd dlmZ d dlmZ d dl	m
Z
 eeejdddZeeeeejdd	d
ZeeeeejdddZeeeejdddZd,eeee
e ejdddZeeeejdddZeeeejdddZeeeeejdddZeeejdddZG dd  d ejjjZeeeeejdd!d"Zeeejd#d$d%Zeeeejd&d'd(Zeeeeejd)d*d+ZdS )-    N)
TensorLike)typechecked)Optional)inputs
tag_bitmapreturnc             C   s.   t || t t | t td| j}|S )a  Constrains the inputs to filter out certain tags at each time step.

    tag_bitmap limits the allowed tags at each input time step.
    This is useful when an observed output at a given time step needs to be
    constrained to a selected set of tags.

    Args:
      inputs: A [batch_size, max_seq_len, num_tags] tensor of unary potentials
          to use as input to the CRF layer.
      tag_bitmap: A [batch_size, max_seq_len, num_tags] boolean tensor
          representing all active tags at each index for which to calculate the
          unnormalized score.
    Returns:
      filtered_inputs: A [batch_size] vector of unnormalized sequence scores.
    z-inf)tfwherefillshapecastfloatdtype)r   r   filtered_inputs r   I/home/dcms/DCMS/lib/python3.7/site-packages/tensorflow_addons/text/crf.pycrf_filtered_inputs   s
    "r   )r   tag_indicessequence_lengthstransition_paramsr   c                sb   t jt jdt jt jd fdd} fdd}t t t  d d||S )a   Computes the unnormalized score for a tag sequence.

    Args:
      inputs: A [batch_size, max_seq_len, num_tags] tensor of unary potentials
          to use as input to the CRF layer.
      tag_indices: A [batch_size, max_seq_len] matrix of tag indices for which
          we compute the unnormalized score.
      sequence_lengths: A [batch_size] vector of true sequence lengths.
      transition_params: A [num_tags, num_tags] transition matrix.
    Returns:
      sequence_scores: A [batch_size] vector of unnormalized sequence scores.
    )r   c                 s   t j t jdd } t t | ddg}t j|t |gdd}t |}t |ddg}t j||gdd}t  |}t t 	dt ||}|S )N)Zout_typer      )axis)
r   r   int32reshaperangeconcat
zeros_like	gather_ndr	   
less_equal)
batch_sizeZ
batch_indsindicesZtag_indssequence_scores)r   r   r   r   r   _single_seq_fnM   s    
z*crf_sequence_score.<locals>._single_seq_fnc                 s$   t  } t}| | }|S )N)crf_unary_scorecrf_binary_score)unary_scoresbinary_scoresr"   )r   r   r   r   r   r   _multi_seq_fn_   s
    
z)crf_sequence_score.<locals>._multi_seq_fnr   )r   r   r   condequalr   )r   r   r   r   r#   r(   r   )r   r   r   r   r   crf_sequence_score6   s
    	r+   )r   r   r   r   r   c                sf   t j|t jd}t jt jdt| |  fdd} fdd}t t t | d d||S )a  Computes the unnormalized score of all tag sequences matching
    tag_bitmap.

    tag_bitmap enables more than one tag to be considered correct at each time
    step. This is useful when an observed output at a given time step is
    consistent with more than one tag, and thus the log likelihood of that
    observation must take into account all possible consistent tags.

    Using one-hot vectors in tag_bitmap gives results identical to
    crf_sequence_score.

    Args:
      inputs: A [batch_size, max_seq_len, num_tags] tensor of unary potentials
          to use as input to the CRF layer.
      tag_bitmap: A [batch_size, max_seq_len, num_tags] boolean tensor
          representing all active tags at each index for which to calculate the
          unnormalized score.
      sequence_lengths: A [batch_size] vector of true sequence lengths.
      transition_params: A [num_tags, num_tags] transition matrix.
    Returns:
      sequence_scores: A [batch_size] vector of unnormalized sequence scores.
    )r   c                  s   t j ddgddS )Nr      F)r   Zkeepdims)r   reduce_logsumexpr   )r   r   r   r#      s    z3crf_multitag_sequence_score.<locals>._single_seq_fnc                  s   t  dS )N)r   r   r   )crf_log_normr   )r   r   r   r   r   r(      s    z2crf_multitag_sequence_score.<locals>._multi_seq_fnr   )r   r   boolr   r   r)   r*   r   )r   r   r   r   r#   r(   r   )r   r   r   r   crf_multitag_sequence_scorek   s    
	r0   )r   r   r   r   c                sx   t jt jdt dddgdddg t  dg  fdd} fdd}t t t d d||S )	a  Computes the normalization for a CRF.

    Args:
      inputs: A [batch_size, max_seq_len, num_tags] tensor of unary potentials
          to use as input to the CRF layer.
      sequence_lengths: A [batch_size] vector of true sequence lengths.
      transition_params: A [num_tags, num_tags] transition matrix.
    Returns:
      log_norm: A [batch_size] vector of normalizers for a CRF.
    )r   r   r   r   c                 s.   t  dg} t t dt | | } | S )Nr   r   )r   r-   r	   r   r   )log_norm)first_inputr   r   r   r#      s    z$crf_log_norm.<locals>._single_seq_fnc                 sV   t dddgdddg} t|  }t |dg}t t dt ||}|S )z$Forward computation of alpha values.r   r   r   )r   slicecrf_forwardr-   r	   r   r   )Zrest_of_inputalphasr1   )r2   r   r   r   r   r   r(      s    z#crf_log_norm.<locals>._multi_seq_fn)r   r   r   r3   squeezer)   r*   r   )r   r   r   r#   r(   r   )r2   r   r   r   r   r.      s    r.   c       	      C   s   t | } | jd }t j|t jd}t j|t jd}|dkr\t jj }t |||gd}t || j	}t
| |||}t| ||}|| }||fS )a  Computes the log-likelihood of tag sequences in a CRF.

    Args:
      inputs: A [batch_size, max_seq_len, num_tags] tensor of unary potentials
          to use as input to the CRF layer.
      tag_indices: A [batch_size, max_seq_len] matrix of tag indices for which
          we compute the log-likelihood.
      sequence_lengths: A [batch_size] vector of true sequence lengths.
      transition_params: A [num_tags, num_tags] transition matrix,
          if available.
    Returns:
      log_likelihood: A [batch_size] `Tensor` containing the log-likelihood of
        each example, given the sequence of tag indices.
      transition_params: A [num_tags, num_tags] transition matrix. This is
          either provided by the caller or created in this function.
    r,   )r   NZtransitions)r   Zconvert_to_tensorr   r   r   kerasZinitializersZGlorotUniformVariabler   r+   r.   )	r   r   r   r   num_tagsZinitializerr"   r1   Zlog_likelihoodr   r   r   crf_log_likelihood   s    

r:   )r   r   r   r   c             C   s   t j| t jd} t j|t jd}t |d }t |d }t |d }t |dg}t t || | d}|t t || d7 }| jt jkrt |t j}t ||  dg}t t 	||||g}	t j
|t | d |	jd}
t |	|
 d}	|	S )aa  Computes the unary scores of tag sequences.

    Args:
      tag_indices: A [batch_size, max_seq_len] matrix of tag indices.
      sequence_lengths: A [batch_size] vector of true sequence lengths.
      inputs: A [batch_size, max_seq_len, num_tags] tensor of unary potentials.
    Returns:
      unary_scores: A [batch_size] vector of unary scores.
    )r   r   r   r,   r   )maxlenr   )r   r   r   r   r   expand_dimsr   r   int64gathersequence_mask
reduce_sum)r   r   r   r    Zmax_seq_lenr9   Zflattened_inputsoffsetsZflattened_tag_indicesr&   masksr   r   r   r$      s"    r$   )r   r   r   r   c             C   s   t j| t jd} t j|t jd}t |d }t | d d }t | ddgd|g}t | ddgd|g}|| | }t |dg}t ||}	t j|t | d |	jd}
t |
ddgddg}t 	|	| d}	|	S )aa  Computes the binary scores of tag sequences.

    Args:
      tag_indices: A [batch_size, max_seq_len] matrix of tag indices.
      sequence_lengths: A [batch_size] vector of true sequence lengths.
      transition_params: A [num_tags, num_tags] matrix of binary potentials.
    Returns:
      binary_scores: A [batch_size] vector of binary scores.
    )r   r   r   r   )r;   r   )
r   r   r   r   r3   r   r>   r?   r   r@   )r   r   r   r9   Znum_transitionsZstart_tag_indicesZend_tag_indicesZflattened_transition_indicesZflattened_transition_paramsr'   rB   Ztruncated_masksr   r   r   r%   #  s    r%   )r   stater   r   r   c                s   t j|t jd}t t jd|jd|d }t | dddg} t  d  fdd}t t || |dddg}t 	t |d|gd}t j
t t |d |gdd}t ||S )a  Computes the alpha values in a linear-chain CRF.

    See http://www.cs.columbia.edu/~mcollins/fb.pdf for reference.

    Args:
      inputs: A [batch_size, num_tags] matrix of unary potentials.
      state: A [batch_size, num_tags] matrix containing the previous alpha
         values.
      transition_params: A [num_tags, num_tags] matrix of binary potentials.
          This matrix is expanded into a [1, num_tags, num_tags] in preparation
          for the broadcast summation occurring within the cell.
      sequence_lengths: A [batch_size] vector of true sequence lengths.

    Returns:
      new_alphas: A [batch_size, num_tags] matrix containing the
          new alpha values.
    )r   r   r   r,   c                s*   t | d} |   }|t |dg }|S )Nr,   r   )r   r<   r-   )_stateZ_inputstransition_scoresZ
new_alphas)r   r   r   _scan_fnh  s    zcrf_forward.<locals>._scan_fn)r   )r   r   r   maximumconstantr   	transposer<   scanr   stackr   r   r   )r   rC   r   r   
last_indexrF   Z
all_alphasidxsr   )r   r   r4   I  s    "r4   )scorer   r   c       	      C   s   t | }t j| t jd}| d |d< xXtd| jd D ]D}t ||d  d| }| | t |d ||< t |d||< q8W t |d g}x*t|dd D ]}|	||d   qW |
  t |d }||fS )a  Decode the highest scoring sequence of tags outside of TensorFlow.

    This should only be used at test time.

    Args:
      score: A [seq_len, num_tags] matrix of unary potentials.
      transition_params: A [num_tags, num_tags] matrix of binary potentials.

    Returns:
      viterbi: A [seq_len] list of integers containing the highest scoring tag
          indices.
      viterbi_score: A float containing the score for the Viterbi sequence.
    )r   r   r   r   N)npr   r   r   r   r<   maxargmaxreversedappendreverse)	rN   r   ZtrellisbackpointerstvZviterbiZbpZviterbi_scorer   r   r   viterbi_decodev  s    
rX   c                   s|   e Zd ZdZeed fddZedd Zedd Z	 fd	d
Z
dd Zed fddZeed dddZ  ZS )CrfDecodeForwardRnnCellz4Computes the forward decoding in a linear-chain CRF.)r   c                s,   t  jf | t|d| _|jd | _dS )a1  Initialize the CrfDecodeForwardRnnCell.

        Args:
          transition_params: A [num_tags, num_tags] matrix of binary
            potentials. This matrix is expanded into a
            [1, num_tags, num_tags] in preparation for the broadcast
            summation occurring within the cell.
        r   N)super__init__r   r<   _transition_paramsr   	_num_tags)selfr   kwargs)	__class__r   r   r[     s    
z CrfDecodeForwardRnnCell.__init__c             C   s   | j S )N)r]   )r^   r   r   r   
state_size  s    z"CrfDecodeForwardRnnCell.state_sizec             C   s   | j S )N)r]   )r^   r   r   r   output_size  s    z#CrfDecodeForwardRnnCell.output_sizec                s   t  | d S )N)rZ   build)r^   Zinput_shape)r`   r   r   rc     s    zCrfDecodeForwardRnnCell.buildc             C   sZ   t |d d}|t | j| j }|t |dg }t |d}t j|t jd}||fS )a  Build the CrfDecodeForwardRnnCell.

        Args:
          inputs: A [batch_size, num_tags] matrix of unary potentials.
          state: A [batch_size, num_tags] matrix containing the previous step's
                score values.

        Returns:
          backpointers: A [batch_size, num_tags] matrix of backpointers.
          new_state: A [batch_size, num_tags] matrix of new score values.
        r   r,   r   )r   )r   r<   r   r\   Z_compute_dtype
reduce_maxrQ   r   )r^   r   rC   rE   Z	new_staterU   r   r   r   call  s    zCrfDecodeForwardRnnCell.call)r   c                sD   dt | jd  i}tt|  }tt	|
 t	|
  S )Nr   r   )r   r6   r\   numpytolistrZ   rY   
get_configdictlistitems)r^   configZbase_config)r`   r   r   rh     s    z"CrfDecodeForwardRnnCell.get_config)rl   r   c             C   s"   t j|d t jd|d< | f |S )Nr   )r   )rO   arrayfloat32)clsrl   r   r   r   from_config  s    z#CrfDecodeForwardRnnCell.from_config)__name__
__module____qualname____doc__r   r   r[   propertyra   rb   rc   re   ri   rh   classmethodrp   __classcell__r   r   )r`   r   rY     s   rY   c             C   sZ   t j|t jd}t |t | d }t|| jd}t jjj	|dd| jd}|| ||dS )a  Computes forward decoding in a linear-chain CRF.

    Args:
      inputs: A [batch_size, num_tags] matrix of unary potentials.
      state: A [batch_size, num_tags] matrix containing the previous step's
            score values.
      transition_params: A [num_tags, num_tags] matrix of binary potentials.
      sequence_lengths: A [batch_size] vector of true sequence lengths.

    Returns:
      backpointers: A [batch_size, num_tags] matrix of backpointers.
      new_state: A [batch_size, num_tags] matrix of new score values.
    )r   r   T)Zreturn_sequencesZreturn_stater   )mask)
r   r   r   r?   r   rY   r   r7   layersZRNN)r   rC   r   r   rx   Zcrf_fwd_cellZcrf_fwd_layerr   r   r   crf_decode_forward  s    rz   )r   rC   r   c             C   s6   t | dddg} dd }t t || |dddgS )aO  Computes backward decoding in a linear-chain CRF.

    Args:
      inputs: A [batch_size, num_tags] matrix of
            backpointer of next step (in time order).
      state: A [batch_size, 1] matrix of tag index of next step.

    Returns:
      new_tags: A [batch_size, num_tags]
        tensor containing the new tag indices.
    r   r   r,   c             S   sL   t j| dgd} t jt t |d | gdd}t jt ||dd}|S )Nr   )r   r   r   )r   r6   rK   r   r   r<   r   )rC   r   rM   Znew_tagsr   r   r   rF      s    "z%crf_decode_backward.<locals>._scan_fn)r   rI   rJ   )r   rC   rF   r   r   r   crf_decode_backward  s    r{   )
potentialsr   sequence_lengthr   c                s   t jdd dkrtd t jt jd fdd} fdd	} jd
 dk	rr jd
 d
krj| S | S n t t t  d
 d
||S dS )a,  Decode the highest scoring sequence of tags.

    Args:
      potentials: A [batch_size, max_seq_len, num_tags] tensor of
                unary potentials.
      transition_params: A [num_tags, num_tags] matrix of
                binary potentials.
      sequence_length: A [batch_size] vector of true sequence lengths.

    Returns:
      decode_tags: A [batch_size, max_seq_len] matrix, with dtype `tf.int32`.
                  Contains the highest scoring tag indices.
      best_score: A [batch_size] vector, containing the score of `decode_tags`.
    N   z2.4zsCRF Decoding does not work with KerasTensors in TF2.4. The bug has since been fixed in tensorflow/tensorflow##45534)r   c                 s<   t jt j ddt jd} t jt j dddgd}| |fS )Nr,   )r   )r   r   )r   )r   r   rQ   r   r   rd   )decode_tags
best_score)r|   r   r   r#   "  s    z"crf_decode.<locals>._single_seq_fnc                 s   t  dddgdddg} t j| dgd} t  dddgdddg}t t jdt jdd }t|| |\}}t j||dd}t jt j	|ddt jd} t j
| dd} t|| }t j|dgd}t j| |gdd}t j|dd}t j|dd}||fS )Nr   r   r   )r   )r   )Zseq_axisr,   )r   r3   r6   rG   rH   r   rz   Zreverse_sequencer   rQ   r<   r{   r   rd   )Zinitial_stater   Zsequence_length_less_onerU   Z
last_scorer   r   )r|   r}   r   r   r   r(   '  s"    
z!crf_decode.<locals>._multi_seq_fnr   )	r   __version__warningswarnr   r   r   r)   r*   )r|   r   r}   r#   r(   r   )r|   r}   r   r   
crf_decode	  s    r   )r|   r   r   r}   r   c             C   s   t | |}t|||S )a  Decode the highest scoring sequence of tags under constraints.

    This is a function for tensor.

    Args:
      potentials: A [batch_size, max_seq_len, num_tags] tensor of
                unary potentials.
      tag_bitmap: A [batch_size, max_seq_len, num_tags] boolean tensor
          representing all active tags at each index for which to calculate the
          unnormalized score.
      transition_params: A [num_tags, num_tags] matrix of
                binary potentials.
      sequence_length: A [batch_size] vector of true sequence lengths.
    Returns:
      decode_tags: A [batch_size, max_seq_len] matrix, with dtype `tf.int32`.
                  Contains the highest scoring tag indices.
      best_score: A [batch_size] vector, containing the score of `decode_tags`.
    )r   r   )r|   r   r   r}   Zfiltered_potentialsr   r   r   crf_constrained_decodeQ  s    
r   )N)r   rf   rO   Z
tensorflowr   Ztensorflow_addons.utils.typesr   Z	typeguardr   typingr   ZTensorr   r+   r0   r.   r:   r$   r%   r4   rX   r7   ry   ZAbstractRNNCellrY   rz   r{   r   r   r   r   r   r   <module>   sX   1-2+'%( AG