U
    d3                     @   s4   d dl Zd dlmZmZmZmZ G dd deZdS )    N)brewcoremodel_helper	recurrentc                   @   sd   e Zd ZdddZdddZdddZdd	 Zdd
dZdd Zdd Z	e
dd Ze
dd ZdS )CRFWithLossNc                 C   s\   || _ || _|d | _|sB| j jjg tdg| j| jgddd}|| _| j j	| j d S )N   Zcrf_transitionsg      g      ?)shapeminmax)
modelnum_classesnum_classes_paddedparam_init_netZUniformFillr   ScopedBlobReferencetransitionsparamsappend)selfr   r   Ztransitions_blob r   5/tmp/pip-unpacked-wheel-ua33x9lu/caffe2/python/crf.py__init__   s    


zCRFWithLoss.__init__c                 C   s4  | j j| jtd}| ||| j}t	|| j j
| j j| j}t|| j j
| j j| j}| |||}| j j||gtd}| j j
jg dgdd}| j jj||gtddd}	| j jj|gddd	d
\}
}| j jj|
gtddgd}
| j j|td}| |
|	|}| j j||gtd}|S )Ntransitions_snapshotZ
path_total   r   r   valueZrnn_initialTZdense_gradientr   )padding_widthend_padding_widthoutputsZrnn_input_dataZdimstransitions_copycrf_loss)r   netZCopyr   r   r   _gather_entries_sumr   r   pad_predictionsr   
pad_labels_path_binary_scoresAddConstantFillGatherRemovePadding
ExpandDims_crf_forwardZSub)r   predictionslabelsseq_lengthsr   Zpath_unary_scoreZpath_binary_scoreZpath_total_score
zero_indexinitial_stateZ
input_data_r    Zall_paths_scoresZlossr   r   r   r!       sz                  
      zCRFWithLoss.crf_lossc                 C   s   | j jj|gdddd\}}| j jj|gdddd\}}| j jj|g| jd}| j j||g}| j j||g}| j j|g}	| j jj|	|gdd}
| j 	|
S )Nr   r   r   )r   r   r   r   Tr   )
r   r"   r*   r(   r   ZMulr'   FlattenToVecr)   ReduceFrontSum)r   r.   r   r/   Z
column_idsr2   Zrow_idsZnum_columns_blobZflattened_idsZflattened_transitionsentriesr   r   r   r&   T   s0       
   
  zCRFWithLoss._path_binary_scoresc           
      C   s~   | j jj|gdd}| j jjg dg|d}| j j||g}| j j|}| j j|}| j j||g}| j j|g}	|	S )Nint64tor   r   )	r   r"   Castr   r(   ZOneHotr4   Z
DotProductr5   )
r   Zin_dataindicesZ
index_sizeZindex_size_blobZquery_one_hotZflattend_queryZflattend_dataZquery_scoresZ	final_sumr   r   r   r#   i   s      zCRFWithLoss._gather_entries_sumc           	      C   sx   |  |||}| jjj|gd| jfd\}}| jjjg d| jgtjj	d}| jj
||g}| jjj|ddd\}}|S )Nr   )r   r   r   r   r   dtyper   )build_crf_netr   r"   Reshaper   r   r(   r   DataTypeINT32SortedSegmentRangeLogSumExp)	r   
input_blobr1   r    r/   out_lastr2   zero_segment_idZaccum_scorer   r   r   r,   u   s"      
   zCRFWithLoss._crf_forwardc              	      s  d  fdd}t jd| jd}|jtdtd|\}}}|jjg |dgd	| j	gtj
jd
}	|j|	 tj|||dgdd}
|jj|
|dg| j	dd}|jj||dg| j	dd}|j||g|dg}|jj||g|dgddd}|jj||d|dg| j	| j	fd\}}|j||	g|dg}|j| |}tj| jj|j||fg||fg||i dd\}}|S )a  
            Adds the crf_net recurrent operator to the model.

            model: model_helper.ModelHelper object new operators would be added
            to

            input_blob: the input sequence in a format T x N x D
            where T is sequence size, N - batch size and D - input dimension
            ##Only supports batch-size 1##

            seq_lengths: blob containing sequence lengths (unused)
            Zcrf_netc                    s   d t t| S ) z{}/{})formatstr)namescoper   r   s   s    z$CRFWithLoss.build_crf_net.<locals>.sZcrf_step)rI   Zparam_modelinput_tcell_t_prevrE   r   r<   prev_transpose)r   r   r   )Zaxes
prev_tiledr   )Ztilesaxisinput_t_tiledr   input_with_prevZprev_with_transitions)	broadcastZuse_grad_hackall_with_transitions_reshapedZall_with_transitions_orig)r   cell_t)r   )r"   Zcell_netinputsZinitial_cell_inputslinksrK   Zoutputs_with_grads)r   ZModelHelperr   r"   ZAddExternalInputsr   r   r   r(   r   r@   rA   ZAddExternalOutputr   Z	transposeZTiler'   r?   rB   ZAddExternalOutputsr   Zrecurrent_net)r   rC   r1   r   rL   Z
step_modelrM   rN   r2   rE   rO   rP   rR   rS   Zall_with_transitionsrU   rV   Zcell_input_blobZout_allrD   r   rJ   r   r>      s    
	          

 
	zCRFWithLoss.build_crf_netc                 C   sF   dd }t || jj| jj| j}| jj||| jgt	d}|S )Nc                 S   s  | d j }| d j }| d j }| d j}|d | t|}tj|tjd}|d |d< td|d D ]D}t||d  d| }|| t|d ||< t	|d||< qjt	|d g}	t
|dd  D ]}
|	|
|	d   q|	  t|}g }t|D ]T\}}|| ||< t	|}|| || ||	|   ||	| < ||< |||< q|ddddf }|d |j ||d j d< d S )Nr   r   )r=   .)datar   Zreshapenpzerosint32rangeZexpand_dimsr
   Zargmaxreversedr   reverse	enumerate)rW   r   r-   r   Zpredictions_shapeZtrellisZbackpointerstvZviterbiZbpZnew_predictionsZ	old_bestsiZw_predictionsZold_bestZorig_predictionsr   r   r   crf_update_predictions_op   s:    








zACRFWithLoss.update_predictions.<locals>.crf_update_predictions_opZpost_crf_classes)
r   r$   r   r   r"   r   Pythonr   r   r   )r   classesrf   Zpadded_classesZnew_classesr   r   r   update_predictions   s    +   zCRFWithLoss.update_predictionsc           
      C   s^   |}|d }|j g dg|d}|j g dg|d}|j| gdd} |j|| |gddd\}}	|S )Nr   r   r7   r8   r   r   )rQ   r   )r(   r:   Concat)
r.   init_netr"   r   Zbos_iZeos_iZbos_i_bZeos_i_bZpadded_labelsr2   r   r   r   r%     s    zCRFWithLoss.pad_labelsc                 C   s  d}t |g| d|g gt j}t |g| |dg gt j}|jg dd|d g|d}|jg dd|d g|d}|jg dgdd}||| g|g}|j|d	d
}|	|}	|j|	g|d}
|j
|
dgd}
|j| |
|
gddd\}}|j|||gddd\}}|S )Ng     @r   b_scoresr   r   )r   valuese_scoresr   r^   r8   r3   r   )r   rQ   )r\   arrayZastypeZfloat32ZGivenTensorFillr(   r)   ZShaper:   ZLengthsRangeFillr+   rj   )r-   rk   r"   r   Z	low_scorerl   rn   r0   lengthZt_rangepaddingZpadded_predictionsr2   Zpadded_predictions_concatr   r   r   r$     sH      
   
 
  
  
zCRFWithLoss.pad_predictions)N)N)N)N)__name__
__module____qualname__r   r!   r&   r#   r,   r>   ri   staticmethodr%   r$   r   r   r   r   r      s   

4
 
P5
	r   )	Znumpyr\   Zcaffe2.pythonr   r   r   r   objectr   r   r   r   r   <module>   s   
