U
    ÿî¹`‡  ã                   @   sl   d Z ddlZddlmZ ddlm  mZ ddlmZ	 ddl
ZddlmZ ddlmZ G dd„ dejƒZdS )zA
Loss functions

Author: Shengyu Huang
Last modified: 30.11.2020
é    N)Úsquare_distance)Úprecision_recall_fscore_supportc                       sB   e Zd ZdZd‡ fdd„	Zdd„ Zd	d
„ Zdd„ Zdd„ Z‡  Z	S )Ú
MetricLossz;
    We evaluate both contrastive loss and circle loss
    é   çš™™™™™¹?çffffffö?c                    sT   t t| ƒ ¡  || _|| _|| _|j| _|j| _|j| _|j	| _	|j
| _
|j| _d S )N)Úsuperr   Ú__init__Ú	log_scaleÚpos_optimalÚneg_optimalÚ
pos_marginÚ
neg_marginÚ
max_pointsÚsafe_radiusÚmatchability_radiusÚ
pos_radius)ÚselfÚconfigsr
   r   r   ©Ú	__class__© ú&/workspace/OverlapPredator/lib/loss.pyr	      s    zMetricLoss.__init__c                 C   sx  || j k }|| jk}| d¡dk| d¡dk  ¡ }| d¡dk| d¡dk  ¡ }|d|  ¡   }|| j }t t |¡|¡ ¡ }|d|  ¡   }| j	| }t t |¡|¡ ¡ }tj
| j|| j  | dd}	tj
| j|| j  | dd}
tj
| j| j|  | dd}tj
| j| j|  | dd}t |	| ¡| j }t |
| ¡| j }||  ¡ ||  ¡  d }|S )zL
        Modified from: https://github.com/XuyangBai/D3Feat.pytorch
        éÿÿÿÿr   éþÿÿÿg     jø@©Údimé   )r   r   ÚsumÚdetachÚfloatr   ÚtorchÚmaxÚ
zeros_liker   Ú	logsumexpr
   r   r   ÚFÚsoftplusÚmean)r   Úcoords_distÚ
feats_distÚpos_maskZneg_maskÚrow_selÚcol_selÚ
pos_weightÚ
neg_weightZlse_pos_rowZlse_pos_colZlse_neg_rowZlse_neg_colZloss_rowZloss_colÚcircle_lossr   r   r   Úget_circle_loss!   s$    

  

zMetricLoss.get_circle_lossc           
      C   s|   || j k }| d¡dk ¡  ¡ d }t |d¡\}}tj|d|dd…df d| d¡dk }|| j k  ¡  ¡ }|| }	|	S )zM
        Get feature match recall, divided by number of true inliers
        r   r   gê-™—q=N)r   Úindex)r   r   r    r!   ÚminÚgather)
r   r(   r)   r*   Zn_gt_posÚ_Zsel_idxZsel_distZ
n_pred_posÚrecallr   r   r   Ú
get_recallB   s    
*zMetricLoss.get_recallc                 C   sœ   t jdd}|||ƒ}t |¡}| ¡ | d¡ }d| }|||dk< |||dk < t || ¡}| ¡  ¡  	¡  
¡ }	t| ¡  
¡ |	dd\}
}}}||
|fS )NÚnone)Ú	reductionr   é   g      à?Úbinary)Úaverage)ÚnnÚBCELossr!   Ú	ones_liker   Úsizer'   r   ÚcpuÚroundÚnumpyr   )r   Ú
predictionÚgtÚlossÚ
class_lossÚweightsZ
w_negativeZ
w_positiveZw_class_lossZpredicted_labelsÚcls_precisionÚ
cls_recallr4   r   r   r   Úget_weighted_bce_lossN   s    

z MetricLoss.get_weighted_bce_lossc
           %   	   C   sJ  t  || dd¡¡|  dd¡}tƒ }
tt|dd…df  ¡  ¡ ƒƒ}tt|dd…df  ¡  ¡ ƒƒ}t  | 	d¡¡}d||< t  | 	d¡¡}d||< t  
||f¡ t  d¡¡}|  ||¡\}}}||
d< ||
d< ||
d< || ||  }}|| ||  }}t  || dd¡¡}| d¡\}}t j|||  d	dd
}| d¡\}}t j|||  d	dd
}t  
|| jk  ¡ || jk  ¡ f¡}|	d| 	d¡… | }|	| 	d¡d… | }t  
||f¡}	|  |	|¡\}}}||
d< ||
d< ||
d< t j||dd…df  ||dd…df   dd}|| jd k }|| }| 	d¡| jkrbtj | 	d¡¡d| j… } ||  }|dd…df }|dd…df }|| ||  }}|| ||  }}t  t|ddd…dd…f |ddd…dd…f ƒ d¡¡}!t  t|ddd…dd…f |ddd…dd…f dd¡ d¡}"|  |!|"¡}#|  |!|"¡}$|$|
d< |#|
d< |
S )a:  
        Circle loss for metric learning, here we feed the positive pairs only
        Input:
            src_pcd:        [N, 3]  
            tgt_pcd:        [M, 3]
            rot:            [3, 3]
            trans:          [3, 1]
            src_feats:      [N, C]
            tgt_feats:      [M, C]
        r   r9   Ng      ð?ÚcudaÚoverlap_lossÚoverlap_recallÚoverlap_precisionr   )Úpr   Úsaliency_lossÚsaliency_recallÚsaliency_precisionr   gü©ñÒMbP?T)Ú
normalisedr/   r5   )r!   ÚmatmulÚ	transposeÚdictÚlistÚsetÚintÚtolistÚzerosr?   ÚcatÚtoÚdevicerJ   r"   Únormr   r    r   r   ÚnpÚrandomÚpermutationÚsqrtr   Úsqueezer6   r0   )%r   Úsrc_pcdÚtgt_pcdÚ	src_featsÚ	tgt_featsÚcorrespondenceÚrotÚtransÚscores_overlapÚscores_saliencyÚstatsZsrc_idxZtgt_idxZsrc_gtZtgt_gtÚ	gt_labelsrF   rH   rI   Zsrc_feats_selZsrc_pcd_selZtgt_feats_selZtgt_pcd_selÚscoresr4   ÚidxZ
distance_1Z
distance_2Zsrc_saliency_scoresZtgt_saliency_scoresZc_distZc_selectÚchoicer(   r)   r5   r/   r   r   r   Úforwardc   sZ       "2:>zMetricLoss.forward)r   r   r   )
Ú__name__Ú
__module__Ú__qualname__Ú__doc__r	   r0   r6   rJ   rs   Ú__classcell__r   r   r   r   r      s   !r   )rw   r!   Útorch.nnr<   Ztorch.nn.functionalÚ
functionalr%   Úmatplotlib.pyplotÚpyplotÚpltrB   r`   Ú	lib.utilsr   Zsklearn.metricsr   ÚModuler   r   r   r   r   Ú<module>   s   