B
    #=6\4                 @   sL   d dl mZmZmZmZ d dlZd dlmZm	Z	m
Z
mZ G dd deZdS )    )absolute_importdivisionprint_functionunicode_literalsN)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   4/tmp/pip-install-l3r2oljg/torch/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)dense_gradientr   )padding_widthend_padding_widthoutputsZrnn_input_data)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$       s:    

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   T)r   )
r   r%   r-   r+   r   ZMulr*   FlattenToVecr,   ReduceFrontSum)r   r1   r   r2   Z
column_idsr5   Zrow_idsZnum_columns_blobZflattened_idsZflattened_transitionsentriesr   r   r   r)   T   s    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   r%   Castr   r+   ZOneHotr6   Z
DotProductr7   )
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_blobr4   r#   r2   out_lastr5   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 dimention
            ##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   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linksrJ   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   r4   r   rK   Z
step_modelrL   rM   r5   rE   rN   rO   rQ   rR   Zall_with_transitionsrT   rU   Zcell_input_blobZout_allrD   r   )rJ   r   r>      sX    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< xVtd|d D ]D}t||d  d| }|| t|d ||< t	|d||< qlW t	|d g}	x*t
|dd  D ]}
|	|
|	d   qW |	  t|}g }x`t|D ]T\}}|| ||< t	|}|| || ||	|   ||	| < ||< |||< qW |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)rV   r!   r0   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   s8    







zACRFWithLoss.update_predictions.<locals>.crf_update_predictions_opZpost_crf_classes)
r
   r'   r   r   r%   r   Pythonr   r   r   )r   classesre   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   r   r9   )r:   r   r   )rP   r!   )r+   r;   Concat)
r1   init_netr%   r   Zbos_iZeos_iZbos_i_bZeos_i_bZpadded_labelsr5   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_scores)r   r   r]   )r:   )r   )r"   )r!   rP   )r[   arrayZastypeZfloat32ZGivenTensorFillr+   r,   ZShaper;   ZLengthsRangeFillr.   ri   )r0   rj   r%   r   Z	low_scorerk   rm   r3   lengthZt_rangepaddingZpadded_predictionsr5   Zpadded_predictions_concatr   r   r   r'     s(    
zCRFWithLoss.pad_predictions)N)N)N)N)__name__
__module____qualname__r   r$   r)   r&   r/   r>   rh   staticmethodr(   r'   r   r   r   r   r
      s   

4

P5
r
   )
__future__r   r   r   r   Znumpyr[   Zcaffe2.pythonr   r   r   r	   objectr
   r   r   r   r   <module>   s   
