o
    ॵi1V                     @   s  d dl Z d dlZd dlZd dlZd dlmZmZmZ d dlZd dl	m
Z d dlZd dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZmZ d d	lmZ d d
lmZ d dlmZ d dlmZm Z  d dl!m"Z" d dl#m$Z$m%Z% d dl&m'Z' d dl(m)Z) d dl*m+Z+ ddl,m-Z-m.Z.m/Z/ ddl0m1Z1 ddl2m3Z3m4Z4m5Z5 ddl6m7Z7m8Z8m9Z9 e) Z:ej;ej<dG dd deZ=dS )    N)CallableDictOptional)SummaryWriter)nn)optim)
DataLoader)Trainers)Model
TorchModel)kws_nearfield_dataset)BaseTrainer)TRAINERS)load_checkpointsave_checkpoint)Config)DEFAULT_MODEL_REVISION	ModelFile)create_device)
get_logger)set_random_seed   )executor_cvexecutor_testexecutor_train)compute_det)query_token_setread_lexicon
read_token)average_modelconvert_to_kaldicount_parameters)module_namec                       s   e Zd Zddefdededee dee dee f
 fddZd	d
 Zdede	ee
f fddZdejfddZdddZdddZ  ZS )KWSNearfieldTrainerNmodelwork_dircfg_filearg_parse_fnmodel_revisionc                    s  t |tr| ||| _|du rtj| jtj}n|dus"J dtj	|| _t
 || t|}d| _|jdd| _t|dd |   || _| jdkritj| jsat| j td	|  tj| jd
}tj|s~J | dt|| _tj| jd}	tj|	sJ |	 dt|	| _tj| jd}
tj|
sJ |
 d|
|jd< || _| jdkrtj| jst| j tj| jd}t |d}t!"|# }|$| W d   dS 1 sw   Y  dS dS )a  
        Args:
            model (str): model id in modelscope
            work_dir (str): main directory for training and evaluating
            cfg_file (str): config file for training and evaluating
            kwargs:
                seed (int): random seed
        Nz?Config file should not be None if model is not from pretrained!pytorchdist_backendncclseedi  r   zCurrent working dir is ztrain/tokens.txtz is missingztrain/lexicon.txtz&train/feature_transform.txt.80dim-l2r2	cmvn_fileconfig.yamlw)%
isinstancestrget_or_download_model_dir	model_dirospathjoinr   CONFIGURATIONdirnamesuper__init__r   	from_filelaunchertraingetr*   r   	init_distr%   rankexistsmakedirsloggerinfor   token_tabler   lexicon_tabler$   configsopenyamldumpto_dictwrite)selfr$   r%   r&   r'   r(   kwargsrG   
token_filelexicon_filefeature_transform_filesaved_config_pathfoutdata	__class__ c/home/ubuntu/.local/lib/python3.10/site-packages/modelscope/trainers/audio/kws_nearfield_trainer.pyr:   )   sZ   







"zKWSNearfieldTrainer.__init__c               	   O   s  | dd}|durtj|r|| _n	tj| jd| _| dd| _|d s,J d|d s4J d	|d
 s<J d|d | _|d | _	|d
 | _
| ddoY| jdkrXdnd| _| jd }t|}d|d< d|d< d|d< tj| jd}tj| jd}t| j| j
|| j| j| j|d| _t| j	| j
|| j| j| j|d| _t| jd| dd| jjjj| jjj ddd| _t| jd| dd| jjjj| jjj ddd| _| | j| _t| j}| jdkrt !d"| | jdur5tj| jr5t#| j| j t$%dd| j}	i }
tj|	r4t&|	d}t'j(|t'j)d}
W d   n	1 s/w   Y  nt !d i }
|
 d d!d" | _*| j*| jd# d$< |
 d%| jd# d& d% }|| jd# d& d%< | d'd(}| j+d"krud)| j, }t-|| _.| j+d"krt/j01 sJ | j2| j.| _t/j3j45| j| _n| j2| j.| _| jdkrtj| jst6| j tj| jd*}t&|d+}t'7| j8 }|9| W d   n	1 sw   Y  t :d, d}| jdkrtj6| jdd- t;tj| j| j}| jd#  d.d/}| jd# d& }t<j=| j> |d% |d0 d1}t<j?j@|d2d3d4d5d6d7}d}| j*dkrM| jdkrMtj| jd8}tA| j|ddddd t :d, i }|d9 |d9< | d:d"|d:< ||d.< | j+|d;< | j|d<< | j,|d=< | jd# d> }tBjBC }tD| j*|D ]}| jE| ||d < |jFd d% }t :d?"|| tG| j|| j| j.|| tH| j| j| j.|\}}t :d@"||| | jdkrtj| jdA"|}tA| j|ddddd t$%dd|}	tI|||dB}t&|	d+}t'7|}|9| W d   n	1 s
w   Y  |JdC|| |JdD|| |}|K| q|dur5| jdkr5|L  tBjBC | }t :dE"|M dF  dS )Gau  
        Args:
            kwargs:
                train_data (int): wave list with kaldi style for training
                cv_data (int): wave list with kaldi style for cross validation
                trans_data (str): transcription list with kaldi style, merge train and cv
                checkpoint (str): basemodel checkpoint, if None, default to use base.pt in model path
                tensorboard_dir (str): path to save tensorboard results,
                                       create 'tensorboard_dir' in work_dir by default
                need_dump (bool): wether to dump data with mapping tokens or not
        
checkpointNztrain/base.pttensorboard_dirtensorboard
train_dataz'please config train data in dict kwargscv_dataz$please config cv data in dict kwargs
trans_dataz/please config transcription data in dict kwargs	need_dumpFr   Tpreprocessorspeed_perturbspec_augshufflezdump_train.txtzdump_cv.txt
pin_memoryprefetch   )
batch_sizerd   num_workersprefetch_factorzthe number of model params: {}z.pt$z.yamlr)Loaderz'Training with random initialized paramsepochr   r=   start_epochlr	optimizerdevicegpucuda:r.   r/   zStart training...)exist_oklog_interval
   weight_decay)ro   rw   ming      ?   gư>g{Gz?)modefactorpatiencemin_lr	thresholdzinit.pt	grad_clip
grad_accum
world_sizer@   
local_rank
max_epochszEpoch {} TRAIN info lr {}z0Epoch {} EVAL info cv_loss {:.6f}, cv_acc {:.2f}z{}.pt)rl   ro   cv_losszepoch/cv_losszepoch/lrTotal time spent: {:.2f} hours      @)Nr>   r4   r5   rA   rY   r6   r3   rZ   r\   r]   r^   r@   r_   rG   copydeepcopyr%   r   rE   rF   train_dataset
cv_datasetr   r=   
dataloaderworkers_per_gputrain_dataloader
evaluationcv_dataloaderbuild_modelr$   r!   rC   warningformatr   resubrH   rI   load
FullLoaderrn   r   r   r   train_devicetorchcudais_availabletor   parallelDistributedDataParallelrB   rJ   rK   rL   rD   r   r   Adam
parameterslr_schedulerReduceLROnPlateaur   datetimenowrange	set_epochparam_groupsr   r   dict
add_scalarstepclosetotal_seconds) rM   argsrN   train_checkpoint
train_confcv_confdump_train_filedump_cv_file
num_params	info_pathinfosfinlr_last_epochdevice_namerR   rS   rT   writerru   
optim_confrp   r   final_epochsave_model_pathtraining_config	max_epoch	totaltimerl   ro   r   cv_acc	info_dictrW   rW   rX   r=   k   sX  










	




	









zKWSNearfieldTrainer.traincheckpoint_pathreturnc               
      s  d| _ |durtj|rtd|  |}nU| j du ra|dd}tj| jd| d| _ td| j   t	| j | jd|d	}t
d>i || _ | | j}t|| j | j}td
|  | j }td| j   |dddur|dddurtd |d }	|d }
ntd | j}	| j}
td|	  td|
  t| jd }d|d d< d|d d< d|d< d|d< d|d< |dddur|d |d d< t|	|
|| j| jddd}t|d|ddd| jjjj| jjjd d!d"}|d#ddus	J d$|d# }| d%dd&}i }dh d'hd'di}|D ]O}t|| j| j\}}i ||< ||| d(< dd)d* |D || d+< fd,d-|D   fd.d-|D  t||D ]\}}||ddu rr|||< qaq&d}| D ]\}}|| d/| d07 }q|td1|  |d2d3dkotj ! }|d4d5}| j"d6kr|rd7| j# }t$|| _%| | j| _&t'|| j& | j&(| j%| _&i }|d8ddur|d8 |d8< ntj)|}tj| jd9| |d8< |d8 | _*tj| j*st+| j* t,d: t-j-. }t/| j&|| j%| |}t-j-. | }t,d;0|1 d<  t	||	|
|d=}t2d>i |}t3| dS )?ab  
        Args:
            checkpoint_path (str): evaluating with ckpt or default average ckpt
            kwargs:
                test_dir (str): local path for saving test results
                test_data (str): wave list with kaldi style
                trans_data (str): transcription list with kaldi style
                average_num (int): the NO. to do model averaging(checkpoint_path==None)
                batch_size (int): batch size during evaluating
                keywords (str): keyword string, split with ','
                gpu (int): evaluating with cpu/gpu: -1 for cpu; >=0 for gpu
        Nz evaluating with specific model: average_numrv   avg_z.ptz!default average model not exist: T)	dst_modelsrc_pathval_bestavg_numz(average model convert to kaldi network: zevaluating with average model: 	test_datar^   z/evaluating with specific data and transcriptionz5evaluating with cross validation data during trainingztest data: ztrans data: r`   i  filter_conf
max_lengthr   
min_lengthFra   rb   rc   rg   
batch_conf rd   re   rf   )rg   rd   persistent_workersrh   ri   keywordszat least one keyword is needed ,z<blk>token_idc                 s   s    | ]	}d t | V  qdS )z%s N)r1   .0irW   rW   rX   	<genexpr>  s    z/KWSNearfieldTrainer.evaluate.<locals>.<genexpr>	token_strc                       g | ]}  |qS rW   addr   )keywords_strsetrW   rX   
<listcomp>      z0KWSNearfieldTrainer.evaluate.<locals>.<listcomp>c                    r   rW   r   r   )keywords_idxsetrW   rX   r     r   (z) zToken set is: rr   rm   rq   cpur   rs   test_dirtest_zStart evaluating...r   r   )r   r   r^   
score_filerW   )4avg_checkpointr4   r5   rA   rC   r   r>   r6   r%   r   r   r   rG   r    r]   r^   r   r   r   rE   rF   r   r   r   r   stripreplacesplitr   zipitemsr   r   r   r   r   r   test_device
test_modelr   r   basenamer   rB   rD   r   r   r   r   r   r   print) rM   r   r   rN   eval_checkpointr   
avg_kwargs	model_cvt	kaldi_cvtr   r^   	test_conftest_datasettest_dataloaderkeywords_strkeywords_listkeywords_tokenkeywords_tokenmapkeywordstrsindexestxtidxtoken_printuse_cudar   testing_config	base_namer   r   
det_kwargsdet_resultsrW   )r   r   rX   evaluate-  s  

















zKWSNearfieldTrainer.evaluatec                 C   s@   t j| j|dd}t|trt|dr|jS t|tjr|S dS )z Instantiate a pytorch model and return.

        By default, we will create a model using config from configuration file. You can
        override this method in a subclass.

        T)cfg_dicttrainingr$   N)	r
   from_pretrainedr3   r0   r   hasattrr$   r   Module)rM   rG   r$   rW   rW   rX   r     s   zKWSNearfieldTrainer.build_modelr   c              	   C   sF  t dd d u rdt jd< t dd d u rdt jd< t dd d u r'dt jd< t dd d u r4dt jd< t dd d u rAd	t jd< tt jd | _tt jd | _tt jd | _t jd | _t jd | _|d
kr| jd
krt	
d| j tj| jdd n|d
krtj| jdd t  t	
d| j| j| j| j| j d S )NRANK0
LOCAL_RANK
WORLD_SIZE1MASTER_ADDR	localhostMASTER_PORT29500r   z'init dist on multiple gpus, this gpu {}zenv://)backendinit_methodz-RANK {}/{}/{}, Master addr:{}, Master port:{})r4   getenvenvironintr@   r   r   master_addrmaster_portrC   rD   r   distinit_process_groupr*   barrierrM   train_nodesrW   rW   rX   r?     sB   






zKWSNearfieldTrainer.init_distc                 C   sT   |dkr| j dkrtd| j t  d S d S |dkr(t  t  d S d S )Nr   z*destory dist on multiple gpus, this gpu {})r   rC   rD   r   r   r  destroy_process_groupr  r  rW   rW   rX   uninit_dist  s   
zKWSNearfieldTrainer.uninit_dist)r   )__name__
__module____qualname__r   r1   r   r   r:   r=   r   floatr  r   r
  r   r?   r!  __classcell__rW   rW   rU   rX   r#   %   s0    B C

 
!r#   )>r   r   r4   r   typingr   r   r   r   torch.distributeddistributedr  rI   tensorboardXr   r   r   torch.utils.datar   modelscope.metainfor	   modelscope.modelsr
   r   Mmodelscope.msdatasets.dataset_cls.custom_datasets.audio.kws_nearfield_datasetr   modelscope.trainers.baser   modelscope.trainers.builderr   modelscope.utils.checkpointr   r   modelscope.utils.configr   modelscope.utils.constantr   r   modelscope.utils.devicer   modelscope.utils.loggerr   modelscope.utils.torch_utilsr   kws_utils.batch_utilsr   r   r   kws_utils.det_utilsr   kws_utils.file_utilsr   r   r   kws_utils.model_utilsr   r    r!   rC   register_module"speech_kws_fsmn_char_ctc_nearfieldr#   rW   rW   rW   rX   <module>   s@   