o
    ߥi                     @   s   d dl mZmZmZ 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 d dlmZ d dlmZmZ d dlmZ G dd dZG d	d
 d
ZejejejdG dd deZdS )    )AnyDictUnionNk_means)Models)MODELS
TorchModel)Tasksc                   @   sV   e Zd Z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 Z
dd ZdS )SpectralClusterzA spectral clustering mehtod using unnormalized Laplacian of affinity matrix.
    This implementation is adapted from https://github.com/speechbrain/speechbrain.
          I+?c                 C   s   || _ || _|| _d S N)min_num_spksmax_num_spkspval)selfr   r   r    r   ^/home/ubuntu/.local/lib/python3.10/site-packages/modelscope/models/audio/sv/cluster_backend.py__init__   s   
zSpectralCluster.__init__Nc           
      C   sL   |  |}| |}d||j  }| |}| ||\}}| ||}	|	S )Ng      ?)get_sim_mat	p_pruningTget_laplacianget_spec_embscluster_embs)
r   X
oracle_numsim_matprunned_sim_matsym_prund_sim_mat	laplacianemb
num_of_spklabelsr   r   r   __call__   s   


zSpectralCluster.__call__c                 C   s   t jj||}|S r   )sklearnmetricspairwisecosine_similarity)r   r   Mr   r   r   r   0   s   zSpectralCluster.get_sim_matc                 C   s   |j d | j dk rd|j d  }n| j}td| |j d  }t|j d D ]}t||d d f }|d| }d|||f< q'|S )Nr      g      @r   )shaper   intrangenpargsort)r   Ar   n_elemsilow_indexesr   r   r   r   5   s   zSpectralCluster.p_pruningc                 C   s>   d|t |jd < t jt |dd}t |}|| }|S )Nr   r   axis)r0   diag_indicesr-   sumabsdiag)r   r+   DLr   r   r   r   F   s
   
zSpectralCluster.get_laplacianc                 C   sh   t j|\}}|d ur|}n| || jd | jd  }t|| j }|d d d |f }||fS Nr   )scipylinalgeighgetEigenGapsr   r   r0   argmax)r   r=   k_oraclelambdaseig_vecsr$   lambda_gap_listr#   r   r   r   r   M   s   zSpectralCluster.get_spec_embsc                 C   s   t ||\}}}|S r   r   )r   r#   k_r%   r   r   r   r   Z   s   zSpectralCluster.cluster_embsc                 C   sD   g }t t|d D ]}t||d  t||  }|| q
|S r>   )r/   lenfloatappend)r   eig_valseig_vals_gap_listr4   gapr   r   r   rB   ^   s
   zSpectralCluster.getEigenGaps)r   r   r   r   )__name__
__module____qualname____doc__r   r&   r   r   r   r   r   rB   r   r   r   r   r      s    


r   c                   @   s,   e Zd ZdZ					dddZdd	 Zd
S )UmapHdbscanz
    Reference:
    - Siqi Zheng, Hongbin Suo. Reformulating Speaker Diarization as Community Detection With
      Emphasis On Topological Structure. ICASSP2022
       <   
   cosinec                 C   s"   || _ || _|| _|| _|| _d S r   )n_neighborsn_componentsmin_samplesmin_cluster_sizemetric)r   rY   rZ   r[   r\   r]   r   r   r   r   m   s
   
zUmapHdbscan.__init__c                 C   sL   t j| jdt| j|jd d | jd|}tj	| j
| jdd|}|S )Ng        r      )rY   min_distrZ   r]   T)r[   r\   allow_single_cluster)umapUMAPrY   minrZ   r-   r]   fit_transformhdbscanHDBSCANr[   r\   fit_predict)r   r   umap_Xr%   r   r   r   r&   y   s    zUmapHdbscan.__call__N)rU   rV   rW   rW   rX   )rP   rQ   rR   rS   r   r&   r   r   r   r   rT   f   s    
rT   )module_namec                       s>   e Zd ZdZdeeef f fddZdd Zdd Z	  Z
S )	ClusterBackendzPerfom clustering for input embeddings and output the labels.
    Args:
        model_dir: A model dir.
        model_config: The model config.
    model_configc                    s<   t  j||g|R i | || _|| _t | _t | _d S r   )superr   rk   other_configr   spectral_clusterrT   umap_hdbscan_cluster)r   	model_dirrk   argskwargs	__class__r   r   r      s
   zClusterBackend.__init__c                 K   s   d|v r|d nd }t |jdksJ d|jd dk r&tj|jd ddS |jd dk s1|d ur8| ||}n| |}|d u rPd	| jv rP| ||| jd	 }|S )
Nr   r^   z5modelscope error: the shape of input should be [N, C]r   rU   r.   )dtypei   	merge_thr)rJ   r-   r0   zerosrn   ro   rk   merge_by_cos)r   r   paramsrH   r%   r   r   r   forward   s$   
zClusterBackend.forwardc                 C   s$  |dkr|dks
J 	 |  d }|dkr	 |S g }t|D ]}|||k d}|| qt|dks7J tj|dd}|tjj|ddd }t	||j
}	t|	d}	tt|	|	j}
|	|
 |k ri	 |S tt|D ]!}|| |
d kr|
d ||< qo|| |
d kr||  d8  < qoq)Nr   r   Tr6   )r7   keepdims)maxr/   meanrL   rJ   r0   stackr@   normmatmulr   triuunravel_indexrC   r-   )r   r%   embscos_thrspk_num
spk_centerr4   spk_embnorm_spk_centeraffinityspksr   r   r   rx      s8   zClusterBackend.merge_by_cos)rP   rQ   rR   rS   r   strr   r   rz   rx   __classcell__r   r   rs   r   rj      s
    	rj   )typingr   r   r   re   numpyr0   r?   r'   ra   sklearn.cluster._kmeansr   modelscope.metainfor   modelscope.modelsr   r	   modelscope.utils.constantr
   r   rT   register_modulespeaker_diarizationcluster_backendrj   r   r   r   r   <module>   s    U!