a
    ==icP$                     @   s^   d dl mZ d dlmZ d dlmZ d dlmZ d dlZd dl	Z
dd ZG dd	 d	eeZdS )
    )get_current_scope)schema)
ModelLayer)SamplingTrainableMixinNc                 C   s   | dv sJ d | | S )N)fp32fp16znOnly support fp32 and fp16 for the fully connected layer in the predictor net, the provided FC precision is {})format)
fc_version r
   h/home/droni/.local/share/virtualenvs/DPS-5Je3_V2c/lib/python3.9/site-packages/caffe2/python/layers/fc.pyget_fc_predictor_version   s    
r   c                       s^   e Zd Zd fdd	Zedd	 Zd
d Zdd Zdd Zdd Z	dd Z
edd Z  ZS )FCNfc   F      ?c              
      s  t t| j|||fi | t|tjs6J d|t| d j	dksTJ d|dksjJ d||| _
t| d j	|d d  }|dksJ d|d | _|d ur>t|dksJ d|\}}|d us|d usJ d	|d u s|d u s||k sJ d
i | _|d ur*|| jd< |d ur>|| jd< |d u rLd}t|| }|rd|nd| |df}|r~|nd| |df}t|||| _|| _| jd u st| jdkr|r||gn||g}| jd||||	d| _| jd|g|||
d| _n~g | _g | _t| jD ]f\}}|r2||gn||g}| j| jd|||||	d | j| jd||g|||	d q|dkr|f}n,t| d j	d|d  }t||g }ttj|f| d| _d S )NzIncorrect input type {}r   z1FC expects limited dimensions of the input tensorr   zaxis {} should >= 1.z'FC expects input dimensions > 0, got {}   zUclip_param must be a tuple / list of length 2 and in the form of (clip_min, clip max)z8clip_min, and clip_max in clip_param cannot both be Nonez?clip_param = [clip_min, clip_max] must have clip_min < clip_maxminmaxr   ZUniformFill)r   r   w)
param_nameshapeZinitializerZ	optimizerZregularizerbzw_sub_{}zb_sub_{}output)superr   __init__
isinstancer   ZScalarr   lenZfield_typesr   axisnpprod	clip_argsmathsqrtcalculate_fc_output_dimsoutput_dim_vec
transposedZcreate_paramr   r   w_vecb_vec	enumerateappendlisttuplefloat32Zget_next_blob_referenceoutput_schema)selfmodelinput_recordZoutput_dimsZweight_initZ	bias_initZweight_optimZ
bias_optimnameZ
weight_regZbias_regZ
clip_parammax_fc_sizer   r%   Z#uniform_weight_init_scale_numeratorkwargsZ
input_dimsZclip_minZclip_maxscaleZweight_shapeidx
output_dimZoutput_shape	__class__r
   r   r      s     










zFC.__init__c                 C   sx   | r| dk rd S | |ks(J d | |tt| | }tt|d | d }|g|d  }||t|  |S )Nr   zwCurrently we split along the output dimension. So we need max_fc_size >= input_dim. But, max_fc_size: {}, input_dim: {}r   )r   intr   floorr)   sum)r2   Z	input_dimr6   Zoutput_dim_allowedZnum_fcr$   r
   r
   r   r#   w   s    zFC.calculate_fc_output_dimsc                 C   s   |dkr\| j r4|j| j | |fd| ji| jS |j| j | |fd| ji| jS n<|dkr|j| j | |fd| ji| jS td	|dS )z
        Args:
            net: the caffe2 net to insert operator
            params: weight and bias for FC
            outputs: the output blobs
            version: support fp32 and fp16 for now.
        r   r   r   zunsupported FC type version {}N)
r%   ZFCTransposedr0   field_blobsr   r3   r   Z
FbFCPacked	Exceptionr   )r.   netparamsoutputsversionr
   r
   r   _insert_fc_ops   s8    zFC._insert_fc_opsc                    s<  | j durN fdd|D }t||D ]"\}} j|g|gfi | j  q&|}| jdu sft| jdkr~|  || j | n|dtt|d  }|tt|d d }t|t|ksJ g }	t	t| jD ]<}
 
d|
}|  ||
 ||
 g|g|}|	| qԈ |	| j | j d d g  dS )	z
        Args:
            params : the weight and bias,
                passed by either add_ops or add_train_ops function
            version : fp16 or fp32, might support in8 in the future.
        Nc                    s   g | ]}  d t| qS )z
clipped_%s)NextScopedBlobstr).0pr>   r
   r   
<listcomp>   s   
zFC._add_ops.<locals>.<listcomp>r   r   zoutput_sub_{}r   Z_concat_dims)r    zipZClipr$   r   rB   r-   r<   r9   rangerC   r   r)   ZConcat)r.   r>   r?   rA   Zclipped_paramsrF   cpr&   r'   Zoutput_blob_veciZoutput_blobZ
insert_retr
   rG   r   _add_ops   s4    

zFC._add_opsc                 C   s0   t  tjddi}|d }| || j| dS )zFBoth the predict net and the eval net will call this function
        r	   r   N)r   getr   __name__rM   param_blobs)r.   r>   version_infoZpredictor_fc_fp_versionr
   r
   r   add_ops   s
    
z
FC.add_opsc                 C   s   |  || jd d S )Nr   )rM   Ztrain_param_blobs)r.   r>   r
   r
   r   add_train_ops   s    zFC.add_train_opsc                 C   s*   | j d u st| j dkr | jgS | jS d S Nr   )r$   r   r   r&   r.   r
   r
   r   get_fp16_compatible_parameters   s    z!FC.get_fp16_compatible_parametersc                 C   s4   | j d u st| j dkr$| j| jgS | j| j S d S rT   )r$   r   r   r   r&   r'   rU   r
   r
   r   rP      s    zFC.param_blobs)NNNNr   NNNNr   Fr   )rO   
__module____qualname__r   staticmethodr#   rB   rM   rR   rS   rV   propertyrP   __classcell__r
   r
   r7   r   r      s        ]
!#	r   )Zcaffe2.python.helpers.arg_scoper   Zcaffe2.pythonr   Zcaffe2.python.layers.layersr   Z-caffe2.python.layers.sampling_trainable_mixinr   r!   numpyr   r   r   r
   r
   r
   r   <module>   s   