U
    d                  	   @   s  d dl Z d dlZd dlZd dlZd dlZd dlmZmZ d dl	m
Z
 d dlmZmZmZ d dlmZ e  edZeej dd Zd	d
 Zdd Zdd Zdd Zdd Zdd Zdd ZG dd deZdd Z dd Z!dd Z"dd  Z#e$d!d"d# Z%e$d$d%d& Z&e$d'd(d) Z'd*d+ Z(e$d,d-d. Z)e$d/d0d1 Z*e$d2d3d4 Z+e$d5d6d7 Z,e$d8d9d: Z-e$d;d<d= Z.e$d>d?d@ Z/e$dAdBdC Z0e$dDdEdF Z1e$dGdHdI Z2e$dJdKdL Z3e$dMdNdO Z4e$dPdQdR Z5e$dSdTdU Z6e$dVdWdX Z7e$dYdZd[ Z8e$d\d]d^ Z9e$d_d`da Z:e$dbdcdd Z;e$dedfdg Z<e$dhdidj Z=e$dkdldm Z>e$dndodp Z?e$dqdrds Z@e$dtdudv ZAeBdwkre jCdxdyZDeDjEdzd{d| eDjEd}d~d| eDjEdddd eDjEdddd eDjEddddd eDjEdddeFg d eDG ZHe
I ZJe
I ZKeHjLZMeHjNZOeHjPZQeHjRZSeTeMZUeVeUW eJ W 5 Q R X eTeOdZUeKXeUW  W 5 Q R X e eJeKdeHjYeHjZd\Z[Z\e[j]d  j^d  Z_e[j]d j`d  Zae[j_be_g e[j_bdd e\jcD  e[jabeag e!e\e_ZPeTeSdZUeUde[e  W 5 Q R X eTeSd dZUeUdefe[ W 5 Q R X eTeQdZUeUdePe  W 5 Q R X dS )    N)
caffe2_pb2caffe2_legacy_pb2)	caffe_pb2)coreutils	workspace)text_formatZcaffe_translatorc                    s   | dr|j| jkrdS | dr4| j|jk r4dS | drN| j|jkrNdS tt| j t|jrt	 fdd|jD rdS t|j
rt	 fdd|j
D rdS dS )	z@A function that reproduces Caffe's StateMeetsRule functionality.phaseF	min_level	max_levelc                    s   g | ]}| kqS  r   .0sZcurr_stagesr   B/tmp/pip-unpacked-wheel-ua33x9lu/caffe2/python/caffe_translator.py
<listcomp>   s     z#_StateMeetsRule.<locals>.<listcomp>c                    s   g | ]}| kqS r   r   r   r   r   r   r   !   s     T)HasFieldr	   levelr
   r   setlistZstagelenanyZ	not_stage)stateruler   r   r   _StateMeetsRule   s    ""r   c                    sV   t |jdk}|t fdd|jD  M }t |jrR|t fdd|jD O }|S )z@A function that reproduces Caffe's inclusion and exclusion rule.r   c                    s   g | ]}t  |qS r   r   r   r   	net_stater   r   r   +   s     z"_ShouldInclude.<locals>.<listcomp>c                    s   g | ]}t  |qS r   r   r   r   r   r   r   .   s     )r   includer   exclude)r   layerretr   r   r   _ShouldInclude'   s
    
r$   c                 C   s   i }t j }|jD ]}||jt| q| j	d j
d }||| tt| j	D ]B}| j	| }	||	  ||kr`|	jd }
||
}|j||< q`|S Nr   r   C	Workspaceprotoscreate_blobnamefeedr   Caffe2TensorToNumpyArrayopinputranger   _run_operatorSerializeToStringoutput
fetch_blobshape)net
net_paramsdummy_inputlegacy_pad_opsdim_mapwsparamexternal_inputiop_defr3   Zblob_legacyr   r   r   _GetLegacyDims2   s     




r@   c                    sL   i }ddddg}d k}|r6|D ]} d j ||< q n fdd|D }|S )Npad_lpad_tpad_rpad_bpadc                    s   i | ]}| | j qS r   r>   )r   xarg_mapr   r   
<dictcomp>M   s      z%_GetLegacyPadArgs.<locals>.<dictcomp>rF   )r?   rI   padskeysis_padkr   rH   r   _GetLegacyPadArgsE   s    rO   c                 C   s(  |\}}}}|\}	}
}}||	ks$t ||
ks0t d|k}||ksJ||kr$||d krh|d  d7  < n||kr|td||||d kr|d  d7  < n||krtd|||r| j|d  g }| D ]&}t }||_|| |_|	| q| j
| n| D ]}|| || _qd S )NrE      rD   z!Unexpected dimensions for height:rC   z Unexpected dimensions for width:)AssertionError	ExceptionargremoverL   r   ZArgumentr+   r>   appendextend)r?   rI   rK   dim1dim2Zn1Zc1h1Zw1Zn2c2h2Zw2rM   argsr+   rS   r   r   r   _AdjustDimsQ   s2    
r]   c                 C   s  g }t t| jD ]@}| j| }td|jr|jD ]}|jdkr4||  qq4q|r|\}}}	}
t	j
|||	|
t	j}t| |||}tj }| jd jd }||| |jD ]}||jt| qt t| jD ]}| j| }||kri }|jD ]}|||j< qt||}t t|jD ]*}|j| }|jdkr6|j|=  qbq6|jd }|d }||jd< ||  ||}||jd< || }|j}t||||| ||  q| S )Nz0^(Conv|ConvTranspose|MaxPool|AveragePool)(\dD)?$
legacy_padr   Z
_nonlegacy)r0   r   r.   rematchtyperS   r+   rU   nprandomrandnastypefloat32r@   r   r'   r(   r/   r*   Z	feed_blobr)   r   r-   rO   r3   r1   r2   r4   r5   r]   )r6   r7   
input_dimsr9   r>   r?   rS   nchwr8   r:   r;   r=   r<   rI   rK   jr3   Znonlegacy_outputZblob_nonlegacyrW   rX   r   r   r   _RemoveLegacyPadn   sX    















rm   c                 C   s   i }t j }|jD ]}||jt| q| j	d j
d }||| tt| j	D ]<}| j	| }||  |jD ]}	||	}
|
j||	< qq`|S r%   r&   )r6   r7   r8   r:   r;   r<   r=   r>   r?   r3   blobr   r   r   _GetBlobDimMap   s    




ro   c                 C   sL   g }| j r| j }n6| jr&| jd j}n"| jd jjrH| jd jjd j}|S r%   )Z	input_dimZinput_shapedimr"   Zinput_paramr5   )	caffe_netrg   r   r   r   _GetInputDims   s    rr   c                   @   s6   e Zd Zi Zedd Zedd Zed	ddZdS )
TranslatorRegistryc                    s    fdd}|S )z.A decorator for registering gradient mappings.c                    s   |  j < | S N)	registry_)funcclsop_namer   r   Wrapper   s    
z,TranslatorRegistry.Register.<locals>.Wrapperr   )rx   ry   rz   r   rw   r   Register   s    zTranslatorRegistry.Registerc                 K   sl   z | j |j |||f|\}}W n$ tk
rD   tdt| Y nX |d krRg }t|tk	rd|g}||fS )Nz+No translator registered for layer: %s yet.)ru   ra   KeyErrorstrr   )rx   r"   pretrained_blobsis_testkwargs	caffe_opsparamsr   r   r   TranslateLayer   s"    
  z!TranslatorRegistry.TranslateLayerFNc              	      sH  |d krt  n|}t }|j|_t }t|jdkrBtd|sNt	|}|j
D ]ʉ t| svtd j qTtd j  fdd|j
D  fdd|jD  }	t|	dkrtd	n&t|	dkrd
d |	d jD }
ng }
| j |
||||d\}}|j| |j| qT|r@|s4tdt|||}||fS )Nr   zuI think something is wrong. This translation script only accepts new style layers that are stored in the layer field.z(Current net state does not need layer {}zTranslate layer {}c                    s   g | ]}|j  j kr|qS r   r+   r   lr"   r   r   r      s    z5TranslatorRegistry.TranslateModel.<locals>.<listcomp>c                    s   g | ]}|j  j kr|qS r   r   r   r   r   r   r      s   rP   z0huh? more than one pretrained layer of one name?c                 S   s   g | ]}t |qS r   )r   ZCaffeBlobToNumpyArray)r   rn   r   r   r   r     s   )r6   r7   rg   z.Please specify input_dims to remove legacy_pad)r   ZNetStater   NetDefr+   ZTensorProtosr   Zlayers
ValueErrorrr   r"   r$   loginfoformatZblobsr   r.   rV   r)   rQ   rm   )rx   rq   Zpretrained_netr   r   remove_legacy_padrg   r6   r7   Zpretrained_layersr~   	operatorsr   r   r   r   TranslateModel   s`    



    
z!TranslatorRegistry.TranslateModel)FNFN)__name__
__module____qualname__ru   classmethodr{   r   r   r   r   r   r   rs      s   
	
    rs   c                  O   s   t j| |S rt   )rs   r   )r\   r   r   r   r   r     s    r   c              
   C   s   t  }| jD ]Z}t|jdkr(tdtjdg |jgt	
dt|jt	
d|jgd}|j|g q|jtjdg |gdgd	g |S )
aa  Takes the net_params returned from TranslateModel, and wrap it as an
    init net that contain GivenTensorFill.

    This is a very simple feature that only works with float tensors, and is
    only intended to be used in an environment where you want a single
    initialization file - for more complex cases, use a db to store the
    parameters.
    r   z.Only float tensors are supported in this util.ZGivenTensorFillr5   values)rS   ZConstantFillrP   )r5   )r   r   r)   r   Z
float_dataRuntimeErrorr   CreateOperatorr+   r   MakeArgumentr   dimsr.   rV   )r7   Z
input_nameinit_netZtensorr.   r   r   r   ConvertTensorProtosToInitNet  s"    	
   r   c                 C   s.   t  }||_|j| j |j| j |S )zBA simple translate interface that maps the layer input and output.)r   OperatorDefra   r/   rV   bottomr3   top)r"   Zcaffe2_typeZ	caffe2_opr   r   r   BaseTranslate6  s
    r   c                 C   s   | j t||g dS )z*Makes an argument based on the value type.N)rS   rV   r   r   )r.   keyvaluer   r   r   AddArgument?  s    r   ZInputc                 K   s   g g fS rt   r   r"   r~   r   r   r   r   r   TranslateInputH  s    r   Z	VideoDatac                 K   s   g g fS rt   r   r   r   r   r   TranslateVideoDataM  s    r   Datac                 K   s   g g fS rt   r   r   r   r   r   TranslateDataR  s    r   c                 C   s  z~t | jdks,t | jdks,t | jdkr4tdt | jrH| jd nd}t | jr`| jd nd}t | jrx| jd nd}W n& tk
r   | j}| j}| j}Y nX | ds| drt|d| j t|d| j	 nt|d| | ds| drR| j
| jkrt|d	| j
 n8t|d
| j
 t|d| j
 t|d| j t|d| j nt|d	| | dsv| drt|d| j t|d| j nt|d| d S )NrP   zRTranslator currently does not support non-conventional pad/kernel/stride settings.r   stride_hstride_wstridepad_hpad_wrE   rB   rD   rA   rC   kernel_hkernel_wkernel)r   r   kernel_sizerE   NotImplementedError	TypeErrorr   r   r   r   r   r   r   r   )r<   caffe_opr   rE   r   r   r   r   _TranslateStridePadKernelHelperY  s<    r   ZConvolution3Dc           
      K   s   | j }t| d}|jd }|j|d  t|d|j|j|jg t|d|j|j	|j	g d}d}t
|drr|j}t
|dr|j}t|d|||gd	  t|d |d g}	t|d	kr|j|d
  |	t|d  |d
  ||	fS )NConvr   _wkernelsstridestemporal_padrE   rK      _brP   )Zconvolution3d_paramr   r3   r/   rU   r   kernel_depthr   temporal_strider   hasattrr   rE   r   NumpyArrayToCaffe2Tensorr   flatten)
r"   r~   r   r   r<   r   r3   r   spatial_padr   r   r   r   TranslateConvNd  s@    




 r   ZConvolutionc                 K   s  | j }t| d}|jd }|j|d  t|| t|d |d g}t|dkr|j|d  |t|d 	 |d  |j
dkrt|d|j
 t|jdkrt|jdkrt|d|jd  n2t|jdkrt|d	|jd  t|d
|jd  ||fS )Nr   r   r   r   r   rP   groupdilationZ
dilation_hZ
dilation_w)convolution_paramr   r3   r/   rU   r   r   r   r   r   r   r   r   )r"   r~   r   r   r<   r   r3   r   r   r   r   TranslateConv  s0    



 
r   ZDeconvolutionc           	      K   s   | j }|jdkrtdt| d}|jd }t|| |j|d g t|dd t	
|d |d }|jrt	
|d  |d }|j|d g |||gfS ||gfS d S )	NrP   z:Translator currently does not support group deconvolution.ZConvTransposer   r   orderNCHWr   )r   r   r   r   r3   r   r/   rV   r   r   r   Z	bias_termr   	r"   r~   r   r   r<   r   r3   weightbiasr   r   r   TranslateDeconv  s&    




 r   ZCropc                    sf  |d |d |d   }}}|\}}}	}
t j|||	|
t j}t|||}| j}|j|j }t	| d}|j
d }||  g g  }}t|| }tdkstdt|D ]}|d |d q fd	d
t||D }|| |d gt|  t }|j
|j
d g |j|j |j|j |j|_t|d| t|d| |g fS )Nr6   r7   rg   ZSlicerP   z@Caffe Translator for Crop only works for offset     of 1 for nowr   c                    s    g | ]}t d   |  qS )r   )int)r   r>   Zinput_1_dimoffsetsr   r   r     s     z!TranslateCrop.<locals>.<listcomp>startsends)rb   rc   rd   re   rf   ro   Z
crop_paramaxisoffsetr   r/   r   rQ   r0   rU   rV   r   r   r3   rS   ra   r   )r"   r~   r   r   r6   r7   rg   rh   ri   rj   rk   r8   r:   r<   r   r   Zinput_1r   r   r   _Z
end_offsetr.   r   r   r   TranslateCrop  s4    




r   ZReLUc                 K   s   t | dg fS )NZRelur   r   r   r   r   TranslateRelu  s    r   ZPoolingc                 K   s   | j }|jtjjkr t| d}n|jtjjkr8t| d}t|| t|dd z
|j	}W n t
k
rp   d}Y nX |st|dtj |jrt|dd |g fS )	NMaxPoolAveragePoolr   r   Fr^   global_poolingrP   )Zpooling_parampoolr   ZPoolingParameterMAXr   AVEr   r   Ztorch_poolingAttributeErrorr   ZCAFFE_LEGACY_POOLINGr   )r"   r~   r   r   r<   r   Zis_torch_poolingr   r   r   TranslatePool  s$    

	

r   Z	Pooling3Dc                 K   s   | j }|jtjjkr t| d}n|jtjjkr8t| d}t|dd t|d|j|j	|j	g t|d|j
|j|jg d}d}t|dr|j}t|d	r|j}t|d
|||gd  |g fS )Nr   r   r   r   r   r   r   r   rE   rK   r   )Zpooling3d_paramr   r   ZPooling3DParameterr   r   r   r   r   r   r   r   r   r   rE   )r"   r~   r   r   r<   r   r   r   r   r   r   TranslatePool3D  s0    


r   LRNc                 K   s   t | d}|jd|jd  d g | j}|jtjjkrBtdt	|dt
|j t	|dt|j t	|dt|j t	|d	t|j t	|d
d |g fS )Nr   r   r   _scalez8Does not support norm region other than across channels.sizealphabetar   r   r   )r   r3   rV   Z	lrn_paramZnorm_regionr   ZLRNParameterZACROSS_CHANNELSr   r   r   Z
local_sizefloatr   r   rN   r"   r~   r   r   r   r<   r   r   r   TranslateLRN7  s    
r   ZInnerProductc           	      K   s  | j }z|jdks|jr tdW n tk
r6   Y nX t| d}|jd }|j|d |d g |d j	dkrztd|d j	d	krt
|d jd d
 ddgkrtdt|d j t|d d|d jd |d }t|d  |d }|||gfS )NrP   zWe don't have testing case for non-default axis and transpose cases yet so we are disabling it for now. If you have a model with this, please do send us your model for us to update this support, and you are more than welcome to send a PR for this.ZFCr   r   r   )r      zUnexpected weight ndim.r   r   z_If pretrained blob has 4 dims (old-style Caffe), the first two should be of value 1, but I got r   )Zinner_product_paramr   Z	transposer   r   r   r3   r/   rV   ndimr   r5   r}   r   r   Zreshaper   r   r   r   r   TranslateInnerProductG  s<    


 r   Dropoutc                 K   sR   t | d}|jd|jd  d g | j}t|d|j |rJt|dd |g fS )Nr   r   r   Z_maskZratior   rP   )r   r3   rV   Zdropout_paramr   Zdropout_ratior   r   r   r   TranslateDropoutk  s    
r   Softmaxc                 K   s   t | d}|g fS )Nr   r   r"   r~   r   r   r   r   r   r   TranslateSoftmaxv  s    
r   ZSoftmaxWithLossc                 K   sp   t d| jd g| jd d }t d|jd | jd g| jd d }t d|jd | jd }|||gg fS )Nr   r   Z_translator_autogen_softmaxZLabelCrossEntropyrP   Z_translator_autogen_xentZAveragedLoss)r   r   r   r3   r   )r"   r~   r   r   Z
softmax_opZxent_opZloss_opr   r   r   TranslateSoftmaxWithLoss|  s      
r   Accuracyc                 K   s.   t | d}| jjdkr&t|d| jj |g fS )Nr   rP   top_k)r   Zaccuracy_paramr   r   r   r   r   r   TranslateAccuracy  s    
r   Concatc                 K   s:   t | d}|jd|jd  d g t|dd |g fS )Nr   r   r   _dimsr   r   )r   r3   rV   r   r   r   r   r   TranslateConcat  s    
r   ZTanHc                 K   s   t | d}|g fS )NZTanhr   r   r   r   r   TranslateTanH  s    
r   InstanceNormc                 K   st   t | d}|jd }t|d  |d }t|d  |d }|j|d |d g t|dd |||gfS )Nr   r   r   rP   r   r   r   )r   r3   r   r   r   r/   rV   r   )r"   r~   r   r   r   r3   r   r   r   r   r   TranslateInstanceNorm  s    


 
 r   Z	BatchNormc                 K   s  t | d}|jd }| j}t|d| t|d|j t|dd |j|d |d |d	 |d
 g |s|j|d	 |d
 |d |d g |d jd }|d d dkrt	d|d d  |d  |d	 }t	d|d d  |d  |d
 }	nt
dt|dkr<t	|d  |d }
t	|d  |d }nPd|d d< t|d |f|d< t	|d |d }
t	t|d |d }||
|||	gfS )NZ	SpatialBNr   r   epsilonr   r   r   Z_biasZ_meanZ_varZ_saved_meanZ
_saved_varr   g      ?rP   zscalar is zero.   r   )r   r3   Zbatch_norm_paramr   Zepsr/   rV   r5   r   r   r   r   r   rb   ZtileZ
zeros_like)r"   r~   r   r   r   r3   r<   Z
n_channelsZmeanvarZscaler   r   r   r   TranslateBatchNorm  sh    



r   ZEltwisec                 K   s4   | j }t|js|jdkr"tdt| d}|g fS )NrP   z(This eltwise layer is not yet supported.ZSum)Zeltwise_paramr   Zcoeff	operationr   r   r"   r~   r   r   r<   r   r   r   r   TranslateElementWise  s
    
r  ZScalec                 K   s  t | d}| j}t|d|j t|dd t|jdkr\|jdkrLtd|jd }|d }|j	| g }|	t
|d  | d }	t|dkrnt|d	kr t|}	d
|	_|d }
|d }|jd d = |j	| |	jd d = |	j	| |	j	|
 |	t
|d  |
 ntd|g}|	r>|	|	 t|t|ksTt||fS t|jd	krvtdntdd S )NZMulr   	broadcastTrP   z$This path has not been verified yet.r   Zscale_wr   ZAddZscale_b	_internalz.Unexpected number of pretrained blobs in ScalezUnexpected number of inputs.)r   scale_paramr   r   r   r/   Znum_axesr   r3   rU   r   r   r   copydeepcopyra   rQ   )r"   r~   r   r   Zmul_opr  r3   Zmul_op_paramweightsZadd_opZadd_op_paramZinternal_blobr   r   r   r   TranslateScale  sR    



 

 

r  Reshapec                 K   sB   t | d}|jd|jd  d  | j}t|d|jj |g fS )Nr	  r   r   r   r5   )r   r3   rU   r/   reshape_paramr   r5   rp   )r"   r~   r   r   r   r
  r   r   r   TranslateReshape$  s
    
r  Flattenc                 K   s\   | j }|jdkrtd|jdkr.t| d}n&|jdkrDt| d}ntd|j|g fS )Nr   z)flatten_param.end_axis not supported yet.r   ZFlattenToVecrP   r  z,Not supported yet for flatten_param.axis {}.)Zflatten_paramZend_axisr   r   r   r   r   r   r   r   TranslateFlatten-  s    



r  Sigmoidc                 K   s   t | d}|g fS )Nr  r   r   r   r   r   TranslateSigmoid?  s    
r  Z
ROIPoolingc                 K   s   t | d}t|dd |r(t|d| n|j|jd d  | j}|dr\t|d|j |drtt|d|j |d	rt|d	|j |g fS )
NZRoIPoolr   r   r   r   Z	_argmaxespooled_hpooled_wspatial_scale)	r   r   r3   rU   Zroi_pooling_paramr   r  r  r  r   r   r   r   TranslateROIPoolingE  s    



r  ZPReLUc                 K   sD   t | d}|jd }|j|d g t|d |d }||gfS )NZPRelur   Z_Slope)r   r3   r/   rV   r   r   )r"   r~   r   r   r   r3   Zsloper   r   r   TranslatePRelu[  s
    

r  Z	Reductionc                 K   sp   | j }|jtjjkr t| d}n"|jtjjkr:t| d}ntd|jdkrTtd|j }t	|d| |g fS )NZReduceBackSumZReduceBackMeanzNot yet supportedr   num_reduce_dim)
Zreduction_paramr   r   ZReductionParameterZSUMr   ZMEANr   r   r   )r"   r~   r   r   r<   r   r  r   r   r   TranslateReductione  s    
r  __main__z>Utilitity to convert pretrained caffe models to Caffe2 models.)description	prototextzCaffe prototext.)help
caffemodelzCaffe trained model.z
--init_netzCaffe2 initialization net.zinit_net.pb)r  defaultz--predict_netzCaffe2 prediction net.zpredict_net.pbz--remove_legacy_padzSRemove legacy pad                         (Only works for nets with one input blob)
store_trueF)r  actionr  z--input_dimszDimension of input blob+)r  nargsra   r  rbT)r   r   rg   r   c                 C   s   g | ]
}|j qS r   r   )r   r<   r   r   r   r     s     r   wbtxtrk   )gargparser  loggingr_   Znumpyrb   Zcaffe2.protor   r   Zcaffe.protor   Zcaffe2.pythonr   r   r   Zgoogle.protobufr   basicConfig	getLoggerr   setLevelINFOr   r$   r@   rO   r]   rm   ro   rr   objectrs   r   r   r   r   r{   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r  r  r  r  r   ArgumentParserparseradd_argumentr   
parse_argsr\   ZNetParameterZcaffenetZcaffenet_pretrainedr  Zinput_protor  Zinput_caffemodelr   Zoutput_init_netZpredict_netZoutput_predict_netopenfZMergereadZParseFromStringr   rg   r6   Zpretrained_paramsr.   r/   r=   r3   Zexternal_outputrV   r)   writer2   r}   r   r   r   r   <module>   s  
7W		


*
"







#








5


3




	


 
  

