o
    pi .                     @   s   d dl Zd dlZddlmZmZ ddlmZ z
d dl	Z	d dl
Z	W n	 ey)   Y nw G dd dZG dd	 d	ZG d
d dZG dd dZ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ZdS )     N   )BatchedDistanceCosineSimilarity   )common_functionsc                   @   s>   e Zd ZdddZdddZ	dddZd	d
 ZdddZdS )MatchFinderNc                 C   s   || _ || _d S Ndistance	threshold)selfr
   r    r   [/home/ubuntu/.local/lib/python3.10/site-packages/pytorch_metric_learning/utils/inference.py__init__   s   
zMatchFinder.__init__c                 O   s$   |d u r|}|||g|R i |S r   r   )r   
input_func	query_embref_embargskwargsr   r   r   operate_on_emb   s   zMatchFinder.operate_on_embFc                 C   sR   t   |d ur|n| j}| | j||||W  d    S 1 s"w   Y  d S r   )torchno_gradr   r   _get_matching_pairs)r   r   r   r   return_tuplesr   r   r   get_matching_pairs   s   
$zMatchFinder.get_matching_pairsc                 C   sJ   |  ||}| j jr||kn||k}|  }|r#ttt| S |S r   )r
   is_invertedcpunumpylistzipnpwhere)r   r   r   r   r   matmatchesr   r   r   r   "   s   zMatchFinder._get_matching_pairsc                 C   s   |d ur|n| j }t 4 | j||}| jjr||kn||k}| dkr4|  W  d    S |	 
 W  d    S 1 sDw   Y  d S Nr   )r   r   r   r
   pairwise_distancer   nelementdetachitemr   r   )r   xyr   distoutputr   r   r   is_match+   s   


$zMatchFinder.is_matchr   NNF)__name__
__module____qualname__r   r   r   r   r-   r   r   r   r   r      s    


		r   c                   @   s   e Zd Z						dddZdd Zddd	Zdd
dZdd Zdd Zdd Z	dddZ
d ddZdd Zdd Zdd ZdS )!InferenceModelNTc                 C   sz   || _ |d u rtj n|| _|d u rtt ddn|| _|d u r'tdddn|| _	|| _
|d u r5t n|| _|| _d S )Ng?r	   F)reset_beforereset_after)trunkr   nnIdentityembedderr   r   match_finderFaissKNNknn_funcnormalize_embeddingsc_fuse_cuda_if_availabledata_devicedtype)r   r5   r8   r9   r<   r;   r?   r@   r   r   r   r   8   s   

zInferenceModel.__init__c              	   C   s   |  |}g }t|tjtfr)tdt||D ]}|| ||||   qn+t|tj	j
jrJtj	j
j||d}|D ]\}}|| | q<n
tdt| dt|S )Nr   
batch_sizez	Indexing z is not supported.)process_if_list
isinstancer   Tensorr   rangelenappendget_embeddingsutilsdataDataset
DataLoader	TypeErrortypecat)r   inputsrB   
embeddingsi
dataloaderinp_r   r   r   %get_embeddings_from_tensor_or_datasetT   s   

z4InferenceModel.get_embeddings_from_tensor_or_dataset@   c                 C      |  | jj|| d S r   )call_knnr;   trainr   rQ   rB   r   r   r   	train_knnb      zInferenceModel.train_knnc                 C   rY   r   )rZ   r;   addr\   r   r   r   
add_to_knne   r^   zInferenceModel.add_to_knnc                 C   s   |  ||}|| d S r   )rW   )r   funcrQ   rB   rR   r   r   r   rZ   h   s   zInferenceModel.call_knnc                 C   s   |  |}| ||S r   )rI   r;   )r   querykr   r   r   r   get_nearest_neighborsl   s   
z$InferenceModel.get_nearest_neighborsc                 C   s   |  |}t|tjrtj|| j| jd}| j	  | j
	  t  | 
| |}W d    n1 s6w   Y  | jrHtjjj|ddd}|S )Ndevicer@   r   r   )pdim)rC   rD   r   rE   r=   	to_devicer?   r@   r5   evalr8   r   r<   r6   
functional	normalize)r   r)   x_embr   r   r   rI   p   s   



zInferenceModel.get_embeddingsFc                 C   s2   |  |}|}|d ur|  |}| j||||S r   )rI   r9   r   )r   rb   refr   r   r   r   r   r   r   get_matches}   s   

zInferenceModel.get_matchesc                 C   s$   |  |}|  |}| j|||S r   )rI   r9   r-   )r   r)   r*   r   r   r   r   r-      s   

zInferenceModel.is_matchc                 C      | j | d S r   )r;   saver   filenamer   r   r   save_knn_func      zInferenceModel.save_knn_funcc                 C   rp   r   )r;   loadrr   r   r   r   load_knn_func   ru   zInferenceModel.load_knn_funcc                 C   s*   t |trtdd |D rt|S |S )Nc                 s   s    | ]	}t |tjV  qd S r   )rD   r   rE   ).0x_r   r   r   	<genexpr>   s    z1InferenceModel.process_if_list.<locals>.<genexpr>)rD   r   allr   stack)r   r)   r   r   r   rC      s   
zInferenceModel.process_if_list)NNTNNN)rX   r.   r   )r/   r0   r1   r   rW   r]   r`   rZ   rd   rI   ro   r-   rt   rw   rC   r   r   r   r   r2   7   s&    





r2   c                   @   sN   e Zd Z	dddZ		dddZdd	 Zd
d Zdd Zdd Zdd Z	dS )r:   TNc                 C   sd   |    || _|| _|d u rtjn|| _|d ur-t|ttfs#t	dt
|dk r-td|| _d S )Nzgpus must be a listr   z$gpus must have length greater than 0)resetr3   r4   faissIndexFlatL2index_init_fnrD   r   tuplerN   rG   
ValueErrorgpus)r   r3   r4   r   r   r   r   r   r      s   
zFaissKNN.__init__Fc           
      C   s   |r|d }|j }|j}|jd }tjd|  tjd|  | jr*| || _| jd u r3t	dt
| j||||| j\}}	tj||d}tj|	|d}	| jrU|   t||	|S )Nr   zrunning k-nn with k=%dembedding dimensionality is %dzAself.index is None. It needs to be initialized before being used.rf   )rf   is_cudashaper=   LOGGERinfor3   r   indexr   try_gpur   ri   r4   r}   return_results)
r   rb   rc   	referenceref_includes_queryrf   r   d	distancesindicesr   r   r   __call__   s4   

zFaissKNN.__call__c                 C   s*   |  |jd | _| t|  d S r$   )r   r   r   r_   r=   numpy_to_torchr   r   rR   r   r   r   r[      s   zFaissKNN.trainc                 C   s   | j t|  d S r   )r   r_   r=   r   r   r   r   r   r   r_      s   zFaissKNN.addc                 C   s   t | j| d S r   )r~   write_indexr   rr   r   r   r   rq      s   zFaissKNN.savec                 C   s   t || _d S r   )r~   
read_indexr   rr   r   r   r   rv      ru   zFaissKNN.loadc                 C   s
   d | _ d S r   r   )r   r   r   r   r}         
zFaissKNN.reset)TTNN)NF)
r/   r0   r1   r   r   r[   r_   rq   rv   r}   r   r   r   r   r:      s    

"r:   c                   @   s   e Zd Zdd Zdd ZdS )FaissKMeansc                 K   s
   || _ d S r   )r   )r   r   r   r   r   r      r   zFaissKMeans.__init__c           	      C   s   |j }t|tj}|j\}}tjd|  tjd|  t	j
||fi | j}|| |j|d\}}tjdd |D t|dS )Nz$running k-means clustering with k=%dr   r   c                 S   s   g | ]}t |d  qS )r   )int)rx   nr   r   r   
<listcomp>   s    z(FaissKMeans.__call__.<locals>.<listcomp>)r@   rf   )rf   r=   to_numpyastyper    float32r   r   r   r~   Kmeansr   r[   r   searchr   tensorr   )	r   r)   nmb_clustersrf   n_datar   kmeansrV   idxsr   r   r   r      s   

zFaissKMeans.__call__Nr/   r0   r1   r   r   r   r   r   r   r      s    r   c                 C   s.   |d ur|  |   | |  |S r   )r_   floatr   r   )r   rb   r   rc   r   r   r   add_to_index_and_search   s   r   c                 C   s4   dt t| v r
| S |d u rt| S tj| |dS )NGpu)r   )strrO   r~   index_cpu_to_all_gpusindex_cpu_to_gpus_list)r   r   r   r   r   convert_to_gpu_index   s
   
r   c                 C   s   dt t| vr
| S t| S )Nr   )r   rO   r~   index_gpu_to_cpur   r   r   r   convert_to_cpu_index   s   
r   c              
   C   s   d }t  dk}|s|d uo|}|r'ttjjdk rdnd}	||	kr't| |}zt||||W S  tt	fyT   |rGt
jd| d|	 d t| }
t|
||| Y S w )Nr   g      #@i   i   z&Using CPU for k-nn search because k = z > z(, which is the maximum allowable on GPU.)r~   get_num_gpusr   r   versioncudar   r   AttributeErrorRuntimeErrorr=   r   warningr   )r   rb   r   rc   r   r   	gpu_indexgpus_are_availablegpu_conditionmax_k_for_gpu	cpu_indexr   r   r   r     s"   
r   c                 C   sX   | j }t| tj} t| jd |}|	|  |j
sJ tjt|| |dS )Nr   r   )rf   r=   r   r   r    r   r~   	PCAMatrixr   r[   
is_trainedri   r   
from_numpyapply_py)r)   output_dimensionalityrf   r"   r   r   r   run_pca  s   

r   c                 C   s   | |   | jd dS )Nr   )viewr   )r)   matches_self_idxr   r   r   mask_reshape_knn_idx   s   r   c                 C   sh   |r0t jt||jd}||dk}t j|dd}t |s&d|| df< t||}t| |} | |fS )Nr   r   )rh   Tr   )r   arangerG   rf   	unsqueezeanyr{   r   )DIr   self_idxr   row_has_matchr   r   r   r   $  s   


r   c                    s    fdd}|S )Nc                    s2   t j| dd\}}| ||< |||< d S )Nr   largestrh   )r   topk)r"   ser   r   r   get_largestr   rc   r   r   fn4  s   zget_topk.<locals>.fnr   )r   r   rc   r   r   r   r   r   get_topk3  s   r   c                   @   s    e Zd ZdddZdddZdS )		CustomKNNNc                 C   s    |rt ||d| _d S || _d S )NrA   )r   r
   )r   r
   rB   r   r   r   r   =  s   
zCustomKNN.__init__Fc           
      C   s   |r|d }| j j}t| j tr9|j}tjt|||d}tjt|||tjd}t	||||| j _
|  || n|  ||}	tj|	||dd\}}t|||S )Nr   r   re   r   )r
   r   rD   r   rf   r   zerosrG   longr   iter_fnr   r   )
r   rb   rc   r   r   r   rf   r   r   r"   r   r   r   r   C  s   zCustomKNN.__call__r   )Fr   r   r   r   r   r   <  s    
r   )r   r    r   r   r   r    r   r=   r~   faiss.contrib.torch_utilsModuleNotFoundErrorr   r2   r:   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   s.    )aD		