From 298ddd13fbf833cd77a3a26659e9187e751d140a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B8=B8=E9=9B=81?= Date: Fri, 15 Dec 2023 23:46:41 +0800 Subject: [PATCH] funasr2 --- egs/aishell/bat/README.md | 16 - .../bat/conf/decode_bat_conformer.yaml | 1 - egs/aishell/bat/conf/train_conformer_bat.yaml | 108 - egs/aishell/bat/local/aishell_data_prep.sh | 66 - egs/aishell/bat/path.sh | 5 - egs/aishell/bat/run.sh | 210 - egs/aishell/bat/utils | 1 - egs/aishell/branchformer/README.md | 15 - .../conf/decode_asr_transformer.yaml | 6 - .../conf/train_asr_branchformer.yaml | 104 - .../branchformer/local/aishell_data_prep.sh | 66 - .../branchformer/local/download_and_untar.sh | 105 - egs/aishell/branchformer/path.sh | 5 - egs/aishell/branchformer/run.sh | 225 - egs/aishell/branchformer/utils | 1 - egs/aishell/conformer/README.md | 17 - .../conf/decode_asr_transformer.yaml | 6 - .../conformer/conf/train_asr_conformer.yaml | 98 - .../conformer/local/aishell_data_prep.sh | 66 - .../conformer/local/download_and_untar.sh | 105 - egs/aishell/conformer/path.sh | 5 - egs/aishell/conformer/run.sh | 225 - egs/aishell/conformer/utils | 1 - .../decode_asr_transformer_noctc_1best.yaml | 6 - ...araformer_transformer_12e_6d_3072_768.yaml | 121 - .../local/aishell_data_prep.sh | 66 - .../local/download_and_untar.sh | 105 - .../data2vec_paraformer_finetune/path.sh | 5 - .../data2vec_paraformer_finetune/run.sh | 231 - .../data2vec_paraformer_finetune/utils | 1 - .../conf/decode_asr_transformer.yaml | 6 - ...train_asr_transformer_12e_6d_3072_768.yaml | 112 - .../local/aishell_data_prep.sh | 66 - .../local/download_and_untar.sh | 105 - .../data2vec_transformer_finetune/path.sh | 5 - .../data2vec_transformer_finetune/run.sh | 230 - .../data2vec_transformer_finetune/utils | 1 - egs/aishell/e_branchformer/README.md | 15 - .../conf/decode_asr_transformer.yaml | 6 - .../conf/train_asr_e_branchformer.yaml | 101 - .../e_branchformer/local/aishell_data_prep.sh | 66 - .../local/download_and_untar.sh | 105 - egs/aishell/e_branchformer/path.sh | 5 - egs/aishell/e_branchformer/run.sh | 225 - egs/aishell/e_branchformer/utils | 1 - egs/aishell/paraformer/README.md | 24 - .../conf/decode_asr_transformer.yaml | 6 - .../decode_asr_transformer_noctc_1best.yaml | 6 - ..._paraformer_conformer_12e_6d_2048_256.yaml | 109 - .../paraformer/local/aishell_data_prep.sh | 66 - .../paraformer/local/download_and_untar.sh | 105 - egs/aishell/paraformer/path.sh | 5 - egs/aishell/paraformer/run.sh | 227 - egs/aishell/paraformer/utils | 1 - egs/aishell/paraformerbert/README.md | 18 - .../conf/decode_asr_transformer.yaml | 6 - .../decode_asr_transformer_noctc_1best.yaml | 6 - ...aformerbert_conformer_12e_6d_2048_256.yaml | 112 - .../paraformerbert/local/aishell_data_prep.sh | 66 - .../local/download_and_untar.sh | 105 - .../paraformerbert/local/extract_embeds.sh | 62 - egs/aishell/paraformerbert/path.sh | 5 - egs/aishell/paraformerbert/run.sh | 237 - egs/aishell/paraformerbert/utils | 1 - egs/aishell/rnnt/README.md | 18 - .../conf/decode_rnnt_conformer_streaming.yaml | 8 - .../decode_rnnt_conformer_streaming_simu.yaml | 5 - .../conf/train_conformer_rnnt_unified.yaml | 99 - egs/aishell/rnnt/local/aishell_data_prep.sh | 66 - egs/aishell/rnnt/path.sh | 5 - egs/aishell/rnnt/run.sh | 210 - egs/aishell/rnnt/utils | 1 - .../conf/decode_asr_transformer.yaml | 6 - .../conf/train_asr_transformer.yaml | 88 - .../transformer/local/aishell_data_prep.sh | 66 - .../transformer/local/download_and_untar.sh | 105 - egs/aishell/transformer/path.sh | 7 - egs/aishell/transformer/run.sh | 225 - egs/aishell/transformer/utils/apply_cmvn.py | 79 - egs/aishell/transformer/utils/apply_cmvn.sh | 36 - .../transformer/utils/apply_lfr_and_cmvn.py | 143 - .../transformer/utils/apply_lfr_and_cmvn.sh | 38 - .../transformer/utils/cmvn_converter.py | 51 - .../transformer/utils/combine_cmvn_file.py | 72 - egs/aishell/transformer/utils/compute_cmvn.py | 126 - egs/aishell/transformer/utils/compute_cmvn.sh | 39 - .../transformer/utils/compute_fbank.py | 171 - .../transformer/utils/compute_fbank.sh | 54 - .../transformer/utils/download_model.py | 20 - egs/aishell/transformer/utils/error_rate_zh | 370 - .../transformer/utils/extract_embeds.py | 47 - egs/aishell/transformer/utils/filter_scp.pl | 87 - egs/aishell/transformer/utils/fix_data.sh | 35 - .../transformer/utils/fix_data_feat.sh | 52 - egs/aishell/transformer/utils/gen_ark_list.sh | 22 - .../utils/gen_modelscope_configuration.py | 118 - .../transformer/utils/parse_options.sh | 97 - .../transformer/utils/prepare_checkpoint.py | 19 - egs/aishell/transformer/utils/print_args.py | 45 - .../transformer/utils/proc_conf_oss.py | 35 - egs/aishell/transformer/utils/proce_text.py | 31 - egs/aishell/transformer/utils/process_opus.py | 86 - egs/aishell/transformer/utils/run.pl | 356 - egs/aishell/transformer/utils/shuffle_list.pl | 44 - egs/aishell/transformer/utils/split_data.py | 60 - egs/aishell/transformer/utils/split_scp.pl | 246 - .../utils/subset_data_dir_tr_cv.sh | 30 - egs/aishell/transformer/utils/text2token.py | 135 - .../transformer/utils/text_tokenize.py | 106 - .../transformer/utils/text_tokenize.sh | 35 - egs/aishell/transformer/utils/textnorm_zh.py | 834 - .../conf/decode_asr_transformer.yaml | 6 - .../conformer/conf/train_asr_conformer.yaml | 99 - egs/aishell2/conformer/local/prepare_data.sh | 53 - egs/aishell2/conformer/path.sh | 6 - egs/aishell2/conformer/run.sh | 230 - egs/aishell2/conformer/utils | 1 - .../conf/train_pretrain_transformer.yaml | 87 - .../data2vec_pretrain/local/prepare_data.sh | 53 - egs/aishell2/data2vec_pretrain/path.sh | 6 - egs/aishell2/data2vec_pretrain/run.sh | 127 - egs/aishell2/data2vec_pretrain/utils | 1 - .../conf/decode_asr_transformer.yaml | 6 - .../decode_asr_transformer_noctc_1best.yaml | 6 - ...er_conformer_20e_1280_320_6d_1280_320.yaml | 109 - egs/aishell2/paraformer/local/prepare_data.sh | 53 - egs/aishell2/paraformer/path.sh | 6 - egs/aishell2/paraformer/run.sh | 229 - egs/aishell2/paraformer/utils | 1 - .../conf/decode_asr_transformer.yaml | 6 - ...aformerbert_conformer_20e_6d_1280_320.yaml | 112 - .../paraformerbert/local/extract_embeds.sh | 62 - .../paraformerbert/local/prepare_data.sh | 53 - egs/aishell2/paraformerbert/path.sh | 6 - egs/aishell2/paraformerbert/run.sh | 239 - egs/aishell2/paraformerbert/utils | 1 - .../conf/decode_asr_transformer.yaml | 6 - .../conf/train_asr_transformer.yaml | 93 - .../transformer/local/prepare_data.sh | 53 - egs/aishell2/transformer/path.sh | 6 - egs/aishell2/transformer/run.sh | 229 - egs/aishell2/transformer/utils | 1 - .../conf/train_lm_transformer.yaml | 31 - egs/aishell2/transformerLM/path.sh | 6 - egs/aishell2/transformerLM/run.sh | 228 - egs/aishell2/transformerLM/utils | 1 - egs/alimeeting/diarization/sond/README.md | 25 - egs/alimeeting/diarization/sond/config.yaml | 2740 - .../diarization/sond/config_fbank.yaml | 2728 - .../diarization/sond/infer_alimeeting_test.py | 24 - .../sond/local/convert_label_to_rttm.py | 132 - egs/alimeeting/diarization/sond/path.sh | 5 - egs/alimeeting/diarization/sond/run.sh | 48 - egs/alimeeting/diarization/sond/unit_test.py | 97 - .../diarization/sond/unit_test_modelscope.py | 92 - egs/alimeeting/modular_sa_asr/README.md | 103 - .../modular_sa_asr/conf/mfcc_hires.conf | 11 - .../tdnn_stats_sad_1a/cmvn_opts | 1 - .../tdnn_stats_sad_1a/final.raw | Bin 5102860 -> 0 bytes .../frame_subsampling_factor | 1 - .../segmentation_1a/tdnn_stats_sad_1a/lda.mat | Bin 160815 -> 0 bytes .../tdnn_stats_sad_1a/lda_stats | Bin 82936 -> 0 bytes .../tdnn_stats_sad_1a/post_output.vec | 1 - .../segmentation_1a/tdnn_stats_sad_1a/srand | 1 - .../modular_sa_asr/figure/20230809161919.jpg | Bin 148964 -> 0 bytes .../modular_sa_asr/local/compute_cpcer.py | 103 - .../local/convert_label_to_rttm.py | 132 - .../local/extract_profile_from_segments.py | 104 - .../modular_sa_asr/local/finetune.py | 34 - .../modular_sa_asr/local/format_wav_scp.py | 1 - .../modular_sa_asr/local/format_wav_scp.sh | 1 - .../modular_sa_asr/local/infer_sond.py | 27 - .../local/make_textgrid_rttm.py | 61 - .../local/meeting_speaker_number_process.py | 86 - .../modular_sa_asr/local/merge_spk_text.py | 52 - .../modular_sa_asr/local/remove_overlap.py | 140 - .../modular_sa_asr/local/resegment_data.py | 78 - .../modular_sa_asr/local/rttm2segments.py | 29 - .../modular_sa_asr/local/run_gss.py | 139 - .../modular_sa_asr/local/run_wpe.py | 153 - .../modular_sa_asr/local/segment_to_lab.py | 58 - .../segmentation/detect_speech_activity.sh | 225 - .../modular_sa_asr/local/test_gss.py | 141 - .../local/textgrid_processor.py | 316 - egs/alimeeting/modular_sa_asr/path.sh | 14 - egs/alimeeting/modular_sa_asr/run_asr.sh | 152 - egs/alimeeting/modular_sa_asr/run_diar.sh | 233 - egs/alimeeting/modular_sa_asr/run_enh.sh | 114 - egs/alimeeting/sa_asr/README.md | 86 - .../sa_asr/conf/decode_asr_rnn.yaml | 6 - .../sa_asr/conf/train_asr_conformer.yaml | 102 - .../sa_asr/conf/train_sa_asr_conformer.yaml | 132 - .../sa_asr/local/alimeeting_data_prep.sh | 161 - .../local/alimeeting_data_prep_test_2023.sh | 129 - .../local/alimeeting_process_overlap_force.py | 238 - .../local/alimeeting_process_textgrid.py | 161 - egs/alimeeting/sa_asr/local/apply_map.pl | 97 - egs/alimeeting/sa_asr/local/combine_data.sh | 146 - egs/alimeeting/sa_asr/local/compute_cmvn.py | 134 - egs/alimeeting/sa_asr/local/compute_cmvn.sh | 39 - egs/alimeeting/sa_asr/local/compute_cpcer.py | 91 - egs/alimeeting/sa_asr/local/convert_model.py | 29 - egs/alimeeting/sa_asr/local/copy_data_dir.sh | 145 - .../sa_asr/local/data/get_reco2dur.sh | 143 - .../local/data/get_segments_for_data.sh | 29 - .../sa_asr/local/data/get_utt2dur.sh | 135 - .../sa_asr/local/data/split_data.sh | 160 - .../sa_asr/local/download_and_untar.sh | 105 - ...wnload_pretrained_model_from_modelscope.py | 7 - .../sa_asr/local/download_xvector_model.py | 6 - .../sa_asr/local/filter_utt2spk_all_fifo.py | 22 - egs/alimeeting/sa_asr/local/fix_data_dir.sh | 215 - egs/alimeeting/sa_asr/local/format_wav_scp.py | 241 - egs/alimeeting/sa_asr/local/format_wav_scp.sh | 142 - .../sa_asr/local/gen_cluster_profile_infer.py | 167 - .../sa_asr/local/gen_oracle_embedding.py | 70 - .../local/gen_oracle_profile_nopadding.py | 59 - .../local/gen_oracle_profile_padding.py | 68 - .../sa_asr/local/perturb_data_dir_speed.sh | 116 - .../local/process_sot_fifo_textchar2spk.py | 88 - .../sa_asr/local/process_text_id.py | 24 - .../sa_asr/local/process_text_spk_merge.py | 55 - .../process_textgrid_to_single_speaker_wav.py | 132 - .../sa_asr/local/spk2utt_to_utt2spk.pl | 27 - egs/alimeeting/sa_asr/local/text_format.pl | 14 - egs/alimeeting/sa_asr/local/text_normalize.pl | 38 - .../sa_asr/local/utt2spk_to_spk2utt.pl | 38 - .../sa_asr/local/validate_data_dir.sh | 404 - egs/alimeeting/sa_asr/local/validate_text.pl | 136 - egs/alimeeting/sa_asr/path.sh | 6 - egs/alimeeting/sa_asr/run.sh | 435 - egs/alimeeting/sa_asr/utils | 1 - ...rain_diar_eend_ola_callhome_chunk2000.yaml | 45 - .../conf/train_diar_eend_ola_simu_2spkr.yaml | 52 - .../train_diar_eend_ola_simu_allspkr.yaml | 52 - ..._diar_eend_ola_simu_allspkr_chunk2000.yaml | 44 - .../TOLD/eend_ola/local/dump_feature.py | 144 - .../TOLD/eend_ola/local/gen_feats_scp.py | 25 - egs/callhome/TOLD/eend_ola/local/infer.py | 138 - .../TOLD/eend_ola/local/make_callhome.sh | 73 - .../TOLD/eend_ola/local/make_mixture.py | 120 - .../TOLD/eend_ola/local/make_musan.py | 123 - .../TOLD/eend_ola/local/make_musan.sh | 37 - egs/callhome/TOLD/eend_ola/local/make_sre.pl | 63 - egs/callhome/TOLD/eend_ola/local/make_sre.sh | 48 - .../TOLD/eend_ola/local/make_swbd2_phase1.pl | 106 - .../TOLD/eend_ola/local/make_swbd2_phase2.pl | 107 - .../TOLD/eend_ola/local/make_swbd2_phase3.pl | 102 - .../eend_ola/local/make_swbd_cellular1.pl | 83 - .../eend_ola/local/make_swbd_cellular2.pl | 83 - .../TOLD/eend_ola/local/model_averaging.py | 28 - .../TOLD/eend_ola/local/parse_options.sh | 97 - .../TOLD/eend_ola/local/random_mixture.py | 145 - .../eend_ola/local/run_prepare_shared_eda.sh | 235 - egs/callhome/TOLD/eend_ola/local/split.py | 117 - egs/callhome/TOLD/eend_ola/path.sh | 13 - egs/callhome/TOLD/eend_ola/run.sh | 324 - ..._None_FFN_FSMN_L6N512_bce_dia_loss_01.yaml | 134 - ...FN_FSMN_L6N512_bce_dia_loss_01_phase2.yaml | 134 - ...FN_FSMN_L6N512_bce_dia_loss_01_phase3.yaml | 134 - .../TOLD/soap/conf/basic_inference.yaml | 2 - egs/callhome/TOLD/soap/conf/fbank.conf | 4 - .../soap/data/token_list/bce_label_n16.txt | 65536 ---------------- .../data/token_list/powerset_label_n16k1.txt | 17 - .../data/token_list/powerset_label_n16k2.txt | 137 - .../data/token_list/powerset_label_n16k3.txt | 697 - .../data/token_list/powerset_label_n16k4.txt | 2517 - egs/callhome/TOLD/soap/finetune.sh | 567 - egs/callhome/TOLD/soap/path.sh | 5 - egs/callhome/TOLD/soap/run.sh | 991 - .../TOLD/soap/script/calc_num_frames.py | 21 - .../script/calc_real_meeting_frame_labels.py | 101 - .../TOLD/soap/script/concat_spk_segs.py | 57 - .../TOLD/soap/script/convert_label_to_rttm.py | 201 - .../script/convert_pse_label_to_bin_ark.py | 35 - .../soap/script/convert_rttm_to_seg_file.py | 63 - .../TOLD/soap/script/dump_meeting_chunks.py | 176 - .../TOLD/soap/script/dump_pipe_wav.py | 48 - .../TOLD/soap/script/dump_speaker_profiles.py | 117 - .../TOLD/soap/script/easy_average_models.py | 54 - .../script/extract_nonoverlap_segments.py | 116 - .../soap/script/remove_silence_from_wav.py | 63 - .../TOLD/soap/script/simu_whole_recordings.py | 216 - egs/callhome/TOLD/soap/unit_test/sond.yaml | 2739 - .../TOLD/soap/unit_test/sond_fbank.yaml | 2739 - egs/callhome/TOLD/soap/unit_test/unit_test.py | 97 - egs/cnceleb/resnet34/README.md | 18 - egs/cnceleb/resnet34/configuration.json | 20 - .../local/convert_tf_ckpt_to_torch.py | 93 - egs/cnceleb/resnet34/local/make_cnceleb1.sh | 62 - egs/cnceleb/resnet34/local/make_cnceleb2.sh | 32 - egs/cnceleb/resnet34/path.sh | 5 - egs/cnceleb/resnet34/run.sh | 138 - egs/cnceleb/resnet34/sid/calc_trial_scores.py | 160 - egs/cnceleb/resnet34/sid/compute_eer.py | 54 - egs/cnceleb/resnet34/sid/compute_min_dcf.py | 151 - .../resnet34/sid/speaker_verification.py | 167 - egs/cnceleb/resnet34/sv.yaml | 3515 - egs/cnceleb/resnet34/utils | 1 - egs/librispeech/branchformer/README.md | 16 - .../decode_asr_transformer_beam10_ctc0.3.yaml | 6 - .../conf/train_asr_branchformer.yaml | 104 - .../branchformer/local/data_prep.sh | 58 - .../branchformer/local/download_and_untar.sh | 97 - .../branchformer/local/spm_encode.py | 98 - .../branchformer/local/spm_train.py | 12 - egs/librispeech/branchformer/path.sh | 5 - egs/librispeech/branchformer/run.sh | 223 - egs/librispeech/branchformer/utils | 1 - .../decode_asr_transformer_ctc0.3_beam5.yaml | 6 - .../decode_asr_transformer_ctc0.3_beam60.yaml | 6 - .../conformer/conf/train_asr_conformer.yaml | 92 - egs/librispeech/conformer/local/data_prep.sh | 58 - .../conformer/local/download_and_untar.sh | 97 - egs/librispeech/conformer/local/spm_encode.py | 98 - egs/librispeech/conformer/local/spm_train.py | 12 - egs/librispeech/conformer/path.sh | 5 - egs/librispeech/conformer/run.sh | 223 - egs/librispeech/conformer/utils | 1 - egs/librispeech/e_branchformer/README.md | 16 - .../decode_asr_transformer_beam10_ctc0.3.yaml | 6 - .../conf/train_asr_e_branchformer.yaml | 105 - .../e_branchformer/local/data_prep.sh | 58 - .../local/download_and_untar.sh | 97 - .../e_branchformer/local/spm_encode.py | 98 - .../e_branchformer/local/spm_train.py | 12 - egs/librispeech/e_branchformer/path.sh | 5 - egs/librispeech/e_branchformer/run.sh | 223 - egs/librispeech/e_branchformer/utils | 1 - egs/librispeech/rnnt/README.md | 18 - .../conf/decode_rnnt_conformer_streaming.yaml | 8 - .../conf/train_conformer_rnnt_unified.yaml | 98 - egs/librispeech/rnnt/local/data_prep.sh | 58 - .../rnnt/local/download_and_untar.sh | 97 - egs/librispeech/rnnt/local/spm_encode.py | 98 - egs/librispeech/rnnt/local/spm_train.py | 12 - egs/librispeech/rnnt/path.sh | 5 - egs/librispeech/rnnt/run.sh | 222 - egs/librispeech/rnnt/utils | 1 - .../decode_asr_transformer_ctc0.3_beam1.yaml | 6 - .../decode_asr_transformer_ctc0.3_beam20.yaml | 6 - .../decode_asr_transformer_ctc0.3_beam5.yaml | 6 - .../conformer/conf/train_asr_conformer.yaml | 92 - .../conformer/local/data_prep.sh | 58 - .../conformer/local/download_and_untar.sh | 97 - .../conformer/local/spm_encode.py | 98 - .../conformer/local/spm_train.py | 12 - egs/librispeech_100h/conformer/path.sh | 5 - egs/librispeech_100h/conformer/run.sh | 219 - egs/librispeech_100h/conformer/utils | 1 - egs/librispeech_100h/rnnt/README.md | 16 - .../rnnt/conf/decode_rnnt_conformer.yaml | 3 - .../rnnt/conf/train_conformer_rnnt.yaml | 96 - egs/librispeech_100h/rnnt/local/data_prep.sh | 58 - .../rnnt/local/download_and_untar.sh | 97 - egs/librispeech_100h/rnnt/local/spm_encode.py | 98 - egs/librispeech_100h/rnnt/local/spm_train.py | 12 - egs/librispeech_100h/rnnt/path.sh | 5 - egs/librispeech_100h/rnnt/run.sh | 213 - egs/librispeech_100h/rnnt/utils | 1 - .../conf/decode_asr_transformer_5beam.yaml | 6 - .../conformer/conf/train_asr_conformer.yaml | 104 - egs/wenetspeech/conformer/local/data.sh | 102 - .../conformer/local/extract_meta.py | 114 - .../conformer/local/process_opus.py | 88 - .../conformer/local/text_normalize.pl | 24 - .../conformer/local/wenetspeech_data_prep.sh | 135 - egs/wenetspeech/conformer/path.sh | 5 - egs/wenetspeech/conformer/run.sh | 222 - egs/wenetspeech/conformer/utils | 1 - egs_modelscope/asr/TEMPLATE/README.md | 359 - egs_modelscope/asr/TEMPLATE/README_zh.md | 356 - egs_modelscope/asr/TEMPLATE/finetune.py | 36 - egs_modelscope/asr/TEMPLATE/infer.py | 29 - egs_modelscope/asr/TEMPLATE/infer.sh | 103 - egs_modelscope/asr/TEMPLATE/utils | 1 - .../README.md | 1 - .../demo.py | 14 - .../finetune.py | 35 - .../infer.py | 1 - .../infer.sh | 1 - .../README.md | 1 - .../demo.py | 13 - .../finetune.py | 36 - .../infer.py | 1 - .../infer.sh | 1 - .../README.md | 53 - .../finetune.py | 37 - .../infer.py | 87 - .../infer_after_finetune.py | 52 - .../README.md | 53 - .../finetune.py | 37 - .../infer.py | 87 - .../infer_after_finetune.py | 52 - .../README.md | 1 - .../RESULTS.md | 40 - .../demo.py | 11 - .../finetune.py | 35 - .../infer.py | 27 - .../infer.sh | 70 - .../utils | 1 - .../README.md | 1 - .../README_zh.md | 1 - .../demo.py | 16 - .../finetune.py | 37 - .../infer.py | 1 - .../infer.sh | 105 - .../infer_aishell1_subtest_demo.py | 40 - .../utils | 1 - .../README.md | 1 - .../README_zh.md | 1 - .../RESULTS.md | 38 - .../demo.py | 13 - .../demo_online.py | 41 - .../demo_online_v2.py | 44 - .../finetune.py | 38 - .../infer.py | 33 - .../infer.sh | 104 - .../utils | 1 - .../README.md | 1 - .../README_zh.md | 1 - .../RESULTS.md | 112 - .../demo.py | 11 - .../finetune.py | 48 - .../infer.py | 1 - .../infer.sh | 103 - .../utils | 1 - .../README.md | 30 - .../infer.py | 89 - .../README.md | 1 - .../README_zh.md | 1 - .../demo.py | 11 - .../finetune.py | 36 - .../infer.py | 1 - .../infer.sh | 103 - .../utils | 1 - .../README.md | 1 - .../README_zh.md | 1 - .../demo.py | 15 - .../finetune.py | 35 - .../infer.py | 1 - .../infer.sh | 103 - .../README.md | 1 - .../README_zh.md | 1 - .../demo.py | 13 - .../finetune.py | 36 - .../infer.py | 1 - .../infer.sh | 103 - .../README.md | 1 - .../README_zh.md | 1 - .../demo.py | 13 - .../demo_online.py | 41 - .../finetune.py | 38 - .../infer.py | 33 - .../infer.sh | 104 - .../utils | 1 - .../README.md | 1 - .../README_zh.md | 1 - .../finetune.py | 36 - .../infer.py | 25 - .../infer.sh | 70 - .../infer_after_finetune.py | 48 - .../utils | 1 - .../README.md | 30 - .../infer.py | 14 - .../infer.py | 13 - .../finetune.py | 35 - .../infer.py | 13 - .../README.md | 30 - .../finetune.py | 35 - .../infer.py | 14 - .../finetune.py | 35 - .../infer.py | 13 - .../finetune.py | 35 - .../infer.py | 13 - .../finetune.py | 35 - .../infer.py | 13 - .../README.md | 53 - .../finetune.py | 36 - .../infer.py | 89 - .../infer_after_finetune.py | 54 - .../finetune.py | 35 - .../infer.py | 13 - .../finetune.py | 35 - .../infer.py | 13 - .../finetune.py | 35 - .../infer.py | 13 - .../finetune.py | 35 - .../infer.py | 13 - .../finetune.py | 35 - .../infer.py | 13 - .../README.md | 53 - .../demo.py | 12 - .../finetune.py | 36 - .../infer.py | 1 - .../infer.sh | 105 - .../utils | 1 - .../finetune.py | 35 - .../infer.py | 13 - .../finetune.py | 35 - .../infer.py | 13 - .../finetune.py | 35 - .../infer.py | 13 - .../README.md | 1 - .../demo.py | 10 - .../finetune.py | 36 - .../infer.py | 13 - .../infer.sh | 103 - .../utils | 1 - .../finetune.py | 35 - .../infer.py | 13 - .../finetune.py | 35 - .../infer.py | 13 - .../README.md | 30 - .../finetune.py | 35 - .../infer.py | 14 - .../README.md | 53 - .../demo.py | 12 - .../finetune.py | 36 - .../infer.py | 1 - .../infer.sh | 105 - .../utils | 1 - .../README.md | 30 - .../finetune.py | 35 - .../infer.py | 14 - egs_modelscope/asr_vad_punc/TEMPLATE | 1 - .../README.md | 1 - .../README_zh.md | 1 - .../demo.py | 18 - .../finetune.py | 35 - .../infer.py | 27 - .../infer.sh | 103 - .../utils | 1 - .../README.md | 1 - .../README_zh.md | 1 - .../demo.py | 17 - .../finetune.py | 35 - .../infer.py | 27 - .../infer.sh | 103 - .../utils | 1 - egs_modelscope/asr_vad_spk/TEMPLATE | 1 - .../demo.py | 17 - .../finetune.py | 35 - .../infer.py | 27 - .../demo.py | 17 - egs_modelscope/punctuation/TEMPLATE/README.md | 112 - .../punctuation/TEMPLATE/README_zh.md | 112 - egs_modelscope/punctuation/TEMPLATE/infer.py | 23 - egs_modelscope/punctuation/TEMPLATE/infer.sh | 66 - egs_modelscope/punctuation/TEMPLATE/utils | 1 - .../README.md | 1 - .../README_zh.md | 1 - .../data/punc_example.txt | 3 - .../demo.py | 22 - .../infer.py | 25 - .../infer.sh | 68 - .../utils | 1 - .../README_zh.md | 1 - .../demo.py | 26 - .../README.md | 1 - .../README_zh.md | 1 - .../data/punc_example.txt | 3 - .../demo.py | 22 - .../infer.py | 1 - .../infer.sh | 1 - .../utils | 1 - .../speaker_diarization/TEMPLATE/README.md | 81 - .../infer.py | 10 - .../infer.py | 33 - .../infer.py | 34 - .../speaker_verification/TEMPLATE/README.md | 121 - .../speaker_verification/TEMPLATE/infer.py | 15 - .../demo.py | 39 - .../infer_sv.py | 21 - .../demo.py | 39 - .../eval_eer.py | 69 - .../infer_sv.py | 21 - .../demo.py | 15 - egs_modelscope/tp/TEMPLATE/README.md | 104 - egs_modelscope/tp/TEMPLATE/README_zh.md | 102 - egs_modelscope/tp/TEMPLATE/infer.py | 29 - egs_modelscope/tp/TEMPLATE/infer.sh | 75 - egs_modelscope/tp/TEMPLATE/utils | 1 - .../README.md | 1 - .../demo.py | 12 - .../demo_long.py | 52 - .../infer.py | 1 - .../infer.sh | 1 - egs_modelscope/vad/TEMPLATE/README.md | 112 - egs_modelscope/vad/TEMPLATE/README_zh.md | 113 - egs_modelscope/vad/TEMPLATE/infer.py | 25 - egs_modelscope/vad/TEMPLATE/infer.sh | 71 - egs_modelscope/vad/TEMPLATE/utils | 1 - .../README.md | 1 - .../README_zh.md | 1 - .../speech_fsmn_vad_zh-cn-16k-common/demo.py | 15 - .../demo_online.py | 36 - .../speech_fsmn_vad_zh-cn-16k-common/infer.py | 1 - .../speech_fsmn_vad_zh-cn-16k-common/infer.sh | 1 - .../speech_fsmn_vad_zh-cn-8k-common/README.md | 1 - .../README_zh.md | 1 - .../speech_fsmn_vad_zh-cn-8k-common/demo.py | 15 - .../demo_online.py | 36 - .../speech_fsmn_vad_zh-cn-8k-common/infer.py | 1 - .../speech_fsmn_vad_zh-cn-8k-common/infer.sh | 1 - funasr/bin/inference.py | 8 +- funasr/bin/train.py | 16 +- funasr/datasets/collate_fn.py | 196 - funasr/datasets/dataset.py | 444 - .../{ => fun_datasets}/data_sampler.py | 0 .../{ => fun_datasets}/dataloader_fn.py | 4 +- .../{ => fun_datasets}/dataset_jsonl.py | 0 funasr/datasets/iterable_dataset.py | 398 - .../large_datasets/build_dataloader.py | 96 - .../large_datasets/datapipes/batch.py | 213 - .../large_datasets/datapipes/filter.py | 24 - .../datasets/large_datasets/datapipes/map.py | 22 - funasr/datasets/large_datasets/dataset.py | 274 - .../datasets/large_datasets/utils/clipping.py | 40 - .../datasets/large_datasets/utils/filter.py | 26 - .../large_datasets/utils/hotword_utils.py | 33 - .../large_datasets/utils/low_frame_rate.py | 30 - .../datasets/large_datasets/utils/padding.py | 74 - .../datasets/large_datasets/utils/tokenize.py | 95 - funasr/datasets/ms_dataset.py | 33 - funasr/datasets/preprocessor.py | 881 - funasr/datasets/small_datasets/collate_fn.py | 88 - funasr/datasets/small_datasets/dataset.py | 263 - .../small_datasets/length_batch_sampler.py | 145 - .../datasets/small_datasets/preprocessor.py | 867 - .../small_datasets/sequence_iter_factory.py | 189 - .../utils => funasr/download}/__init__.py | 0 .../{utils => download}/download_from_hub.py | 2 +- funasr/{utils => download}/modelscope_file.py | 0 .../{utils => download}/name_maps_from_hub.py | 0 .../runtime_sdk_download_tool.py | 2 +- .../models/decoder/contextual_decoder.py | 6 +- funasr/export/models/decoder/sanm_decoder.py | 6 +- .../models/decoder/transformer_decoder.py | 6 +- .../export/models/decoder/xformer_decoder.py | 2 +- .../models/encoder/conformer_encoder.py | 6 +- funasr/export/models/encoder/sanm_encoder.py | 6 +- funasr/fileio/npy_scp.py | 94 - funasr/fileio/rand_gen_dataset.py | 83 - funasr/fileio/read_text.py | 78 - funasr/fileio/sound_scp.py | 218 - funasr/iterators/abs_iter_factory.py | 9 - funasr/iterators/chunk_iter_factory.py | 213 - funasr/iterators/multiple_iter_factory.py | 35 - funasr/iterators/sequence_iter_factory.py | 141 - funasr/layers/abs_normalize.py | 14 - funasr/layers/inversible_interface.py | 14 - funasr/layers/sinc_conv.py | 269 - funasr/losses/label_smoothing_loss.py | 2 +- funasr/main_funcs/calculate_all_attentions.py | 160 - funasr/{datasets => metrics}/__init__.py | 0 .../e2e_asr_common.py => metrics/common.py} | 0 funasr/{utils => metrics}/compute_eer.py | 0 funasr/{utils => metrics}/compute_min_dcf.py | 0 .../utils => funasr/metrics}/compute_wer.py | 0 funasr/models/base_model.py | 17 - .../large_datasets => models/bat}/__init__.py | 0 .../models/{e2e_asr_bat.py => bat/model.py} | 12 +- .../bici_paraformer}/__init__.py | 0 .../utils => models/branchformer}/__init__.py | 0 .../branchformer_encoder.py | 16 +- .../{modules => models/branchformer}/cgmlp.py | 4 +- .../branchformer}/fastformer.py | 0 funasr/models/branchformer/model.py | 64 + .../campplus}/__init__.py | 0 funasr/{modules => models}/cnn/DTDNN.py | 0 funasr/{modules => models}/cnn/ResNet.py | 2 +- funasr/{modules => models}/cnn/ResNet_aug.py | 2 +- funasr/{modules => models}/cnn/__init__.py | 0 funasr/{modules => models}/cnn/fusion.py | 0 funasr/{modules => models}/cnn/layers.py | 0 .../{fileio => models/conformer}/__init__.py | 0 .../conformer_encoder.py | 36 +- funasr/models/conformer/model.py | 65 + .../ct_transformer}/__init__.py | 0 .../target_delay_transformer.py | 2 +- funasr/{layers => models/ctc}/__init__.py | 0 funasr/models/{ => ctc}/ctc.py | 0 .../data2vec}/__init__.py | 0 funasr/models/{ => data2vec}/data2vec.py | 2 +- .../{encoder => data2vec}/data2vec_encoder.py | 10 +- .../data2vec/data_utils.py | 0 .../data2vec/ema_module.py | 0 .../data2vec/grad_multiply.py | 0 .../data2vec/multihead_attention.py | 2 +- .../data2vec/quant_noise.py | 0 funasr/{modules => models}/data2vec/utils.py | 2 +- .../{modules => models}/data2vec/wav2vec2.py | 4 +- funasr/models/decoder/abs_decoder.py | 19 - funasr/models/e2e_asr.py | 455 - .../models/e2e_asr_contextual_paraformer.py | 374 - funasr/models/e2e_asr_paraformer.py | 2270 - funasr/models/e2e_asr_transducer.py | 993 - .../{decoder => e_branchformer}/__init__.py | 0 .../e_branchformer_encoder.py | 18 +- funasr/models/e_branchformer/model.py | 64 + funasr/models/{encoder => eend}/__init__.py | 0 funasr/models/{ => eend}/e2e_diar_eend_ola.py | 15 +- .../eend}/eend_ola_dataloader.py | 0 .../eend_ola => models/eend}/encoder.py | 0 .../eend}/encoder_decoder_attractor.py | 0 .../utils}/__init__.py | 0 .../eend_ola => models/eend}/utils/feature.py | 0 .../eend}/utils/kaldi_data.py | 0 .../eend_ola => models/eend}/utils/losses.py | 0 .../eend_ola => models/eend}/utils/power.py | 0 .../eend_ola => models/eend}/utils/report.py | 2 +- funasr/models/encoder/abs_encoder.py | 21 - funasr/models/frontend/default.py | 8 +- funasr/models/frontend/s3prl.py | 4 +- .../{frontends_utils => utils}/__init__.py | 0 .../{frontends_utils => utils}/beamformer.py | 0 .../frontend/utils}/complex_utils.py | 0 .../dnn_beamformer.py | 8 +- .../{frontends_utils => utils}/dnn_wpe.py | 4 +- .../feature_transform.py | 2 +- .../{frontends_utils => utils}/frontend.py | 4 +- .../frontend/utils}/log_mel.py | 2 +- .../mask_estimator.py | 6 +- .../{layers => models/frontend/utils}/stft.py | 8 +- .../models/{pooling => fsmn_vad}/__init__.py | 0 .../{encoder => fsmn_vad}/fsmn_encoder.py | 0 .../models/{e2e_vad.py => fsmn_vad/model.py} | 425 +- .../vad_realtime_transformer.py | 2 +- funasr/models/joint_net/__init__.py | 1 - .../__init__.py | 0 .../language_model}/rnn/__init__.py | 0 .../language_model}/rnn/argument.py | 0 .../language_model}/rnn/attentions.py | 4 +- .../language_model}/rnn/decoders.py | 18 +- .../language_model}/rnn/encoders.py | 6 +- .../models/{ => language_model}/seq_rnn_lm.py | 0 .../{ => language_model}/transformer_lm.py | 4 +- funasr/models/{predictor => lora}/__init__.py | 0 funasr/{modules => models}/lora/layers.py | 0 funasr/{modules => models}/lora/utils.py | 0 .../models/{preencoder => mfcca}/__init__.py | 0 funasr/models/{ => mfcca}/e2e_asr_mfcca.py | 8 +- .../{encoder => mfcca}/encoder_layer_mfcca.py | 2 +- .../{encoder => mfcca}/mfcca_encoder.py | 30 +- funasr/models/model_class_factory.py | 230 +- .../__init__.py | 0 funasr/models/{ => mossformer}/e2e_ss.py | 0 .../mossformer}/mossformer.py | 0 .../mossformer_decoder.py | 0 .../mossformer_encoder.py | 6 +- .../neat_contextual_paraformer}/__init__.py | 0 .../normalize}/__init__.py | 0 .../normalize}/global_mvn.py | 6 +- .../normalize}/utterance_mvn.py | 5 +- .../cif.py => paraformer/cif_predictor.py} | 10 +- .../contextual_decoder.py | 12 +- funasr/models/paraformer/model.py | 16 +- funasr/models/paraformer/search.py | 6 +- .../paraformer_online}/__init__.py | 0 funasr/models/postencoder/abs_postencoder.py | 17 - .../hugging_face_transformers_postencoder.py | 113 - funasr/models/preencoder/abs_preencoder.py | 17 - funasr/models/preencoder/linear.py | 36 - funasr/models/preencoder/sinc.py | 279 - .../eend_ola => models/rwkv_bat}/__init__.py | 0 .../rwkv_bat}/cuda_decoder/wkv_cuda.cu | 0 .../rwkv_bat}/cuda_decoder/wkv_op.cpp | 0 .../rwkv_bat}/cuda_encoder/wkv_cuda.cu | 0 .../rwkv_bat}/cuda_encoder/wkv_op.cpp | 0 .../models/rwkv_bat/model.py | 0 funasr/{modules => models/rwkv_bat}/rwkv.py | 6 +- .../rwkv_bat}/rwkv_attention.py | 0 .../{encoder => rwkv_bat}/rwkv_encoder.py | 8 +- .../rwkv_bat}/rwkv_feed_forward.py | 0 .../rwkv_bat}/rwkv_subsampling.py | 6 +- .../utils => models/sa_asr}/__init__.py | 0 .../sa_asr}/beam_search_sa_asr.py | 6 +- funasr/models/{ => sa_asr}/e2e_sa_asr.py | 8 +- .../{modules/lora => models/sanm}/__init__.py | 0 .../models/{decoder => sanm}/sanm_decoder.py | 12 +- .../models/{encoder => sanm}/sanm_encoder.py | 34 +- .../scama}/__init__.py | 0 funasr/models/scama/beam_search.py | 496 + .../scama}/chunk_utilis.py | 4 +- .../streaming_utils => models/scama}/utils.py | 0 funasr/{samplers => models/sond}/__init__.py | 0 funasr/models/{ => sond}/e2e_diar_sond.py | 6 +- .../sond/encoder}/__init__.py | 0 .../encoder}/ci_scorers.py | 0 .../encoder}/conv_encoder.py | 6 +- .../{ => sond}/encoder/ecapa_tdnn_encoder.py | 0 .../encoder}/fsmn_encoder.py | 8 +- .../{ => sond}/encoder/resnet34_encoder.py | 0 .../encoder}/self_attention_encoder.py | 30 +- .../sond}/label_aggregation.py | 2 +- .../sond/pooling}/__init__.py | 0 .../{ => sond}/pooling/pooling_layers.py | 0 .../{ => sond}/pooling/statistic_pooling.py | 2 +- funasr/models/{decoder => sond}/sv_decoder.py | 0 funasr/models/specaug/abs_profileaug.py | 22 - funasr/models/specaug/abs_specaug.py | 16 - .../specaug}/mask_along_axis.py | 0 funasr/models/specaug/profileaug.py | 5 +- funasr/models/specaug/specaug.py | 12 +- .../{layers => models/specaug}/time_warp.py | 2 +- .../{train => models/tp_aligner}/__init__.py | 0 funasr/models/{ => tp_aligner}/e2e_tp.py | 6 +- .../transducer}/__init__.py | 0 .../transducer}/beam_search_transducer.py | 2 +- .../joint_network.py | 2 +- funasr/models/transducer/model.py | 577 + .../{decoder => transducer}/rnn_decoder.py | 6 +- .../{encoder => transducer}/rnn_encoder.py | 6 +- .../{decoder => transducer}/rnnt_decoder.py | 2 +- funasr/models/transformer/__init__.py | 0 .../transformer}/attention.py | 2 +- .../transformer}/embedding.py | 0 .../transformer}/layer_norm.py | 0 funasr/models/transformer/model.py | 484 + .../transformer}/positionwise_feed_forward.py | 2 +- .../transformer}/scorers/__init__.py | 0 .../transformer}/scorers/ctc.py | 6 +- .../transformer}/scorers/ctc_prefix_score.py | 0 .../transformer}/scorers/length_bonus.py | 2 +- .../transformer}/scorers/scorer_interface.py | 0 funasr/models/transformer/search.py | 460 + .../transformer_decoder.py | 26 +- .../transformer_encoder.py | 38 +- funasr/models/transformer/utils/__init__.py | 0 .../transformer/utils}/add_sos_eos.py | 2 +- .../transformer/utils}/dynamic_conv.py | 0 .../transformer/utils}/dynamic_conv2d.py | 0 .../transformer/utils}/lightconv.py | 0 .../transformer/utils}/lightconv2d.py | 0 .../transformer/utils}/mask.py | 0 .../transformer/utils}/multi_layer_conv.py | 0 .../transformer/utils}/nets_utils.py | 0 .../transformer/utils}/repeat.py | 2 +- .../transformer/utils}/subsampling.py | 6 +- .../utils}/subsampling_without_posenc.py | 0 .../transformer/utils}/vgg2l.py | 0 funasr/models/uniasr/__init__.py | 0 funasr/models/{ => uniasr}/e2e_uni_asr.py | 12 +- funasr/models/whisper/__init__.py | 0 .../{whisper_models => whisper}/model.py | 6 +- funasr/models/whisper/utils/__init__.py | 0 .../whisper/utils}/assets/gpt2/merges.txt | 0 .../assets/gpt2/special_tokens_map.json | 0 .../utils}/assets/gpt2/tokenizer_config.json | 0 .../whisper/utils}/assets/gpt2/vocab.json | 0 .../whisper/utils}/assets/mel_filters.npz | Bin .../assets/multilingual/added_tokens.json | 0 .../utils}/assets/multilingual/merges.txt | 0 .../multilingual/special_tokens_map.json | 0 .../assets/multilingual/tokenizer_config.json | 0 .../utils}/assets/multilingual/vocab.json | 0 .../whisper/utils}/audio.py | 2 +- .../whisper/utils}/decoding.py | 6 +- .../whisper/utils}/tokenizer.py | 0 .../whisper/utils}/transcribe.py | 8 +- .../whisper/utils}/utils.py | 0 funasr/models/xvector/__init__.py | 0 funasr/models/{ => xvector}/e2e_sv.py | 8 +- .../modules/beam_search/batch_beam_search.py | 348 - .../batch_beam_search_online_sim.py | 270 - funasr/modules/beam_search/beam_search.py | 1400 - funasr/modules/e2e_asr_common.py | 403 - funasr/samplers/abs_sampler.py | 19 - funasr/samplers/build_batch_sampler.py | 164 - funasr/samplers/folded_batch_sampler.py | 154 - funasr/samplers/length_batch_sampler.py | 145 - funasr/samplers/num_elements_batch_sampler.py | 158 - funasr/samplers/sorted_batch_sampler.py | 93 - funasr/samplers/unsorted_batch_sampler.py | 89 - funasr/tasks/abs_task.py | 1965 - funasr/tasks/asr.py | 1762 - funasr/tasks/data2vec.py | 368 - funasr/tasks/diar.py | 659 - funasr/tasks/lm.py | 201 - funasr/tasks/punctuation.py | 218 - funasr/tasks/sa_asr.py | 615 - funasr/tasks/sv.py | 536 - funasr/tasks/vad.py | 320 - funasr/tasks/whisper.py | 675 - funasr/torch_utils/initialize.py | 100 - funasr/train/abs_model.py | 303 - funasr/train/distributed_utils.py | 380 - funasr/train/reporter.py | 531 - funasr/train/trainer.py | 878 - funasr/train_utils/__init__.py | 0 .../add_gradient_noise.py | 0 .../average_nbest_models.py | 0 .../collect_stats.py | 6 +- .../device_funcs.py | 0 .../forward_adaptor.py | 0 funasr/train_utils/initialize.py | 59 + .../load_pretrained_model.py | 0 .../model_summary.py | 0 .../{main_funcs => train_utils}/pack_funcs.py | 0 .../pytorch_version.py | 0 .../recursive_op.py | 0 .../set_all_random_seed.py | 0 funasr/{utils => train_utils}/trainer.py | 4 +- funasr/utils/asr_env_checking.py | 85 - funasr/utils/build_dataclass.py | 15 - funasr/{train => utils}/class_choices.py | 0 funasr/utils/cluster_backend.py | 191 - funasr/utils/compute_wer.py | 157 - funasr/utils/config_argparse.py | 47 - funasr/{fileio => utils}/datadir_writer.py | 0 funasr/utils/download_and_prepare_model.py | 93 - funasr/utils/get_default_kwargs.py | 57 - funasr/utils/griffin_lim.py | 190 - funasr/utils/hinter.py | 13 - funasr/utils/job_runner.py | 103 - funasr/utils/kwargs2args.py | 19 - funasr/utils/load_fr_py.py | 13 - .../streaming_utils => utils}/load_fr_tf.py | 0 funasr/utils/modelscope_param.py | 35 - funasr/utils/modelscope_utils.py | 40 - funasr/utils/nested_dict_action.py | 106 - funasr/utils/sized_dict.py | 75 - funasr/utils/wav_utils.py | 332 - .../huggingface_models.md | 0 .../modelscope_models.md | 0 .../modelscope_models_zh.md | 0 927 files changed, 2889 insertions(+), 146157 deletions(-) delete mode 100644 egs/aishell/bat/README.md delete mode 100644 egs/aishell/bat/conf/decode_bat_conformer.yaml delete mode 100644 egs/aishell/bat/conf/train_conformer_bat.yaml delete mode 100755 egs/aishell/bat/local/aishell_data_prep.sh delete mode 100644 egs/aishell/bat/path.sh delete mode 100755 egs/aishell/bat/run.sh delete mode 120000 egs/aishell/bat/utils delete mode 100644 egs/aishell/branchformer/README.md delete mode 100644 egs/aishell/branchformer/conf/decode_asr_transformer.yaml delete mode 100644 egs/aishell/branchformer/conf/train_asr_branchformer.yaml delete mode 100755 egs/aishell/branchformer/local/aishell_data_prep.sh delete mode 100755 egs/aishell/branchformer/local/download_and_untar.sh delete mode 100755 egs/aishell/branchformer/path.sh delete mode 100755 egs/aishell/branchformer/run.sh delete mode 120000 egs/aishell/branchformer/utils delete mode 100644 egs/aishell/conformer/README.md delete mode 100644 egs/aishell/conformer/conf/decode_asr_transformer.yaml delete mode 100644 egs/aishell/conformer/conf/train_asr_conformer.yaml delete mode 100755 egs/aishell/conformer/local/aishell_data_prep.sh delete mode 100755 egs/aishell/conformer/local/download_and_untar.sh delete mode 100755 egs/aishell/conformer/path.sh delete mode 100755 egs/aishell/conformer/run.sh delete mode 120000 egs/aishell/conformer/utils delete mode 100644 egs/aishell/data2vec_paraformer_finetune/conf/decode_asr_transformer_noctc_1best.yaml delete mode 100644 egs/aishell/data2vec_paraformer_finetune/conf/train_asr_paraformer_transformer_12e_6d_3072_768.yaml delete mode 100755 egs/aishell/data2vec_paraformer_finetune/local/aishell_data_prep.sh delete mode 100755 egs/aishell/data2vec_paraformer_finetune/local/download_and_untar.sh delete mode 100755 egs/aishell/data2vec_paraformer_finetune/path.sh delete mode 100755 egs/aishell/data2vec_paraformer_finetune/run.sh delete mode 120000 egs/aishell/data2vec_paraformer_finetune/utils delete mode 100644 egs/aishell/data2vec_transformer_finetune/conf/decode_asr_transformer.yaml delete mode 100644 egs/aishell/data2vec_transformer_finetune/conf/train_asr_transformer_12e_6d_3072_768.yaml delete mode 100755 egs/aishell/data2vec_transformer_finetune/local/aishell_data_prep.sh delete mode 100755 egs/aishell/data2vec_transformer_finetune/local/download_and_untar.sh delete mode 100755 egs/aishell/data2vec_transformer_finetune/path.sh delete mode 100755 egs/aishell/data2vec_transformer_finetune/run.sh delete mode 120000 egs/aishell/data2vec_transformer_finetune/utils delete mode 100644 egs/aishell/e_branchformer/README.md delete mode 100644 egs/aishell/e_branchformer/conf/decode_asr_transformer.yaml delete mode 100644 egs/aishell/e_branchformer/conf/train_asr_e_branchformer.yaml delete mode 100755 egs/aishell/e_branchformer/local/aishell_data_prep.sh delete mode 100755 egs/aishell/e_branchformer/local/download_and_untar.sh delete mode 100755 egs/aishell/e_branchformer/path.sh delete mode 100755 egs/aishell/e_branchformer/run.sh delete mode 120000 egs/aishell/e_branchformer/utils delete mode 100644 egs/aishell/paraformer/README.md delete mode 100644 egs/aishell/paraformer/conf/decode_asr_transformer.yaml delete mode 100644 egs/aishell/paraformer/conf/decode_asr_transformer_noctc_1best.yaml delete mode 100644 egs/aishell/paraformer/conf/train_asr_paraformer_conformer_12e_6d_2048_256.yaml delete mode 100755 egs/aishell/paraformer/local/aishell_data_prep.sh delete mode 100755 egs/aishell/paraformer/local/download_and_untar.sh delete mode 100755 egs/aishell/paraformer/path.sh delete mode 100755 egs/aishell/paraformer/run.sh delete mode 120000 egs/aishell/paraformer/utils delete mode 100644 egs/aishell/paraformerbert/README.md delete mode 100644 egs/aishell/paraformerbert/conf/decode_asr_transformer.yaml delete mode 100644 egs/aishell/paraformerbert/conf/decode_asr_transformer_noctc_1best.yaml delete mode 100644 egs/aishell/paraformerbert/conf/train_asr_paraformerbert_conformer_12e_6d_2048_256.yaml delete mode 100755 egs/aishell/paraformerbert/local/aishell_data_prep.sh delete mode 100755 egs/aishell/paraformerbert/local/download_and_untar.sh delete mode 100755 egs/aishell/paraformerbert/local/extract_embeds.sh delete mode 100755 egs/aishell/paraformerbert/path.sh delete mode 100755 egs/aishell/paraformerbert/run.sh delete mode 120000 egs/aishell/paraformerbert/utils delete mode 100644 egs/aishell/rnnt/README.md delete mode 100644 egs/aishell/rnnt/conf/decode_rnnt_conformer_streaming.yaml delete mode 100644 egs/aishell/rnnt/conf/decode_rnnt_conformer_streaming_simu.yaml delete mode 100644 egs/aishell/rnnt/conf/train_conformer_rnnt_unified.yaml delete mode 100755 egs/aishell/rnnt/local/aishell_data_prep.sh delete mode 100644 egs/aishell/rnnt/path.sh delete mode 100755 egs/aishell/rnnt/run.sh delete mode 120000 egs/aishell/rnnt/utils delete mode 100644 egs/aishell/transformer/conf/decode_asr_transformer.yaml delete mode 100644 egs/aishell/transformer/conf/train_asr_transformer.yaml delete mode 100755 egs/aishell/transformer/local/aishell_data_prep.sh delete mode 100755 egs/aishell/transformer/local/download_and_untar.sh delete mode 100755 egs/aishell/transformer/path.sh delete mode 100755 egs/aishell/transformer/run.sh delete mode 100755 egs/aishell/transformer/utils/apply_cmvn.py delete mode 100755 egs/aishell/transformer/utils/apply_cmvn.sh delete mode 100755 egs/aishell/transformer/utils/apply_lfr_and_cmvn.py delete mode 100755 egs/aishell/transformer/utils/apply_lfr_and_cmvn.sh delete mode 100644 egs/aishell/transformer/utils/cmvn_converter.py delete mode 100755 egs/aishell/transformer/utils/combine_cmvn_file.py delete mode 100755 egs/aishell/transformer/utils/compute_cmvn.py delete mode 100755 egs/aishell/transformer/utils/compute_cmvn.sh delete mode 100755 egs/aishell/transformer/utils/compute_fbank.py delete mode 100755 egs/aishell/transformer/utils/compute_fbank.sh delete mode 100755 egs/aishell/transformer/utils/download_model.py delete mode 100755 egs/aishell/transformer/utils/error_rate_zh delete mode 100755 egs/aishell/transformer/utils/extract_embeds.py delete mode 100755 egs/aishell/transformer/utils/filter_scp.pl delete mode 100755 egs/aishell/transformer/utils/fix_data.sh delete mode 100755 egs/aishell/transformer/utils/fix_data_feat.sh delete mode 100755 egs/aishell/transformer/utils/gen_ark_list.sh delete mode 100644 egs/aishell/transformer/utils/gen_modelscope_configuration.py delete mode 100755 egs/aishell/transformer/utils/parse_options.sh delete mode 100644 egs/aishell/transformer/utils/prepare_checkpoint.py delete mode 100755 egs/aishell/transformer/utils/print_args.py delete mode 100755 egs/aishell/transformer/utils/proc_conf_oss.py delete mode 100755 egs/aishell/transformer/utils/proce_text.py delete mode 100755 egs/aishell/transformer/utils/process_opus.py delete mode 100755 egs/aishell/transformer/utils/run.pl delete mode 100755 egs/aishell/transformer/utils/shuffle_list.pl delete mode 100755 egs/aishell/transformer/utils/split_data.py delete mode 100755 egs/aishell/transformer/utils/split_scp.pl delete mode 100755 egs/aishell/transformer/utils/subset_data_dir_tr_cv.sh delete mode 100755 egs/aishell/transformer/utils/text2token.py delete mode 100755 egs/aishell/transformer/utils/text_tokenize.py delete mode 100755 egs/aishell/transformer/utils/text_tokenize.sh delete mode 100755 egs/aishell/transformer/utils/textnorm_zh.py delete mode 100644 egs/aishell2/conformer/conf/decode_asr_transformer.yaml delete mode 100644 egs/aishell2/conformer/conf/train_asr_conformer.yaml delete mode 100755 egs/aishell2/conformer/local/prepare_data.sh delete mode 100755 egs/aishell2/conformer/path.sh delete mode 100755 egs/aishell2/conformer/run.sh delete mode 120000 egs/aishell2/conformer/utils delete mode 100644 egs/aishell2/data2vec_pretrain/conf/train_pretrain_transformer.yaml delete mode 100755 egs/aishell2/data2vec_pretrain/local/prepare_data.sh delete mode 100755 egs/aishell2/data2vec_pretrain/path.sh delete mode 100755 egs/aishell2/data2vec_pretrain/run.sh delete mode 120000 egs/aishell2/data2vec_pretrain/utils delete mode 100644 egs/aishell2/paraformer/conf/decode_asr_transformer.yaml delete mode 100644 egs/aishell2/paraformer/conf/decode_asr_transformer_noctc_1best.yaml delete mode 100644 egs/aishell2/paraformer/conf/train_asr_paraformer_conformer_20e_1280_320_6d_1280_320.yaml delete mode 100755 egs/aishell2/paraformer/local/prepare_data.sh delete mode 100755 egs/aishell2/paraformer/path.sh delete mode 100755 egs/aishell2/paraformer/run.sh delete mode 120000 egs/aishell2/paraformer/utils delete mode 100644 egs/aishell2/paraformerbert/conf/decode_asr_transformer.yaml delete mode 100644 egs/aishell2/paraformerbert/conf/train_asr_paraformerbert_conformer_20e_6d_1280_320.yaml delete mode 100755 egs/aishell2/paraformerbert/local/extract_embeds.sh delete mode 100755 egs/aishell2/paraformerbert/local/prepare_data.sh delete mode 100755 egs/aishell2/paraformerbert/path.sh delete mode 100755 egs/aishell2/paraformerbert/run.sh delete mode 120000 egs/aishell2/paraformerbert/utils delete mode 100644 egs/aishell2/transformer/conf/decode_asr_transformer.yaml delete mode 100644 egs/aishell2/transformer/conf/train_asr_transformer.yaml delete mode 100755 egs/aishell2/transformer/local/prepare_data.sh delete mode 100755 egs/aishell2/transformer/path.sh delete mode 100755 egs/aishell2/transformer/run.sh delete mode 120000 egs/aishell2/transformer/utils delete mode 100644 egs/aishell2/transformerLM/conf/train_lm_transformer.yaml delete mode 100755 egs/aishell2/transformerLM/path.sh delete mode 100755 egs/aishell2/transformerLM/run.sh delete mode 120000 egs/aishell2/transformerLM/utils delete mode 100644 egs/alimeeting/diarization/sond/README.md delete mode 100644 egs/alimeeting/diarization/sond/config.yaml delete mode 100644 egs/alimeeting/diarization/sond/config_fbank.yaml delete mode 100644 egs/alimeeting/diarization/sond/infer_alimeeting_test.py delete mode 100644 egs/alimeeting/diarization/sond/local/convert_label_to_rttm.py delete mode 100755 egs/alimeeting/diarization/sond/path.sh delete mode 100644 egs/alimeeting/diarization/sond/run.sh delete mode 100644 egs/alimeeting/diarization/sond/unit_test.py delete mode 100644 egs/alimeeting/diarization/sond/unit_test_modelscope.py delete mode 100644 egs/alimeeting/modular_sa_asr/README.md delete mode 100644 egs/alimeeting/modular_sa_asr/conf/mfcc_hires.conf delete mode 100755 egs/alimeeting/modular_sa_asr/exp/segmentation_1a/tdnn_stats_sad_1a/cmvn_opts delete mode 100755 egs/alimeeting/modular_sa_asr/exp/segmentation_1a/tdnn_stats_sad_1a/final.raw delete mode 100755 egs/alimeeting/modular_sa_asr/exp/segmentation_1a/tdnn_stats_sad_1a/frame_subsampling_factor delete mode 100755 egs/alimeeting/modular_sa_asr/exp/segmentation_1a/tdnn_stats_sad_1a/lda.mat delete mode 100755 egs/alimeeting/modular_sa_asr/exp/segmentation_1a/tdnn_stats_sad_1a/lda_stats delete mode 100755 egs/alimeeting/modular_sa_asr/exp/segmentation_1a/tdnn_stats_sad_1a/post_output.vec delete mode 100755 egs/alimeeting/modular_sa_asr/exp/segmentation_1a/tdnn_stats_sad_1a/srand delete mode 100644 egs/alimeeting/modular_sa_asr/figure/20230809161919.jpg delete mode 100644 egs/alimeeting/modular_sa_asr/local/compute_cpcer.py delete mode 100644 egs/alimeeting/modular_sa_asr/local/convert_label_to_rttm.py delete mode 100644 egs/alimeeting/modular_sa_asr/local/extract_profile_from_segments.py delete mode 100644 egs/alimeeting/modular_sa_asr/local/finetune.py delete mode 120000 egs/alimeeting/modular_sa_asr/local/format_wav_scp.py delete mode 120000 egs/alimeeting/modular_sa_asr/local/format_wav_scp.sh delete mode 100644 egs/alimeeting/modular_sa_asr/local/infer_sond.py delete mode 100755 egs/alimeeting/modular_sa_asr/local/make_textgrid_rttm.py delete mode 100755 egs/alimeeting/modular_sa_asr/local/meeting_speaker_number_process.py delete mode 100644 egs/alimeeting/modular_sa_asr/local/merge_spk_text.py delete mode 100755 egs/alimeeting/modular_sa_asr/local/remove_overlap.py delete mode 100644 egs/alimeeting/modular_sa_asr/local/resegment_data.py delete mode 100644 egs/alimeeting/modular_sa_asr/local/rttm2segments.py delete mode 100644 egs/alimeeting/modular_sa_asr/local/run_gss.py delete mode 100644 egs/alimeeting/modular_sa_asr/local/run_wpe.py delete mode 100755 egs/alimeeting/modular_sa_asr/local/segment_to_lab.py delete mode 100755 egs/alimeeting/modular_sa_asr/local/segmentation/detect_speech_activity.sh delete mode 100644 egs/alimeeting/modular_sa_asr/local/test_gss.py delete mode 100644 egs/alimeeting/modular_sa_asr/local/textgrid_processor.py delete mode 100755 egs/alimeeting/modular_sa_asr/path.sh delete mode 100755 egs/alimeeting/modular_sa_asr/run_asr.sh delete mode 100755 egs/alimeeting/modular_sa_asr/run_diar.sh delete mode 100755 egs/alimeeting/modular_sa_asr/run_enh.sh delete mode 100644 egs/alimeeting/sa_asr/README.md delete mode 100644 egs/alimeeting/sa_asr/conf/decode_asr_rnn.yaml delete mode 100644 egs/alimeeting/sa_asr/conf/train_asr_conformer.yaml delete mode 100644 egs/alimeeting/sa_asr/conf/train_sa_asr_conformer.yaml delete mode 100755 egs/alimeeting/sa_asr/local/alimeeting_data_prep.sh delete mode 100755 egs/alimeeting/sa_asr/local/alimeeting_data_prep_test_2023.sh delete mode 100755 egs/alimeeting/sa_asr/local/alimeeting_process_overlap_force.py delete mode 100755 egs/alimeeting/sa_asr/local/alimeeting_process_textgrid.py delete mode 100755 egs/alimeeting/sa_asr/local/apply_map.pl delete mode 100755 egs/alimeeting/sa_asr/local/combine_data.sh delete mode 100755 egs/alimeeting/sa_asr/local/compute_cmvn.py delete mode 100755 egs/alimeeting/sa_asr/local/compute_cmvn.sh delete mode 100644 egs/alimeeting/sa_asr/local/compute_cpcer.py delete mode 100644 egs/alimeeting/sa_asr/local/convert_model.py delete mode 100755 egs/alimeeting/sa_asr/local/copy_data_dir.sh delete mode 100755 egs/alimeeting/sa_asr/local/data/get_reco2dur.sh delete mode 100755 egs/alimeeting/sa_asr/local/data/get_segments_for_data.sh delete mode 100755 egs/alimeeting/sa_asr/local/data/get_utt2dur.sh delete mode 100755 egs/alimeeting/sa_asr/local/data/split_data.sh delete mode 100755 egs/alimeeting/sa_asr/local/download_and_untar.sh delete mode 100644 egs/alimeeting/sa_asr/local/download_pretrained_model_from_modelscope.py delete mode 100644 egs/alimeeting/sa_asr/local/download_xvector_model.py delete mode 100644 egs/alimeeting/sa_asr/local/filter_utt2spk_all_fifo.py delete mode 100755 egs/alimeeting/sa_asr/local/fix_data_dir.sh delete mode 100755 egs/alimeeting/sa_asr/local/format_wav_scp.py delete mode 100755 egs/alimeeting/sa_asr/local/format_wav_scp.sh delete mode 100644 egs/alimeeting/sa_asr/local/gen_cluster_profile_infer.py delete mode 100644 egs/alimeeting/sa_asr/local/gen_oracle_embedding.py delete mode 100644 egs/alimeeting/sa_asr/local/gen_oracle_profile_nopadding.py delete mode 100644 egs/alimeeting/sa_asr/local/gen_oracle_profile_padding.py delete mode 100755 egs/alimeeting/sa_asr/local/perturb_data_dir_speed.sh delete mode 100755 egs/alimeeting/sa_asr/local/process_sot_fifo_textchar2spk.py delete mode 100644 egs/alimeeting/sa_asr/local/process_text_id.py delete mode 100644 egs/alimeeting/sa_asr/local/process_text_spk_merge.py delete mode 100755 egs/alimeeting/sa_asr/local/process_textgrid_to_single_speaker_wav.py delete mode 100755 egs/alimeeting/sa_asr/local/spk2utt_to_utt2spk.pl delete mode 100755 egs/alimeeting/sa_asr/local/text_format.pl delete mode 100755 egs/alimeeting/sa_asr/local/text_normalize.pl delete mode 100755 egs/alimeeting/sa_asr/local/utt2spk_to_spk2utt.pl delete mode 100755 egs/alimeeting/sa_asr/local/validate_data_dir.sh delete mode 100755 egs/alimeeting/sa_asr/local/validate_text.pl delete mode 100755 egs/alimeeting/sa_asr/path.sh delete mode 100755 egs/alimeeting/sa_asr/run.sh delete mode 120000 egs/alimeeting/sa_asr/utils delete mode 100644 egs/callhome/TOLD/eend_ola/conf/train_diar_eend_ola_callhome_chunk2000.yaml delete mode 100644 egs/callhome/TOLD/eend_ola/conf/train_diar_eend_ola_simu_2spkr.yaml delete mode 100644 egs/callhome/TOLD/eend_ola/conf/train_diar_eend_ola_simu_allspkr.yaml delete mode 100644 egs/callhome/TOLD/eend_ola/conf/train_diar_eend_ola_simu_allspkr_chunk2000.yaml delete mode 100644 egs/callhome/TOLD/eend_ola/local/dump_feature.py delete mode 100644 egs/callhome/TOLD/eend_ola/local/gen_feats_scp.py delete mode 100644 egs/callhome/TOLD/eend_ola/local/infer.py delete mode 100755 egs/callhome/TOLD/eend_ola/local/make_callhome.sh delete mode 100755 egs/callhome/TOLD/eend_ola/local/make_mixture.py delete mode 100755 egs/callhome/TOLD/eend_ola/local/make_musan.py delete mode 100755 egs/callhome/TOLD/eend_ola/local/make_musan.sh delete mode 100755 egs/callhome/TOLD/eend_ola/local/make_sre.pl delete mode 100755 egs/callhome/TOLD/eend_ola/local/make_sre.sh delete mode 100755 egs/callhome/TOLD/eend_ola/local/make_swbd2_phase1.pl delete mode 100755 egs/callhome/TOLD/eend_ola/local/make_swbd2_phase2.pl delete mode 100755 egs/callhome/TOLD/eend_ola/local/make_swbd2_phase3.pl delete mode 100644 egs/callhome/TOLD/eend_ola/local/make_swbd_cellular1.pl delete mode 100755 egs/callhome/TOLD/eend_ola/local/make_swbd_cellular2.pl delete mode 100755 egs/callhome/TOLD/eend_ola/local/model_averaging.py delete mode 100755 egs/callhome/TOLD/eend_ola/local/parse_options.sh delete mode 100755 egs/callhome/TOLD/eend_ola/local/random_mixture.py delete mode 100755 egs/callhome/TOLD/eend_ola/local/run_prepare_shared_eda.sh delete mode 100644 egs/callhome/TOLD/eend_ola/local/split.py delete mode 100755 egs/callhome/TOLD/eend_ola/path.sh delete mode 100644 egs/callhome/TOLD/eend_ola/run.sh delete mode 100644 egs/callhome/TOLD/soap/conf/EAND_ResNet34_SAN_L4N512_None_FFN_FSMN_L6N512_bce_dia_loss_01.yaml delete mode 100644 egs/callhome/TOLD/soap/conf/EAND_ResNet34_SAN_L4N512_None_FFN_FSMN_L6N512_bce_dia_loss_01_phase2.yaml delete mode 100644 egs/callhome/TOLD/soap/conf/EAND_ResNet34_SAN_L4N512_None_FFN_FSMN_L6N512_bce_dia_loss_01_phase3.yaml delete mode 100644 egs/callhome/TOLD/soap/conf/basic_inference.yaml delete mode 100644 egs/callhome/TOLD/soap/conf/fbank.conf delete mode 100644 egs/callhome/TOLD/soap/data/token_list/bce_label_n16.txt delete mode 100644 egs/callhome/TOLD/soap/data/token_list/powerset_label_n16k1.txt delete mode 100644 egs/callhome/TOLD/soap/data/token_list/powerset_label_n16k2.txt delete mode 100644 egs/callhome/TOLD/soap/data/token_list/powerset_label_n16k3.txt delete mode 100644 egs/callhome/TOLD/soap/data/token_list/powerset_label_n16k4.txt delete mode 100644 egs/callhome/TOLD/soap/finetune.sh delete mode 100644 egs/callhome/TOLD/soap/path.sh delete mode 100644 egs/callhome/TOLD/soap/run.sh delete mode 100644 egs/callhome/TOLD/soap/script/calc_num_frames.py delete mode 100644 egs/callhome/TOLD/soap/script/calc_real_meeting_frame_labels.py delete mode 100644 egs/callhome/TOLD/soap/script/concat_spk_segs.py delete mode 100644 egs/callhome/TOLD/soap/script/convert_label_to_rttm.py delete mode 100644 egs/callhome/TOLD/soap/script/convert_pse_label_to_bin_ark.py delete mode 100644 egs/callhome/TOLD/soap/script/convert_rttm_to_seg_file.py delete mode 100644 egs/callhome/TOLD/soap/script/dump_meeting_chunks.py delete mode 100644 egs/callhome/TOLD/soap/script/dump_pipe_wav.py delete mode 100644 egs/callhome/TOLD/soap/script/dump_speaker_profiles.py delete mode 100644 egs/callhome/TOLD/soap/script/easy_average_models.py delete mode 100644 egs/callhome/TOLD/soap/script/extract_nonoverlap_segments.py delete mode 100644 egs/callhome/TOLD/soap/script/remove_silence_from_wav.py delete mode 100644 egs/callhome/TOLD/soap/script/simu_whole_recordings.py delete mode 100644 egs/callhome/TOLD/soap/unit_test/sond.yaml delete mode 100644 egs/callhome/TOLD/soap/unit_test/sond_fbank.yaml delete mode 100644 egs/callhome/TOLD/soap/unit_test/unit_test.py delete mode 100644 egs/cnceleb/resnet34/README.md delete mode 100644 egs/cnceleb/resnet34/configuration.json delete mode 100644 egs/cnceleb/resnet34/local/convert_tf_ckpt_to_torch.py delete mode 100644 egs/cnceleb/resnet34/local/make_cnceleb1.sh delete mode 100644 egs/cnceleb/resnet34/local/make_cnceleb2.sh delete mode 100755 egs/cnceleb/resnet34/path.sh delete mode 100644 egs/cnceleb/resnet34/run.sh delete mode 100644 egs/cnceleb/resnet34/sid/calc_trial_scores.py delete mode 100644 egs/cnceleb/resnet34/sid/compute_eer.py delete mode 100644 egs/cnceleb/resnet34/sid/compute_min_dcf.py delete mode 100644 egs/cnceleb/resnet34/sid/speaker_verification.py delete mode 100644 egs/cnceleb/resnet34/sv.yaml delete mode 120000 egs/cnceleb/resnet34/utils delete mode 100644 egs/librispeech/branchformer/README.md delete mode 100644 egs/librispeech/branchformer/conf/decode_asr_transformer_beam10_ctc0.3.yaml delete mode 100644 egs/librispeech/branchformer/conf/train_asr_branchformer.yaml delete mode 100755 egs/librispeech/branchformer/local/data_prep.sh delete mode 100755 egs/librispeech/branchformer/local/download_and_untar.sh delete mode 100755 egs/librispeech/branchformer/local/spm_encode.py delete mode 100755 egs/librispeech/branchformer/local/spm_train.py delete mode 100755 egs/librispeech/branchformer/path.sh delete mode 100755 egs/librispeech/branchformer/run.sh delete mode 120000 egs/librispeech/branchformer/utils delete mode 100644 egs/librispeech/conformer/conf/decode_asr_transformer_ctc0.3_beam5.yaml delete mode 100644 egs/librispeech/conformer/conf/decode_asr_transformer_ctc0.3_beam60.yaml delete mode 100644 egs/librispeech/conformer/conf/train_asr_conformer.yaml delete mode 100755 egs/librispeech/conformer/local/data_prep.sh delete mode 100755 egs/librispeech/conformer/local/download_and_untar.sh delete mode 100755 egs/librispeech/conformer/local/spm_encode.py delete mode 100755 egs/librispeech/conformer/local/spm_train.py delete mode 100755 egs/librispeech/conformer/path.sh delete mode 100755 egs/librispeech/conformer/run.sh delete mode 120000 egs/librispeech/conformer/utils delete mode 100644 egs/librispeech/e_branchformer/README.md delete mode 100644 egs/librispeech/e_branchformer/conf/decode_asr_transformer_beam10_ctc0.3.yaml delete mode 100644 egs/librispeech/e_branchformer/conf/train_asr_e_branchformer.yaml delete mode 100755 egs/librispeech/e_branchformer/local/data_prep.sh delete mode 100755 egs/librispeech/e_branchformer/local/download_and_untar.sh delete mode 100755 egs/librispeech/e_branchformer/local/spm_encode.py delete mode 100755 egs/librispeech/e_branchformer/local/spm_train.py delete mode 100755 egs/librispeech/e_branchformer/path.sh delete mode 100755 egs/librispeech/e_branchformer/run.sh delete mode 120000 egs/librispeech/e_branchformer/utils delete mode 100644 egs/librispeech/rnnt/README.md delete mode 100644 egs/librispeech/rnnt/conf/decode_rnnt_conformer_streaming.yaml delete mode 100644 egs/librispeech/rnnt/conf/train_conformer_rnnt_unified.yaml delete mode 100755 egs/librispeech/rnnt/local/data_prep.sh delete mode 100755 egs/librispeech/rnnt/local/download_and_untar.sh delete mode 100755 egs/librispeech/rnnt/local/spm_encode.py delete mode 100755 egs/librispeech/rnnt/local/spm_train.py delete mode 100644 egs/librispeech/rnnt/path.sh delete mode 100755 egs/librispeech/rnnt/run.sh delete mode 120000 egs/librispeech/rnnt/utils delete mode 100644 egs/librispeech_100h/conformer/conf/decode_asr_transformer_ctc0.3_beam1.yaml delete mode 100644 egs/librispeech_100h/conformer/conf/decode_asr_transformer_ctc0.3_beam20.yaml delete mode 100644 egs/librispeech_100h/conformer/conf/decode_asr_transformer_ctc0.3_beam5.yaml delete mode 100644 egs/librispeech_100h/conformer/conf/train_asr_conformer.yaml delete mode 100755 egs/librispeech_100h/conformer/local/data_prep.sh delete mode 100755 egs/librispeech_100h/conformer/local/download_and_untar.sh delete mode 100755 egs/librispeech_100h/conformer/local/spm_encode.py delete mode 100755 egs/librispeech_100h/conformer/local/spm_train.py delete mode 100755 egs/librispeech_100h/conformer/path.sh delete mode 100755 egs/librispeech_100h/conformer/run.sh delete mode 120000 egs/librispeech_100h/conformer/utils delete mode 100644 egs/librispeech_100h/rnnt/README.md delete mode 100644 egs/librispeech_100h/rnnt/conf/decode_rnnt_conformer.yaml delete mode 100644 egs/librispeech_100h/rnnt/conf/train_conformer_rnnt.yaml delete mode 100755 egs/librispeech_100h/rnnt/local/data_prep.sh delete mode 100755 egs/librispeech_100h/rnnt/local/download_and_untar.sh delete mode 100755 egs/librispeech_100h/rnnt/local/spm_encode.py delete mode 100755 egs/librispeech_100h/rnnt/local/spm_train.py delete mode 100644 egs/librispeech_100h/rnnt/path.sh delete mode 100755 egs/librispeech_100h/rnnt/run.sh delete mode 120000 egs/librispeech_100h/rnnt/utils delete mode 100644 egs/wenetspeech/conformer/conf/decode_asr_transformer_5beam.yaml delete mode 100644 egs/wenetspeech/conformer/conf/train_asr_conformer.yaml delete mode 100755 egs/wenetspeech/conformer/local/data.sh delete mode 100755 egs/wenetspeech/conformer/local/extract_meta.py delete mode 100755 egs/wenetspeech/conformer/local/process_opus.py delete mode 100755 egs/wenetspeech/conformer/local/text_normalize.pl delete mode 100755 egs/wenetspeech/conformer/local/wenetspeech_data_prep.sh delete mode 100755 egs/wenetspeech/conformer/path.sh delete mode 100644 egs/wenetspeech/conformer/run.sh delete mode 120000 egs/wenetspeech/conformer/utils delete mode 100644 egs_modelscope/asr/TEMPLATE/README.md delete mode 100644 egs_modelscope/asr/TEMPLATE/README_zh.md delete mode 100644 egs_modelscope/asr/TEMPLATE/finetune.py delete mode 100644 egs_modelscope/asr/TEMPLATE/infer.py delete mode 100644 egs_modelscope/asr/TEMPLATE/infer.sh delete mode 120000 egs_modelscope/asr/TEMPLATE/utils delete mode 120000 egs_modelscope/asr/conformer/speech_conformer_asr_nat-zh-cn-16k-aishell1-vocab4234-pytorch/README.md delete mode 100644 egs_modelscope/asr/conformer/speech_conformer_asr_nat-zh-cn-16k-aishell1-vocab4234-pytorch/demo.py delete mode 100644 egs_modelscope/asr/conformer/speech_conformer_asr_nat-zh-cn-16k-aishell1-vocab4234-pytorch/finetune.py delete mode 120000 egs_modelscope/asr/conformer/speech_conformer_asr_nat-zh-cn-16k-aishell1-vocab4234-pytorch/infer.py delete mode 120000 egs_modelscope/asr/conformer/speech_conformer_asr_nat-zh-cn-16k-aishell1-vocab4234-pytorch/infer.sh delete mode 120000 egs_modelscope/asr/conformer/speech_conformer_asr_nat-zh-cn-16k-aishell2-vocab5212-pytorch/README.md delete mode 100644 egs_modelscope/asr/conformer/speech_conformer_asr_nat-zh-cn-16k-aishell2-vocab5212-pytorch/demo.py delete mode 100644 egs_modelscope/asr/conformer/speech_conformer_asr_nat-zh-cn-16k-aishell2-vocab5212-pytorch/finetune.py delete mode 120000 egs_modelscope/asr/conformer/speech_conformer_asr_nat-zh-cn-16k-aishell2-vocab5212-pytorch/infer.py delete mode 120000 egs_modelscope/asr/conformer/speech_conformer_asr_nat-zh-cn-16k-aishell2-vocab5212-pytorch/infer.sh delete mode 100644 egs_modelscope/asr/data2vec/speech_data2vec_pretrain-paraformer-zh-cn-aishell2-16k/README.md delete mode 100644 egs_modelscope/asr/data2vec/speech_data2vec_pretrain-paraformer-zh-cn-aishell2-16k/finetune.py delete mode 100644 egs_modelscope/asr/data2vec/speech_data2vec_pretrain-paraformer-zh-cn-aishell2-16k/infer.py delete mode 100644 egs_modelscope/asr/data2vec/speech_data2vec_pretrain-paraformer-zh-cn-aishell2-16k/infer_after_finetune.py delete mode 100644 egs_modelscope/asr/data2vec/speech_data2vec_pretrain-zh-cn-aishell2-16k-pytorch/README.md delete mode 100644 egs_modelscope/asr/data2vec/speech_data2vec_pretrain-zh-cn-aishell2-16k-pytorch/finetune.py delete mode 100644 egs_modelscope/asr/data2vec/speech_data2vec_pretrain-zh-cn-aishell2-16k-pytorch/infer.py delete mode 100644 egs_modelscope/asr/data2vec/speech_data2vec_pretrain-zh-cn-aishell2-16k-pytorch/infer_after_finetune.py delete mode 120000 egs_modelscope/asr/mfcca/speech_mfcca_asr-zh-cn-16k-alimeeting-vocab4950/README.md delete mode 100644 egs_modelscope/asr/mfcca/speech_mfcca_asr-zh-cn-16k-alimeeting-vocab4950/RESULTS.md delete mode 100644 egs_modelscope/asr/mfcca/speech_mfcca_asr-zh-cn-16k-alimeeting-vocab4950/demo.py delete mode 100755 egs_modelscope/asr/mfcca/speech_mfcca_asr-zh-cn-16k-alimeeting-vocab4950/finetune.py delete mode 100755 egs_modelscope/asr/mfcca/speech_mfcca_asr-zh-cn-16k-alimeeting-vocab4950/infer.py delete mode 100755 egs_modelscope/asr/mfcca/speech_mfcca_asr-zh-cn-16k-alimeeting-vocab4950/infer.sh delete mode 120000 egs_modelscope/asr/mfcca/speech_mfcca_asr-zh-cn-16k-alimeeting-vocab4950/utils delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer-large-contextual_asr_nat-zh-cn-16k-common-vocab8404/README.md delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer-large-contextual_asr_nat-zh-cn-16k-common-vocab8404/README_zh.md delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer-large-contextual_asr_nat-zh-cn-16k-common-vocab8404/demo.py delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer-large-contextual_asr_nat-zh-cn-16k-common-vocab8404/finetune.py delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer-large-contextual_asr_nat-zh-cn-16k-common-vocab8404/infer.py delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer-large-contextual_asr_nat-zh-cn-16k-common-vocab8404/infer.sh delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer-large-contextual_asr_nat-zh-cn-16k-common-vocab8404/infer_aishell1_subtest_demo.py delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer-large-contextual_asr_nat-zh-cn-16k-common-vocab8404/utils delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-online/README.md delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-online/README_zh.md delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-online/RESULTS.md delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-online/demo.py delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-online/demo_online.py delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-online/demo_online_v2.py delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-online/finetune.py delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-online/infer.py delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-online/infer.sh delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-online/utils delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch/README.md delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch/README_zh.md delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch/RESULTS.md delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch/demo.py delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch/finetune.py delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch/infer.py delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch/infer.sh delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch/utils delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer-tiny-commandword_asr_nat-zh-cn-16k-vocab544-pytorch/README.md delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer-tiny-commandword_asr_nat-zh-cn-16k-vocab544-pytorch/infer.py delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer_asr-en-16k-vocab4199-pytorch/README.md delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer_asr-en-16k-vocab4199-pytorch/README_zh.md delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer_asr-en-16k-vocab4199-pytorch/demo.py delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer_asr-en-16k-vocab4199-pytorch/finetune.py delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer_asr-en-16k-vocab4199-pytorch/infer.py delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer_asr-en-16k-vocab4199-pytorch/infer.sh delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer_asr-en-16k-vocab4199-pytorch/utils delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-16k-aishell1-vocab4234-pytorch/README.md delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-16k-aishell1-vocab4234-pytorch/README_zh.md delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-16k-aishell1-vocab4234-pytorch/demo.py delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-16k-aishell1-vocab4234-pytorch/finetune.py delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-16k-aishell1-vocab4234-pytorch/infer.py delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-16k-aishell1-vocab4234-pytorch/infer.sh delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-16k-aishell2-vocab5212-pytorch/README.md delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-16k-aishell2-vocab5212-pytorch/README_zh.md delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-16k-aishell2-vocab5212-pytorch/demo.py delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-16k-aishell2-vocab5212-pytorch/finetune.py delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-16k-aishell2-vocab5212-pytorch/infer.py delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-16k-aishell2-vocab5212-pytorch/infer.sh delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-16k-common-vocab8404-online/README.md delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-16k-common-vocab8404-online/README_zh.md delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-16k-common-vocab8404-online/demo.py delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-16k-common-vocab8404-online/demo_online.py delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-16k-common-vocab8404-online/finetune.py delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-16k-common-vocab8404-online/infer.py delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-16k-common-vocab8404-online/infer.sh delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-16k-common-vocab8404-online/utils delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-8k-common-vocab8358-tensorflow1/README.md delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-8k-common-vocab8358-tensorflow1/README_zh.md delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-8k-common-vocab8358-tensorflow1/finetune.py delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-8k-common-vocab8358-tensorflow1/infer.py delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-8k-common-vocab8358-tensorflow1/infer.sh delete mode 100644 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-8k-common-vocab8358-tensorflow1/infer_after_finetune.py delete mode 120000 egs_modelscope/asr/paraformer/speech_paraformer_asr_nat-zh-cn-8k-common-vocab8358-tensorflow1/utils delete mode 100644 egs_modelscope/asr/paraformerbert/speech_paraformerbert_asr_nat-zh-cn-16k-aishell1-vocab4234-pytorch/README.md delete mode 100644 egs_modelscope/asr/paraformerbert/speech_paraformerbert_asr_nat-zh-cn-16k-aishell1-vocab4234-pytorch/infer.py delete mode 100644 egs_modelscope/asr/paraformerbert/speech_paraformerbert_asr_nat-zh-cn-16k-aishell2-vocab5212-pytorch/infer.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-cantonese-CHS-16k-common-vocab1468-tensorflow1-online/finetune.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-cantonese-CHS-16k-common-vocab1468-tensorflow1-online/infer.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-cn-dialect-16k-vocab8358-tensorflow1-online/README.md delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-cn-dialect-16k-vocab8358-tensorflow1-online/finetune.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-cn-dialect-16k-vocab8358-tensorflow1-online/infer.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-de-16k-common-vocab3690-tensorflow1-online/finetune.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-de-16k-common-vocab3690-tensorflow1-online/infer.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-en-16k-common-vocab1080-tensorflow1-online/finetune.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-en-16k-common-vocab1080-tensorflow1-online/infer.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-es-16k-common-vocab3445-tensorflow1-online/finetune.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-es-16k-common-vocab3445-tensorflow1-online/infer.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-fa-16k-common-vocab1257-pytorch-online/README.md delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-fa-16k-common-vocab1257-pytorch-online/finetune.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-fa-16k-common-vocab1257-pytorch-online/infer.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-fa-16k-common-vocab1257-pytorch-online/infer_after_finetune.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-fr-16k-common-vocab3472-tensorflow1-online/finetune.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-fr-16k-common-vocab3472-tensorflow1-online/infer.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-he-16k-common-vocab1085-pytorch/finetune.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-he-16k-common-vocab1085-pytorch/infer.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-id-16k-common-vocab1067-tensorflow1-online/finetune.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-id-16k-common-vocab1067-tensorflow1-online/infer.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-ja-16k-common-vocab93-tensorflow1-online/finetune.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-ja-16k-common-vocab93-tensorflow1-online/infer.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-ko-16k-common-vocab6400-tensorflow1-online/finetune.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-ko-16k-common-vocab6400-tensorflow1-online/infer.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-minnan-16k-common-vocab3825/README.md delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-minnan-16k-common-vocab3825/demo.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-minnan-16k-common-vocab3825/finetune.py delete mode 120000 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-minnan-16k-common-vocab3825/infer.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-minnan-16k-common-vocab3825/infer.sh delete mode 120000 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-minnan-16k-common-vocab3825/utils delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-my-16k-common-vocab696-pytorch/finetune.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-my-16k-common-vocab696-pytorch/infer.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-pt-16k-common-vocab1617-tensorflow1-online/finetune.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-pt-16k-common-vocab1617-tensorflow1-online/infer.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-ru-16k-common-vocab1664-tensorflow1-online/finetune.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-ru-16k-common-vocab1664-tensorflow1-online/infer.py delete mode 120000 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-tr-16k-common-vocab1582-pytorch/README.md delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-tr-16k-common-vocab1582-pytorch/demo.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-tr-16k-common-vocab1582-pytorch/finetune.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-tr-16k-common-vocab1582-pytorch/infer.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-tr-16k-common-vocab1582-pytorch/infer.sh delete mode 120000 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-tr-16k-common-vocab1582-pytorch/utils delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-ur-16k-common-vocab877-pytorch/finetune.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-ur-16k-common-vocab877-pytorch/infer.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-vi-16k-common-vocab1001-pytorch-online/finetune.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-vi-16k-common-vocab1001-pytorch-online/infer.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-zh-cn-16k-common-vocab8358-tensorflow1-online/README.md delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-zh-cn-16k-common-vocab8358-tensorflow1-online/finetune.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-zh-cn-16k-common-vocab8358-tensorflow1-online/infer.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-zh-cn-8k-common-vocab3445-pytorch-online/README.md delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-zh-cn-8k-common-vocab3445-pytorch-online/demo.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-zh-cn-8k-common-vocab3445-pytorch-online/finetune.py delete mode 120000 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-zh-cn-8k-common-vocab3445-pytorch-online/infer.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-zh-cn-8k-common-vocab3445-pytorch-online/infer.sh delete mode 120000 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-zh-cn-8k-common-vocab3445-pytorch-online/utils delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-zh-cn-8k-common-vocab8358-tensorflow1-online/README.md delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-zh-cn-8k-common-vocab8358-tensorflow1-online/finetune.py delete mode 100644 egs_modelscope/asr/uniasr/speech_UniASR_asr_2pass-zh-cn-8k-common-vocab8358-tensorflow1-online/infer.py delete mode 120000 egs_modelscope/asr_vad_punc/TEMPLATE delete mode 120000 egs_modelscope/asr_vad_punc/speech_paraformer-large-vad-punc_asr_nat-en-16k-common-vocab10020/README.md delete mode 120000 egs_modelscope/asr_vad_punc/speech_paraformer-large-vad-punc_asr_nat-en-16k-common-vocab10020/README_zh.md delete mode 100644 egs_modelscope/asr_vad_punc/speech_paraformer-large-vad-punc_asr_nat-en-16k-common-vocab10020/demo.py delete mode 100644 egs_modelscope/asr_vad_punc/speech_paraformer-large-vad-punc_asr_nat-en-16k-common-vocab10020/finetune.py delete mode 100644 egs_modelscope/asr_vad_punc/speech_paraformer-large-vad-punc_asr_nat-en-16k-common-vocab10020/infer.py delete mode 100644 egs_modelscope/asr_vad_punc/speech_paraformer-large-vad-punc_asr_nat-en-16k-common-vocab10020/infer.sh delete mode 120000 egs_modelscope/asr_vad_punc/speech_paraformer-large-vad-punc_asr_nat-en-16k-common-vocab10020/utils delete mode 120000 egs_modelscope/asr_vad_punc/speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-pytorch/README.md delete mode 120000 egs_modelscope/asr_vad_punc/speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-pytorch/README_zh.md delete mode 100644 egs_modelscope/asr_vad_punc/speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-pytorch/demo.py delete mode 100644 egs_modelscope/asr_vad_punc/speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-pytorch/finetune.py delete mode 100644 egs_modelscope/asr_vad_punc/speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-pytorch/infer.py delete mode 100644 egs_modelscope/asr_vad_punc/speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-pytorch/infer.sh delete mode 120000 egs_modelscope/asr_vad_punc/speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-pytorch/utils delete mode 120000 egs_modelscope/asr_vad_spk/TEMPLATE delete mode 100644 egs_modelscope/asr_vad_spk/speech_paraformer-large-vad-punc-spk_asr_nat-zh-cn/demo.py delete mode 100644 egs_modelscope/asr_vad_spk/speech_paraformer-large-vad-punc-spk_asr_nat-zh-cn/finetune.py delete mode 100644 egs_modelscope/asr_vad_spk/speech_paraformer-large-vad-punc-spk_asr_nat-zh-cn/infer.py delete mode 100644 egs_modelscope/lm/speech_transformer_lm_zh-cn-common-vocab8404-pytorch/demo.py delete mode 100644 egs_modelscope/punctuation/TEMPLATE/README.md delete mode 100644 egs_modelscope/punctuation/TEMPLATE/README_zh.md delete mode 100644 egs_modelscope/punctuation/TEMPLATE/infer.py delete mode 100644 egs_modelscope/punctuation/TEMPLATE/infer.sh delete mode 120000 egs_modelscope/punctuation/TEMPLATE/utils delete mode 120000 egs_modelscope/punctuation/punc_ct-transformer_cn-en-common-vocab471067-large/README.md delete mode 120000 egs_modelscope/punctuation/punc_ct-transformer_cn-en-common-vocab471067-large/README_zh.md delete mode 100644 egs_modelscope/punctuation/punc_ct-transformer_cn-en-common-vocab471067-large/data/punc_example.txt delete mode 100644 egs_modelscope/punctuation/punc_ct-transformer_cn-en-common-vocab471067-large/demo.py delete mode 100644 egs_modelscope/punctuation/punc_ct-transformer_cn-en-common-vocab471067-large/infer.py delete mode 100644 egs_modelscope/punctuation/punc_ct-transformer_cn-en-common-vocab471067-large/infer.sh delete mode 120000 egs_modelscope/punctuation/punc_ct-transformer_cn-en-common-vocab471067-large/utils delete mode 120000 egs_modelscope/punctuation/punc_ct-transformer_zh-cn-common-vadrealtime-vocab272727/README_zh.md delete mode 100644 egs_modelscope/punctuation/punc_ct-transformer_zh-cn-common-vadrealtime-vocab272727/demo.py delete mode 120000 egs_modelscope/punctuation/punc_ct-transformer_zh-cn-common-vocab272727-pytorch/README.md delete mode 120000 egs_modelscope/punctuation/punc_ct-transformer_zh-cn-common-vocab272727-pytorch/README_zh.md delete mode 100644 egs_modelscope/punctuation/punc_ct-transformer_zh-cn-common-vocab272727-pytorch/data/punc_example.txt delete mode 100644 egs_modelscope/punctuation/punc_ct-transformer_zh-cn-common-vocab272727-pytorch/demo.py delete mode 120000 egs_modelscope/punctuation/punc_ct-transformer_zh-cn-common-vocab272727-pytorch/infer.py delete mode 120000 egs_modelscope/punctuation/punc_ct-transformer_zh-cn-common-vocab272727-pytorch/infer.sh delete mode 120000 egs_modelscope/punctuation/punc_ct-transformer_zh-cn-common-vocab272727-pytorch/utils delete mode 100644 egs_modelscope/speaker_diarization/TEMPLATE/README.md delete mode 100644 egs_modelscope/speaker_diarization/speech_diarization_eend-ola-en-us-callhome-8k/infer.py delete mode 100644 egs_modelscope/speaker_diarization/speech_diarization_sond-en-us-callhome-8k-n16k4-pytorch/infer.py delete mode 100644 egs_modelscope/speaker_diarization/speech_diarization_sond-zh-cn-alimeeting-16k-n16k4-pytorch/infer.py delete mode 100644 egs_modelscope/speaker_verification/TEMPLATE/README.md delete mode 100644 egs_modelscope/speaker_verification/TEMPLATE/infer.py delete mode 100644 egs_modelscope/speaker_verification/speech_xvector_sv-en-us-callhome-8k-spk6135-pytorch/demo.py delete mode 100644 egs_modelscope/speaker_verification/speech_xvector_sv-en-us-callhome-8k-spk6135-pytorch/infer_sv.py delete mode 100644 egs_modelscope/speaker_verification/speech_xvector_sv-zh-cn-cnceleb-16k-spk3465-pytorch/demo.py delete mode 100644 egs_modelscope/speaker_verification/speech_xvector_sv-zh-cn-cnceleb-16k-spk3465-pytorch/eval_eer.py delete mode 100644 egs_modelscope/speaker_verification/speech_xvector_sv-zh-cn-cnceleb-16k-spk3465-pytorch/infer_sv.py delete mode 100644 egs_modelscope/speech_separation/speech_separation_mossformer_8k_pytorch/demo.py delete mode 100644 egs_modelscope/tp/TEMPLATE/README.md delete mode 100644 egs_modelscope/tp/TEMPLATE/README_zh.md delete mode 100644 egs_modelscope/tp/TEMPLATE/infer.py delete mode 100644 egs_modelscope/tp/TEMPLATE/infer.sh delete mode 120000 egs_modelscope/tp/TEMPLATE/utils delete mode 120000 egs_modelscope/tp/speech_timestamp_prediction-v1-16k-offline/README.md delete mode 100644 egs_modelscope/tp/speech_timestamp_prediction-v1-16k-offline/demo.py delete mode 100644 egs_modelscope/tp/speech_timestamp_prediction-v1-16k-offline/demo_long.py delete mode 120000 egs_modelscope/tp/speech_timestamp_prediction-v1-16k-offline/infer.py delete mode 120000 egs_modelscope/tp/speech_timestamp_prediction-v1-16k-offline/infer.sh delete mode 100644 egs_modelscope/vad/TEMPLATE/README.md delete mode 100644 egs_modelscope/vad/TEMPLATE/README_zh.md delete mode 100644 egs_modelscope/vad/TEMPLATE/infer.py delete mode 100644 egs_modelscope/vad/TEMPLATE/infer.sh delete mode 120000 egs_modelscope/vad/TEMPLATE/utils delete mode 120000 egs_modelscope/vad/speech_fsmn_vad_zh-cn-16k-common/README.md delete mode 120000 egs_modelscope/vad/speech_fsmn_vad_zh-cn-16k-common/README_zh.md delete mode 100644 egs_modelscope/vad/speech_fsmn_vad_zh-cn-16k-common/demo.py delete mode 100644 egs_modelscope/vad/speech_fsmn_vad_zh-cn-16k-common/demo_online.py delete mode 120000 egs_modelscope/vad/speech_fsmn_vad_zh-cn-16k-common/infer.py delete mode 120000 egs_modelscope/vad/speech_fsmn_vad_zh-cn-16k-common/infer.sh delete mode 120000 egs_modelscope/vad/speech_fsmn_vad_zh-cn-8k-common/README.md delete mode 120000 egs_modelscope/vad/speech_fsmn_vad_zh-cn-8k-common/README_zh.md delete mode 100644 egs_modelscope/vad/speech_fsmn_vad_zh-cn-8k-common/demo.py delete mode 100644 egs_modelscope/vad/speech_fsmn_vad_zh-cn-8k-common/demo_online.py delete mode 120000 egs_modelscope/vad/speech_fsmn_vad_zh-cn-8k-common/infer.py delete mode 120000 egs_modelscope/vad/speech_fsmn_vad_zh-cn-8k-common/infer.sh delete mode 100644 funasr/datasets/collate_fn.py delete mode 100644 funasr/datasets/dataset.py rename funasr/datasets/{ => fun_datasets}/data_sampler.py (100%) rename funasr/datasets/{ => fun_datasets}/dataloader_fn.py (93%) rename funasr/datasets/{ => fun_datasets}/dataset_jsonl.py (100%) delete mode 100644 funasr/datasets/iterable_dataset.py delete mode 100644 funasr/datasets/large_datasets/build_dataloader.py delete mode 100644 funasr/datasets/large_datasets/datapipes/batch.py delete mode 100644 funasr/datasets/large_datasets/datapipes/filter.py delete mode 100644 funasr/datasets/large_datasets/datapipes/map.py delete mode 100644 funasr/datasets/large_datasets/dataset.py delete mode 100644 funasr/datasets/large_datasets/utils/clipping.py delete mode 100644 funasr/datasets/large_datasets/utils/filter.py delete mode 100644 funasr/datasets/large_datasets/utils/hotword_utils.py delete mode 100644 funasr/datasets/large_datasets/utils/low_frame_rate.py delete mode 100644 funasr/datasets/large_datasets/utils/padding.py delete mode 100644 funasr/datasets/large_datasets/utils/tokenize.py delete mode 100644 funasr/datasets/ms_dataset.py delete mode 100644 funasr/datasets/preprocessor.py delete mode 100644 funasr/datasets/small_datasets/collate_fn.py delete mode 100644 funasr/datasets/small_datasets/dataset.py delete mode 100644 funasr/datasets/small_datasets/length_batch_sampler.py delete mode 100644 funasr/datasets/small_datasets/preprocessor.py delete mode 100644 funasr/datasets/small_datasets/sequence_iter_factory.py rename {egs/aishell/transformer/utils => funasr/download}/__init__.py (100%) rename funasr/{utils => download}/download_from_hub.py (96%) rename funasr/{utils => download}/modelscope_file.py (100%) rename funasr/{utils => download}/name_maps_from_hub.py (100%) rename funasr/{utils => download}/runtime_sdk_download_tool.py (97%) delete mode 100644 funasr/fileio/npy_scp.py delete mode 100644 funasr/fileio/rand_gen_dataset.py delete mode 100644 funasr/fileio/read_text.py delete mode 100644 funasr/fileio/sound_scp.py delete mode 100644 funasr/iterators/abs_iter_factory.py delete mode 100644 funasr/iterators/chunk_iter_factory.py delete mode 100644 funasr/iterators/multiple_iter_factory.py delete mode 100644 funasr/iterators/sequence_iter_factory.py delete mode 100644 funasr/layers/abs_normalize.py delete mode 100644 funasr/layers/inversible_interface.py delete mode 100644 funasr/layers/sinc_conv.py delete mode 100644 funasr/main_funcs/calculate_all_attentions.py rename funasr/{datasets => metrics}/__init__.py (100%) rename funasr/{models/e2e_asr_common.py => metrics/common.py} (100%) rename funasr/{utils => metrics}/compute_eer.py (100%) rename funasr/{utils => metrics}/compute_min_dcf.py (100%) rename {egs/aishell/transformer/utils => funasr/metrics}/compute_wer.py (100%) delete mode 100644 funasr/models/base_model.py rename funasr/{datasets/large_datasets => models/bat}/__init__.py (100%) rename funasr/models/{e2e_asr_bat.py => bat/model.py} (97%) rename funasr/{datasets/large_datasets/datapipes => models/bici_paraformer}/__init__.py (100%) rename funasr/{datasets/large_datasets/utils => models/branchformer}/__init__.py (100%) rename funasr/models/{encoder => branchformer}/branchformer_encoder.py (97%) rename funasr/{modules => models/branchformer}/cgmlp.py (96%) rename funasr/{modules => models/branchformer}/fastformer.py (100%) create mode 100644 funasr/models/branchformer/model.py rename funasr/{datasets/small_datasets => models/campplus}/__init__.py (100%) rename funasr/{modules => models}/cnn/DTDNN.py (100%) rename funasr/{modules => models}/cnn/ResNet.py (99%) rename funasr/{modules => models}/cnn/ResNet_aug.py (99%) rename funasr/{modules => models}/cnn/__init__.py (100%) rename funasr/{modules => models}/cnn/fusion.py (100%) rename funasr/{modules => models}/cnn/layers.py (100%) rename funasr/{fileio => models/conformer}/__init__.py (100%) rename funasr/models/{encoder => conformer}/conformer_encoder.py (97%) create mode 100644 funasr/models/conformer/model.py rename funasr/{iterators => models/ct_transformer}/__init__.py (100%) rename funasr/models/{ => ct_transformer}/target_delay_transformer.py (98%) rename funasr/{layers => models/ctc}/__init__.py (100%) rename funasr/models/{ => ctc}/ctc.py (100%) rename funasr/{main_funcs => models/data2vec}/__init__.py (100%) rename funasr/models/{ => data2vec}/data2vec.py (98%) rename funasr/models/{encoder => data2vec}/data2vec_encoder.py (98%) rename funasr/{modules => models}/data2vec/data_utils.py (100%) rename funasr/{modules => models}/data2vec/ema_module.py (100%) rename funasr/{modules => models}/data2vec/grad_multiply.py (100%) rename funasr/{modules => models}/data2vec/multihead_attention.py (99%) rename funasr/{modules => models}/data2vec/quant_noise.py (100%) rename funasr/{modules => models}/data2vec/utils.py (98%) rename funasr/{modules => models}/data2vec/wav2vec2.py (99%) delete mode 100644 funasr/models/decoder/abs_decoder.py delete mode 100644 funasr/models/e2e_asr.py delete mode 100644 funasr/models/e2e_asr_contextual_paraformer.py delete mode 100644 funasr/models/e2e_asr_paraformer.py delete mode 100644 funasr/models/e2e_asr_transducer.py rename funasr/models/{decoder => e_branchformer}/__init__.py (100%) rename funasr/models/{encoder => e_branchformer}/e_branchformer_encoder.py (96%) create mode 100644 funasr/models/e_branchformer/model.py rename funasr/models/{encoder => eend}/__init__.py (100%) rename funasr/models/{ => eend}/e2e_diar_eend_ola.py (94%) rename funasr/{modules/eend_ola => models/eend}/eend_ola_dataloader.py (100%) rename funasr/{modules/eend_ola => models/eend}/encoder.py (100%) rename funasr/{modules/eend_ola => models/eend}/encoder_decoder_attractor.py (100%) rename funasr/models/{encoder/opennmt_encoders => eend/utils}/__init__.py (100%) rename funasr/{modules/eend_ola => models/eend}/utils/feature.py (100%) rename funasr/{modules/eend_ola => models/eend}/utils/kaldi_data.py (100%) rename funasr/{modules/eend_ola => models/eend}/utils/losses.py (100%) rename funasr/{modules/eend_ola => models/eend}/utils/power.py (100%) rename funasr/{modules/eend_ola => models/eend}/utils/report.py (99%) delete mode 100644 funasr/models/encoder/abs_encoder.py rename funasr/models/frontend/{frontends_utils => utils}/__init__.py (100%) rename funasr/models/frontend/{frontends_utils => utils}/beamformer.py (100%) rename funasr/{layers => models/frontend/utils}/complex_utils.py (100%) rename funasr/models/frontend/{frontends_utils => utils}/dnn_beamformer.py (94%) rename funasr/models/frontend/{frontends_utils => utils}/dnn_wpe.py (95%) rename funasr/models/frontend/{frontends_utils => utils}/feature_transform.py (99%) rename funasr/models/frontend/{frontends_utils => utils}/frontend.py (96%) rename funasr/{layers => models/frontend/utils}/log_mel.py (97%) rename funasr/models/frontend/{frontends_utils => utils}/mask_estimator.py (93%) rename funasr/{layers => models/frontend/utils}/stft.py (97%) rename funasr/models/{pooling => fsmn_vad}/__init__.py (100%) rename funasr/models/{encoder => fsmn_vad}/fsmn_encoder.py (100%) rename funasr/models/{e2e_vad.py => fsmn_vad/model.py} (98%) rename funasr/models/{ => fsmn_vad}/vad_realtime_transformer.py (98%) delete mode 100644 funasr/models/joint_net/__init__.py rename funasr/models/{postencoder => language_model}/__init__.py (100%) rename funasr/{modules => models/language_model}/rnn/__init__.py (100%) rename funasr/{modules => models/language_model}/rnn/argument.py (100%) rename funasr/{modules => models/language_model}/rnn/attentions.py (99%) rename funasr/{modules => models/language_model}/rnn/decoders.py (98%) rename funasr/{modules => models/language_model}/rnn/encoders.py (98%) rename funasr/models/{ => language_model}/seq_rnn_lm.py (100%) rename funasr/models/{ => language_model}/transformer_lm.py (96%) rename funasr/models/{predictor => lora}/__init__.py (100%) rename funasr/{modules => models}/lora/layers.py (100%) rename funasr/{modules => models}/lora/utils.py (100%) rename funasr/models/{preencoder => mfcca}/__init__.py (100%) rename funasr/models/{ => mfcca}/e2e_asr_mfcca.py (98%) rename funasr/models/{encoder => mfcca}/encoder_layer_mfcca.py (99%) rename funasr/models/{encoder => mfcca}/mfcca_encoder.py (94%) rename funasr/models/{whisper_models => mossformer}/__init__.py (100%) rename funasr/models/{ => mossformer}/e2e_ss.py (100%) rename funasr/{modules => models/mossformer}/mossformer.py (100%) rename funasr/models/{decoder => mossformer}/mossformer_decoder.py (100%) rename funasr/models/{encoder => mossformer}/mossformer_encoder.py (98%) rename funasr/{modules => models/neat_contextual_paraformer}/__init__.py (100%) rename funasr/{modules/beam_search => models/normalize}/__init__.py (100%) rename funasr/{layers => models/normalize}/global_mvn.py (93%) rename funasr/{layers => models/normalize}/utterance_mvn.py (93%) rename funasr/models/{predictor/cif.py => paraformer/cif_predictor.py} (96%) rename funasr/models/{decoder => paraformer}/contextual_decoder.py (98%) rename funasr/{modules/data2vec => models/paraformer_online}/__init__.py (100%) delete mode 100644 funasr/models/postencoder/abs_postencoder.py delete mode 100644 funasr/models/postencoder/hugging_face_transformers_postencoder.py delete mode 100644 funasr/models/preencoder/abs_preencoder.py delete mode 100644 funasr/models/preencoder/linear.py delete mode 100644 funasr/models/preencoder/sinc.py rename funasr/{modules/eend_ola => models/rwkv_bat}/__init__.py (100%) rename funasr/{modules => models/rwkv_bat}/cuda_decoder/wkv_cuda.cu (100%) rename funasr/{modules => models/rwkv_bat}/cuda_decoder/wkv_op.cpp (100%) rename funasr/{modules => models/rwkv_bat}/cuda_encoder/wkv_cuda.cu (100%) rename funasr/{modules => models/rwkv_bat}/cuda_encoder/wkv_op.cpp (100%) rename egs/wenetspeech/conformer/local/path.sh => funasr/models/rwkv_bat/model.py (100%) rename funasr/{modules => models/rwkv_bat}/rwkv.py (95%) rename funasr/{modules => models/rwkv_bat}/rwkv_attention.py (100%) rename funasr/models/{encoder => rwkv_bat}/rwkv_encoder.py (94%) rename funasr/{modules => models/rwkv_bat}/rwkv_feed_forward.py (100%) rename funasr/{modules => models/rwkv_bat}/rwkv_subsampling.py (97%) rename funasr/{modules/eend_ola/utils => models/sa_asr}/__init__.py (100%) rename funasr/{modules/beam_search => models/sa_asr}/beam_search_sa_asr.py (98%) rename funasr/models/{ => sa_asr}/e2e_sa_asr.py (98%) rename funasr/{modules/lora => models/sanm}/__init__.py (100%) rename funasr/models/{decoder => sanm}/sanm_decoder.py (99%) rename funasr/models/{encoder => sanm}/sanm_encoder.py (97%) rename funasr/{modules/streaming_utils => models/scama}/__init__.py (100%) create mode 100644 funasr/models/scama/beam_search.py rename funasr/{modules/streaming_utils => models/scama}/chunk_utilis.py (99%) rename funasr/{modules/streaming_utils => models/scama}/utils.py (100%) rename funasr/{samplers => models/sond}/__init__.py (100%) rename funasr/models/{ => sond}/e2e_diar_sond.py (99%) rename funasr/{tasks => models/sond/encoder}/__init__.py (100%) rename funasr/models/{encoder/opennmt_encoders => sond/encoder}/ci_scorers.py (100%) rename funasr/models/{encoder/opennmt_encoders => sond/encoder}/conv_encoder.py (98%) rename funasr/models/{ => sond}/encoder/ecapa_tdnn_encoder.py (100%) rename funasr/models/{encoder/opennmt_encoders => sond/encoder}/fsmn_encoder.py (98%) rename funasr/models/{ => sond}/encoder/resnet34_encoder.py (100%) rename funasr/models/{encoder/opennmt_encoders => sond/encoder}/self_attention_encoder.py (95%) rename funasr/{layers => models/sond}/label_aggregation.py (97%) rename funasr/{torch_utils => models/sond/pooling}/__init__.py (100%) rename funasr/models/{ => sond}/pooling/pooling_layers.py (100%) rename funasr/models/{ => sond}/pooling/statistic_pooling.py (97%) rename funasr/models/{decoder => sond}/sv_decoder.py (100%) delete mode 100644 funasr/models/specaug/abs_profileaug.py delete mode 100644 funasr/models/specaug/abs_specaug.py rename funasr/{layers => models/specaug}/mask_along_axis.py (100%) rename funasr/{layers => models/specaug}/time_warp.py (97%) rename funasr/{train => models/tp_aligner}/__init__.py (100%) rename funasr/models/{ => tp_aligner}/e2e_tp.py (96%) rename funasr/{utils/whisper_utils => models/transducer}/__init__.py (100%) rename funasr/{modules/beam_search => models/transducer}/beam_search_transducer.py (99%) rename funasr/models/{joint_net => transducer}/joint_network.py (96%) create mode 100644 funasr/models/transducer/model.py rename funasr/models/{decoder => transducer}/rnn_decoder.py (98%) rename funasr/models/{encoder => transducer}/rnn_encoder.py (94%) rename funasr/models/{decoder => transducer}/rnnt_decoder.py (99%) create mode 100644 funasr/models/transformer/__init__.py rename funasr/{modules => models/transformer}/attention.py (99%) rename funasr/{modules => models/transformer}/embedding.py (100%) rename funasr/{modules => models/transformer}/layer_norm.py (100%) create mode 100644 funasr/models/transformer/model.py rename funasr/{modules => models/transformer}/positionwise_feed_forward.py (96%) rename funasr/{modules => models/transformer}/scorers/__init__.py (100%) rename funasr/{modules => models/transformer}/scorers/ctc.py (95%) rename funasr/{modules => models/transformer}/scorers/ctc_prefix_score.py (100%) rename funasr/{modules => models/transformer}/scorers/length_bonus.py (95%) rename funasr/{modules => models/transformer}/scorers/scorer_interface.py (100%) create mode 100644 funasr/models/transformer/search.py rename funasr/models/{decoder => transformer}/transformer_decoder.py (97%) rename funasr/models/{encoder => transformer}/transformer_encoder.py (95%) create mode 100644 funasr/models/transformer/utils/__init__.py rename funasr/{modules => models/transformer/utils}/add_sos_eos.py (93%) rename funasr/{modules => models/transformer/utils}/dynamic_conv.py (100%) rename funasr/{modules => models/transformer/utils}/dynamic_conv2d.py (100%) rename funasr/{modules => models/transformer/utils}/lightconv.py (100%) rename funasr/{modules => models/transformer/utils}/lightconv2d.py (100%) rename funasr/{modules => models/transformer/utils}/mask.py (100%) rename funasr/{modules => models/transformer/utils}/multi_layer_conv.py (100%) rename funasr/{modules => models/transformer/utils}/nets_utils.py (100%) rename funasr/{modules => models/transformer/utils}/repeat.py (98%) rename funasr/{modules => models/transformer/utils}/subsampling.py (99%) rename funasr/{modules => models/transformer/utils}/subsampling_without_posenc.py (100%) rename funasr/{modules => models/transformer/utils}/vgg2l.py (100%) create mode 100644 funasr/models/uniasr/__init__.py rename funasr/models/{ => uniasr}/e2e_uni_asr.py (99%) create mode 100644 funasr/models/whisper/__init__.py rename funasr/models/{whisper_models => whisper}/model.py (97%) create mode 100644 funasr/models/whisper/utils/__init__.py rename funasr/{utils/whisper_utils => models/whisper/utils}/assets/gpt2/merges.txt (100%) rename funasr/{utils/whisper_utils => models/whisper/utils}/assets/gpt2/special_tokens_map.json (100%) rename funasr/{utils/whisper_utils => models/whisper/utils}/assets/gpt2/tokenizer_config.json (100%) rename funasr/{utils/whisper_utils => models/whisper/utils}/assets/gpt2/vocab.json (100%) rename funasr/{utils/whisper_utils => models/whisper/utils}/assets/mel_filters.npz (100%) rename funasr/{utils/whisper_utils => models/whisper/utils}/assets/multilingual/added_tokens.json (100%) rename funasr/{utils/whisper_utils => models/whisper/utils}/assets/multilingual/merges.txt (100%) rename funasr/{utils/whisper_utils => models/whisper/utils}/assets/multilingual/special_tokens_map.json (100%) rename funasr/{utils/whisper_utils => models/whisper/utils}/assets/multilingual/tokenizer_config.json (100%) rename funasr/{utils/whisper_utils => models/whisper/utils}/assets/multilingual/vocab.json (100%) rename funasr/{utils/whisper_utils => models/whisper/utils}/audio.py (98%) rename funasr/{utils/whisper_utils => models/whisper/utils}/decoding.py (99%) rename funasr/{utils/whisper_utils => models/whisper/utils}/tokenizer.py (100%) rename funasr/{utils/whisper_utils => models/whisper/utils}/transcribe.py (97%) rename funasr/{utils/whisper_utils => models/whisper/utils}/utils.py (100%) create mode 100644 funasr/models/xvector/__init__.py rename funasr/models/{ => xvector}/e2e_sv.py (97%) delete mode 100644 funasr/modules/beam_search/batch_beam_search.py delete mode 100644 funasr/modules/beam_search/batch_beam_search_online_sim.py delete mode 100644 funasr/modules/beam_search/beam_search.py delete mode 100644 funasr/modules/e2e_asr_common.py delete mode 100644 funasr/samplers/abs_sampler.py delete mode 100644 funasr/samplers/build_batch_sampler.py delete mode 100644 funasr/samplers/folded_batch_sampler.py delete mode 100644 funasr/samplers/length_batch_sampler.py delete mode 100644 funasr/samplers/num_elements_batch_sampler.py delete mode 100644 funasr/samplers/sorted_batch_sampler.py delete mode 100644 funasr/samplers/unsorted_batch_sampler.py delete mode 100644 funasr/tasks/abs_task.py delete mode 100644 funasr/tasks/asr.py delete mode 100644 funasr/tasks/data2vec.py delete mode 100644 funasr/tasks/diar.py delete mode 100644 funasr/tasks/lm.py delete mode 100644 funasr/tasks/punctuation.py delete mode 100644 funasr/tasks/sa_asr.py delete mode 100644 funasr/tasks/sv.py delete mode 100644 funasr/tasks/vad.py delete mode 100644 funasr/tasks/whisper.py delete mode 100644 funasr/torch_utils/initialize.py delete mode 100644 funasr/train/abs_model.py delete mode 100644 funasr/train/distributed_utils.py delete mode 100644 funasr/train/reporter.py delete mode 100644 funasr/train/trainer.py create mode 100644 funasr/train_utils/__init__.py rename funasr/{torch_utils => train_utils}/add_gradient_noise.py (100%) rename funasr/{main_funcs => train_utils}/average_nbest_models.py (100%) rename funasr/{main_funcs => train_utils}/collect_stats.py (96%) rename funasr/{torch_utils => train_utils}/device_funcs.py (100%) rename funasr/{torch_utils => train_utils}/forward_adaptor.py (100%) create mode 100644 funasr/train_utils/initialize.py rename funasr/{torch_utils => train_utils}/load_pretrained_model.py (100%) rename funasr/{torch_utils => train_utils}/model_summary.py (100%) rename funasr/{main_funcs => train_utils}/pack_funcs.py (100%) rename funasr/{torch_utils => train_utils}/pytorch_version.py (100%) rename funasr/{torch_utils => train_utils}/recursive_op.py (100%) rename funasr/{torch_utils => train_utils}/set_all_random_seed.py (100%) rename funasr/{utils => train_utils}/trainer.py (98%) delete mode 100644 funasr/utils/asr_env_checking.py delete mode 100644 funasr/utils/build_dataclass.py rename funasr/{train => utils}/class_choices.py (100%) delete mode 100644 funasr/utils/cluster_backend.py delete mode 100755 funasr/utils/compute_wer.py delete mode 100644 funasr/utils/config_argparse.py rename funasr/{fileio => utils}/datadir_writer.py (100%) delete mode 100644 funasr/utils/download_and_prepare_model.py delete mode 100644 funasr/utils/get_default_kwargs.py delete mode 100644 funasr/utils/griffin_lim.py delete mode 100644 funasr/utils/hinter.py delete mode 100644 funasr/utils/job_runner.py delete mode 100644 funasr/utils/kwargs2args.py delete mode 100644 funasr/utils/load_fr_py.py rename funasr/{modules/streaming_utils => utils}/load_fr_tf.py (100%) delete mode 100644 funasr/utils/modelscope_param.py delete mode 100644 funasr/utils/modelscope_utils.py delete mode 100644 funasr/utils/nested_dict_action.py delete mode 100644 funasr/utils/sized_dict.py delete mode 100644 funasr/utils/wav_utils.py rename {docs/model_zoo => model_zoo}/huggingface_models.md (100%) rename {docs/model_zoo => model_zoo}/modelscope_models.md (100%) rename {docs/model_zoo => model_zoo}/modelscope_models_zh.md (100%) diff --git a/egs/aishell/bat/README.md b/egs/aishell/bat/README.md deleted file mode 100644 index ed2a6dafb..000000000 --- a/egs/aishell/bat/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Boundary Aware Transducer (BAT) Result - -## Training Config -- 8 gpu(Tesla V100) -- Feature info: using 80 dims fbank, global cmvn, speed perturb(0.9, 1.0, 1.1), specaugment -- Train config: conf/train_conformer_bat.yaml -- LM config: LM was not used -- Model size: 90M - -## Results (CER) -- Decode config: conf/decode_bat_conformer.yaml - -| testset | CER(%) | -|:-----------:|:-------:| -| dev | 4.56 | -| test | 4.97 | diff --git a/egs/aishell/bat/conf/decode_bat_conformer.yaml b/egs/aishell/bat/conf/decode_bat_conformer.yaml deleted file mode 100644 index 9a71e66b8..000000000 --- a/egs/aishell/bat/conf/decode_bat_conformer.yaml +++ /dev/null @@ -1 +0,0 @@ -beam_size: 10 diff --git a/egs/aishell/bat/conf/train_conformer_bat.yaml b/egs/aishell/bat/conf/train_conformer_bat.yaml deleted file mode 100644 index 46ca9bfa6..000000000 --- a/egs/aishell/bat/conf/train_conformer_bat.yaml +++ /dev/null @@ -1,108 +0,0 @@ -encoder: chunk_conformer -encoder_conf: - activation_type: swish - positional_dropout_rate: 0.5 - time_reduction_factor: 2 - embed_vgg_like: false - subsampling_factor: 4 - linear_units: 2048 - output_size: 512 - attention_heads: 8 - dropout_rate: 0.5 - positional_dropout_rate: 0.5 - attention_dropout_rate: 0.5 - cnn_module_kernel: 15 - num_blocks: 12 - -# decoder related -rnnt_decoder: rnnt -rnnt_decoder_conf: - embed_size: 512 - hidden_size: 512 - embed_dropout_rate: 0.5 - dropout_rate: 0.5 - use_embed_mask: true - -predictor: bat_predictor -predictor_conf: - idim: 512 - threshold: 1.0 - l_order: 1 - r_order: 1 - return_accum: true - -joint_network_conf: - joint_space_size: 512 - -# frontend related -frontend: wav_frontend -frontend_conf: - fs: 16000 - window: hamming - n_mels: 80 - frame_length: 25 - frame_shift: 10 - lfr_m: 1 - lfr_n: 1 - - -# Auxiliary CTC -model: bat -model_conf: - auxiliary_ctc_weight: 0.0 - cif_weight: 1.0 - r_d: 3 - r_u: 5 - -# minibatch related -use_amp: true - -# optimization related -accum_grad: 1 -grad_clip: 5 -max_epoch: 100 -val_scheduler_criterion: - - valid - - loss -best_model_criterion: -- - valid - - cer_transducer - - min -keep_nbest_models: 10 - -optim: adam -optim_conf: - lr: 0.001 -scheduler: warmuplr -scheduler_conf: - warmup_steps: 25000 - -specaug: specaug -specaug_conf: - apply_time_warp: true - time_warp_window: 5 - time_warp_mode: bicubic - apply_freq_mask: true - freq_mask_width_range: - - 0 - - 40 - num_freq_mask: 2 - apply_time_mask: true - time_mask_width_range: - - 0 - - 50 - num_time_mask: 5 - -dataset_conf: - data_names: speech,text - data_types: sound,text - shuffle: True - shuffle_conf: - shuffle_size: 2048 - sort_size: 500 - batch_conf: - batch_type: token - batch_size: 25000 - num_workers: 8 - -log_interval: 50 diff --git a/egs/aishell/bat/local/aishell_data_prep.sh b/egs/aishell/bat/local/aishell_data_prep.sh deleted file mode 100755 index 83f489b3c..000000000 --- a/egs/aishell/bat/local/aishell_data_prep.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash - -# Copyright 2017 Xingyu Na -# Apache 2.0 - -#. ./path.sh || exit 1; - -if [ $# != 3 ]; then - echo "Usage: $0 " - echo " $0 /export/a05/xna/data/data_aishell/wav /export/a05/xna/data/data_aishell/transcript data" - exit 1; -fi - -aishell_audio_dir=$1 -aishell_text=$2/aishell_transcript_v0.8.txt -output_dir=$3 - -train_dir=$output_dir/data/local/train -dev_dir=$output_dir/data/local/dev -test_dir=$output_dir/data/local/test -tmp_dir=$output_dir/data/local/tmp - -mkdir -p $train_dir -mkdir -p $dev_dir -mkdir -p $test_dir -mkdir -p $tmp_dir - -# data directory check -if [ ! -d $aishell_audio_dir ] || [ ! -f $aishell_text ]; then - echo "Error: $0 requires two directory arguments" - exit 1; -fi - -# find wav audio file for train, dev and test resp. -find $aishell_audio_dir -iname "*.wav" > $tmp_dir/wav.flist -n=`cat $tmp_dir/wav.flist | wc -l` -[ $n -ne 141925 ] && \ - echo Warning: expected 141925 data data files, found $n - -grep -i "wav/train" $tmp_dir/wav.flist > $train_dir/wav.flist || exit 1; -grep -i "wav/dev" $tmp_dir/wav.flist > $dev_dir/wav.flist || exit 1; -grep -i "wav/test" $tmp_dir/wav.flist > $test_dir/wav.flist || exit 1; - -rm -r $tmp_dir - -# Transcriptions preparation -for dir in $train_dir $dev_dir $test_dir; do - echo Preparing $dir transcriptions - sed -e 's/\.wav//' $dir/wav.flist | awk -F '/' '{print $NF}' > $dir/utt.list - paste -d' ' $dir/utt.list $dir/wav.flist > $dir/wav.scp_all - utils/filter_scp.pl -f 1 $dir/utt.list $aishell_text > $dir/transcripts.txt - awk '{print $1}' $dir/transcripts.txt > $dir/utt.list - utils/filter_scp.pl -f 1 $dir/utt.list $dir/wav.scp_all | sort -u > $dir/wav.scp - sort -u $dir/transcripts.txt > $dir/text -done - -mkdir -p $output_dir/data/train $output_dir/data/dev $output_dir/data/test - -for f in wav.scp text; do - cp $train_dir/$f $output_dir/data/train/$f || exit 1; - cp $dev_dir/$f $output_dir/data/dev/$f || exit 1; - cp $test_dir/$f $output_dir/data/test/$f || exit 1; -done - -echo "$0: AISHELL data preparation succeeded" -exit 0; diff --git a/egs/aishell/bat/path.sh b/egs/aishell/bat/path.sh deleted file mode 100644 index 7972642d0..000000000 --- a/egs/aishell/bat/path.sh +++ /dev/null @@ -1,5 +0,0 @@ -export FUNASR_DIR=$PWD/../../.. - -# NOTE(kan-bayashi): Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C -export PYTHONIOENCODING=UTF-8 -export PATH=$FUNASR_DIR/funasr/bin:$PATH diff --git a/egs/aishell/bat/run.sh b/egs/aishell/bat/run.sh deleted file mode 100755 index 54f1d877b..000000000 --- a/egs/aishell/bat/run.sh +++ /dev/null @@ -1,210 +0,0 @@ -#!/usr/bin/env bash - -. ./path.sh || exit 1; - -# machines configuration -CUDA_VISIBLE_DEVICES="0,1,2,3,4,5,6,7" -gpu_num=8 -count=1 -gpu_inference=true # Whether to perform gpu decoding, set false for cpu decoding -# for gpu decoding, inference_nj=ngpu*njob; for cpu decoding, inference_nj=njob -njob=5 -train_cmd=utils/run.pl -infer_cmd=utils/run.pl - -# general configuration -feats_dir="../DATA" #feature output dictionary -exp_dir="." -lang=zh -token_type=char -type=sound -scp=wav.scp -speed_perturb="0.9 1.0 1.1" -stage=0 -stop_stage=5 - -# feature configuration -feats_dim=80 -nj=64 - -# data -raw_data=../raw_data -data_url=www.openslr.org/resources/33 - -# exp tag -tag="exp1" - -. utils/parse_options.sh || exit 1; - -# Set bash to 'debug' mode, it will exit on : -# -e 'error', -u 'undefined variable', -o ... 'error in pipeline', -x 'print commands', -set -e -set -u -set -o pipefail - -train_set=train -valid_set=dev -test_sets="dev test" - -asr_config=conf/train_conformer_bat.yaml -model_dir="baseline_$(basename "${asr_config}" .yaml)_${lang}_${token_type}_${tag}" - -inference_config=conf/decode_bat_conformer.yaml -inference_asr_model=valid.cer_transducer.ave_10best.pb - -# you can set gpu num for decoding here -gpuid_list=$CUDA_VISIBLE_DEVICES # set gpus for decoding, the same as training stage by default -ngpu=$(echo $gpuid_list | awk -F "," '{print NF}') - -if ${gpu_inference}; then - inference_nj=$[${ngpu}*${njob}] - _ngpu=1 -else - inference_nj=$njob - _ngpu=0 -fi - -if [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then - echo "stage -1: Data Download" - local/download_and_untar.sh ${raw_data} ${data_url} data_aishell - local/download_and_untar.sh ${raw_data} ${data_url} resource_aishell -fi - -if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then - echo "stage 0: Data preparation" - # Data preparation - local/aishell_data_prep.sh ${raw_data}/data_aishell/wav ${raw_data}/data_aishell/transcript ${feats_dir} - for x in train dev test; do - cp ${feats_dir}/data/${x}/text ${feats_dir}/data/${x}/text.org - paste -d " " <(cut -f 1 -d" " ${feats_dir}/data/${x}/text.org) <(cut -f 2- -d" " ${feats_dir}/data/${x}/text.org | tr -d " ") \ - > ${feats_dir}/data/${x}/text - utils/text2token.py -n 1 -s 1 ${feats_dir}/data/${x}/text > ${feats_dir}/data/${x}/text.org - mv ${feats_dir}/data/${x}/text.org ${feats_dir}/data/${x}/text - done -fi - -if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then - echo "stage 1: Feature and CMVN Generation" - utils/compute_cmvn.sh --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} ${feats_dir}/data/${train_set} -fi - -token_list=${feats_dir}/data/${lang}_token_list/char/tokens.txt -echo "dictionary: ${token_list}" -if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then - echo "stage 2: Dictionary Preparation" - mkdir -p ${feats_dir}/data/${lang}_token_list/char/ - - echo "make a dictionary" - echo "" > ${token_list} - echo "" >> ${token_list} - echo "" >> ${token_list} - utils/text2token.py -s 1 -n 1 --space "" ${feats_dir}/data/$train_set/text | cut -f 2- -d" " | tr " " "\n" \ - | sort | uniq | grep -a -v -e '^\s*$' | awk '{print $0}' >> ${token_list} - echo "" >> ${token_list} -fi - -# LM Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then - echo "stage 3: LM Training" -fi - -# ASR Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then - echo "stage 4: ASR Training" - mkdir -p ${exp_dir}/exp/${model_dir} - mkdir -p ${exp_dir}/exp/${model_dir}/log - INIT_FILE=./ddp_init - if [ -f $INIT_FILE ];then - rm -f $INIT_FILE - fi - init_method=file://$(readlink -f $INIT_FILE) - echo "$0: init method is $init_method" - for ((i = 0; i < $gpu_num; ++i)); do - { - rank=$i - local_rank=$i - gpu_id=$(echo $CUDA_VISIBLE_DEVICES | cut -d',' -f$[$i+1]) - train.py \ - --task_name asr \ - --gpu_id $gpu_id \ - --use_preprocessor true \ - --token_type char \ - --token_list $token_list \ - --data_dir ${feats_dir}/data \ - --train_set ${train_set} \ - --valid_set ${valid_set} \ - --data_file_names "wav.scp,text" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/cmvn.mvn \ - --speed_perturb ${speed_perturb} \ - --resume true \ - --output_dir ${exp_dir}/exp/${model_dir} \ - --config $asr_config \ - --ngpu $gpu_num \ - --num_worker_count $count \ - --dist_init_method $init_method \ - --dist_world_size $world_size \ - --dist_rank $rank \ - --local_rank $local_rank 1> ${exp_dir}/exp/${model_dir}/log/train.log.$i 2>&1 - } & - done - wait -fi - -# Testing Stage -if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then - echo "stage 5: Inference" - for dset in ${test_sets}; do - asr_exp=${exp_dir}/exp/${model_dir} - inference_tag="$(basename "${inference_config}" .yaml)" - _dir="${asr_exp}/${inference_tag}/${inference_asr_model}/${dset}" - _logdir="${_dir}/logdir" - if [ -d ${_dir} ]; then - echo "${_dir} is already exists. if you want to decode again, please delete this dir first." - exit 0 - fi - mkdir -p "${_logdir}" - _data="${feats_dir}/data/${dset}" - key_file=${_data}/${scp} - num_scp_file="$(<${key_file} wc -l)" - _nj=$([ $inference_nj -le $num_scp_file ] && echo "$inference_nj" || echo "$num_scp_file") - split_scps= - for n in $(seq "${_nj}"); do - split_scps+=" ${_logdir}/keys.${n}.scp" - done - # shellcheck disable=SC2086 - utils/split_scp.pl "${key_file}" ${split_scps} - _opts= - if [ -n "${inference_config}" ]; then - _opts+="--config ${inference_config} " - fi - ${infer_cmd} --gpu "${_ngpu}" --max-jobs-run "${_nj}" JOB=1:"${_nj}" "${_logdir}"/asr_inference.JOB.log \ - python -m funasr.bin.asr_inference_launch \ - --batch_size 1 \ - --ngpu "${_ngpu}" \ - --njob ${njob} \ - --gpuid_list ${gpuid_list} \ - --data_path_and_name_and_type "${_data}/${scp},speech,${type}" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/cmvn.mvn \ - --key_file "${_logdir}"/keys.JOB.scp \ - --asr_train_config "${asr_exp}"/config.yaml \ - --asr_model_file "${asr_exp}"/"${inference_asr_model}" \ - --output_dir "${_logdir}"/output.JOB \ - --mode bat \ - ${_opts} - - for f in token token_int score text; do - if [ -f "${_logdir}/output.1/1best_recog/${f}" ]; then - for i in $(seq "${_nj}"); do - cat "${_logdir}/output.${i}/1best_recog/${f}" - done | sort -k1 >"${_dir}/${f}" - fi - done - python utils/proce_text.py ${_dir}/text ${_dir}/text.proc - python utils/proce_text.py ${_data}/text ${_data}/text.proc - python utils/compute_wer.py ${_data}/text.proc ${_dir}/text.proc ${_dir}/text.cer - tail -n 3 ${_dir}/text.cer > ${_dir}/text.cer.txt - cat ${_dir}/text.cer.txt - done -fi diff --git a/egs/aishell/bat/utils b/egs/aishell/bat/utils deleted file mode 120000 index 4072eacc1..000000000 --- a/egs/aishell/bat/utils +++ /dev/null @@ -1 +0,0 @@ -../transformer/utils \ No newline at end of file diff --git a/egs/aishell/branchformer/README.md b/egs/aishell/branchformer/README.md deleted file mode 100644 index 90bba97e9..000000000 --- a/egs/aishell/branchformer/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Branchformer Result - -## Training Config -- Feature info: using raw speech, extracting 80 dims fbank online, global cmvn, speed perturb(0.9, 1.0, 1.1), specaugment -- Train info: lr 0.001, batch_size 10000, 4 gpu(Tesla V100), acc_grad 1, 180 epochs -- Train config: conf/train_asr_branchformer.yaml -- LM config: LM was not used - -## Results (CER) -- Decode config: conf/decode_asr_transformer.yaml (ctc weight:0.4) - -| testset | CER(%) | -|:-----------:|:-------:| -| dev | 4.15 | -| test | 4.51 | \ No newline at end of file diff --git a/egs/aishell/branchformer/conf/decode_asr_transformer.yaml b/egs/aishell/branchformer/conf/decode_asr_transformer.yaml deleted file mode 100644 index e87a2937f..000000000 --- a/egs/aishell/branchformer/conf/decode_asr_transformer.yaml +++ /dev/null @@ -1,6 +0,0 @@ -beam_size: 10 -penalty: 0.0 -maxlenratio: 0.0 -minlenratio: 0.0 -ctc_weight: 0.4 -lm_weight: 0.0 diff --git a/egs/aishell/branchformer/conf/train_asr_branchformer.yaml b/egs/aishell/branchformer/conf/train_asr_branchformer.yaml deleted file mode 100644 index f35c89706..000000000 --- a/egs/aishell/branchformer/conf/train_asr_branchformer.yaml +++ /dev/null @@ -1,104 +0,0 @@ -# network architecture -# encoder related -encoder: branchformer -encoder_conf: - output_size: 256 - use_attn: true - attention_heads: 4 - attention_layer_type: rel_selfattn - pos_enc_layer_type: rel_pos - rel_pos_type: latest - use_cgmlp: true - cgmlp_linear_units: 2048 - cgmlp_conv_kernel: 31 - use_linear_after_conv: false - gate_activation: identity - merge_method: concat - cgmlp_weight: 0.5 # used only if merge_method is "fixed_ave" - attn_branch_drop_rate: 0.0 # used only if merge_method is "learned_ave" - num_blocks: 24 - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - attention_dropout_rate: 0.1 - input_layer: conv2d - stochastic_depth_rate: 0.0 - -# decoder related -decoder: transformer -decoder_conf: - attention_heads: 4 - linear_units: 2048 - num_blocks: 6 - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - self_attention_dropout_rate: 0. - src_attention_dropout_rate: 0. - -# frontend related -frontend: wav_frontend -frontend_conf: - fs: 16000 - window: hamming - n_mels: 80 - frame_length: 25 - frame_shift: 10 - lfr_m: 1 - lfr_n: 1 - -# hybrid CTC/attention -model_conf: - ctc_weight: 0.3 - lsm_weight: 0.1 # label smoothing option - length_normalized_loss: false - -# optimization related -accum_grad: 1 -grad_clip: 5 -max_epoch: 180 -val_scheduler_criterion: - - valid - - acc -best_model_criterion: -- - valid - - acc - - max -keep_nbest_models: 10 - -optim: adam -optim_conf: - lr: 0.001 - weight_decay: 0.000001 -scheduler: warmuplr -scheduler_conf: - warmup_steps: 35000 - -specaug: specaug -specaug_conf: - apply_time_warp: true - time_warp_window: 5 - time_warp_mode: bicubic - apply_freq_mask: true - freq_mask_width_range: - - 0 - - 27 - num_freq_mask: 2 - apply_time_mask: true - time_mask_width_ratio_range: - - 0. - - 0.05 - num_time_mask: 10 - -dataset_conf: - data_names: speech,text - data_types: sound,text - shuffle: True - shuffle_conf: - shuffle_size: 2048 - sort_size: 500 - batch_conf: - batch_type: token - batch_size: 10000 - num_workers: 8 - -log_interval: 50 -normalize: None \ No newline at end of file diff --git a/egs/aishell/branchformer/local/aishell_data_prep.sh b/egs/aishell/branchformer/local/aishell_data_prep.sh deleted file mode 100755 index 83f489b3c..000000000 --- a/egs/aishell/branchformer/local/aishell_data_prep.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash - -# Copyright 2017 Xingyu Na -# Apache 2.0 - -#. ./path.sh || exit 1; - -if [ $# != 3 ]; then - echo "Usage: $0 " - echo " $0 /export/a05/xna/data/data_aishell/wav /export/a05/xna/data/data_aishell/transcript data" - exit 1; -fi - -aishell_audio_dir=$1 -aishell_text=$2/aishell_transcript_v0.8.txt -output_dir=$3 - -train_dir=$output_dir/data/local/train -dev_dir=$output_dir/data/local/dev -test_dir=$output_dir/data/local/test -tmp_dir=$output_dir/data/local/tmp - -mkdir -p $train_dir -mkdir -p $dev_dir -mkdir -p $test_dir -mkdir -p $tmp_dir - -# data directory check -if [ ! -d $aishell_audio_dir ] || [ ! -f $aishell_text ]; then - echo "Error: $0 requires two directory arguments" - exit 1; -fi - -# find wav audio file for train, dev and test resp. -find $aishell_audio_dir -iname "*.wav" > $tmp_dir/wav.flist -n=`cat $tmp_dir/wav.flist | wc -l` -[ $n -ne 141925 ] && \ - echo Warning: expected 141925 data data files, found $n - -grep -i "wav/train" $tmp_dir/wav.flist > $train_dir/wav.flist || exit 1; -grep -i "wav/dev" $tmp_dir/wav.flist > $dev_dir/wav.flist || exit 1; -grep -i "wav/test" $tmp_dir/wav.flist > $test_dir/wav.flist || exit 1; - -rm -r $tmp_dir - -# Transcriptions preparation -for dir in $train_dir $dev_dir $test_dir; do - echo Preparing $dir transcriptions - sed -e 's/\.wav//' $dir/wav.flist | awk -F '/' '{print $NF}' > $dir/utt.list - paste -d' ' $dir/utt.list $dir/wav.flist > $dir/wav.scp_all - utils/filter_scp.pl -f 1 $dir/utt.list $aishell_text > $dir/transcripts.txt - awk '{print $1}' $dir/transcripts.txt > $dir/utt.list - utils/filter_scp.pl -f 1 $dir/utt.list $dir/wav.scp_all | sort -u > $dir/wav.scp - sort -u $dir/transcripts.txt > $dir/text -done - -mkdir -p $output_dir/data/train $output_dir/data/dev $output_dir/data/test - -for f in wav.scp text; do - cp $train_dir/$f $output_dir/data/train/$f || exit 1; - cp $dev_dir/$f $output_dir/data/dev/$f || exit 1; - cp $test_dir/$f $output_dir/data/test/$f || exit 1; -done - -echo "$0: AISHELL data preparation succeeded" -exit 0; diff --git a/egs/aishell/branchformer/local/download_and_untar.sh b/egs/aishell/branchformer/local/download_and_untar.sh deleted file mode 100755 index d98255915..000000000 --- a/egs/aishell/branchformer/local/download_and_untar.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2014 Johns Hopkins University (author: Daniel Povey) -# 2017 Xingyu Na -# Apache 2.0 - -remove_archive=false - -if [ "$1" == --remove-archive ]; then - remove_archive=true - shift -fi - -if [ $# -ne 3 ]; then - echo "Usage: $0 [--remove-archive] " - echo "e.g.: $0 /export/a05/xna/data www.openslr.org/resources/33 data_aishell" - echo "With --remove-archive it will remove the archive after successfully un-tarring it." - echo " can be one of: data_aishell, resource_aishell." -fi - -data=$1 -url=$2 -part=$3 - -if [ ! -d "$data" ]; then - echo "$0: no such directory $data" - exit 1; -fi - -part_ok=false -list="data_aishell resource_aishell" -for x in $list; do - if [ "$part" == $x ]; then part_ok=true; fi -done -if ! $part_ok; then - echo "$0: expected to be one of $list, but got '$part'" - exit 1; -fi - -if [ -z "$url" ]; then - echo "$0: empty URL base." - exit 1; -fi - -if [ -f $data/$part/.complete ]; then - echo "$0: data part $part was already successfully extracted, nothing to do." - exit 0; -fi - -# sizes of the archive files in bytes. -sizes="15582913665 1246920" - -if [ -f $data/$part.tgz ]; then - size=$(/bin/ls -l $data/$part.tgz | awk '{print $5}') - size_ok=false - for s in $sizes; do if [ $s == $size ]; then size_ok=true; fi; done - if ! $size_ok; then - echo "$0: removing existing file $data/$part.tgz because its size in bytes $size" - echo "does not equal the size of one of the archives." - rm $data/$part.tgz - else - echo "$data/$part.tgz exists and appears to be complete." - fi -fi - -if [ ! -f $data/$part.tgz ]; then - if ! command -v wget >/dev/null; then - echo "$0: wget is not installed." - exit 1; - fi - full_url=$url/$part.tgz - echo "$0: downloading data from $full_url. This may take some time, please be patient." - - cd $data || exit 1 - if ! wget --no-check-certificate $full_url; then - echo "$0: error executing wget $full_url" - exit 1; - fi -fi - -cd $data || exit 1 - -if ! tar -xvzf $part.tgz; then - echo "$0: error un-tarring archive $data/$part.tgz" - exit 1; -fi - -touch $data/$part/.complete - -if [ $part == "data_aishell" ]; then - cd $data/$part/wav || exit 1 - for wav in ./*.tar.gz; do - echo "Extracting wav from $wav" - tar -zxf $wav && rm $wav - done -fi - -echo "$0: Successfully downloaded and un-tarred $data/$part.tgz" - -if $remove_archive; then - echo "$0: removing $data/$part.tgz file since --remove-archive option was supplied." - rm $data/$part.tgz -fi - -exit 0; diff --git a/egs/aishell/branchformer/path.sh b/egs/aishell/branchformer/path.sh deleted file mode 100755 index 7972642d0..000000000 --- a/egs/aishell/branchformer/path.sh +++ /dev/null @@ -1,5 +0,0 @@ -export FUNASR_DIR=$PWD/../../.. - -# NOTE(kan-bayashi): Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C -export PYTHONIOENCODING=UTF-8 -export PATH=$FUNASR_DIR/funasr/bin:$PATH diff --git a/egs/aishell/branchformer/run.sh b/egs/aishell/branchformer/run.sh deleted file mode 100755 index 6bb4a0cc5..000000000 --- a/egs/aishell/branchformer/run.sh +++ /dev/null @@ -1,225 +0,0 @@ -#!/usr/bin/env bash - -. ./path.sh || exit 1; - -# machines configuration -CUDA_VISIBLE_DEVICES="0,1,2,3" -gpu_num=4 -count=1 -gpu_inference=true # Whether to perform gpu decoding, set false for cpu decoding -# for gpu decoding, inference_nj=ngpu*njob; for cpu decoding, inference_nj=njob -njob=5 -train_cmd=utils/run.pl -infer_cmd=utils/run.pl - -# general configuration -feats_dir="../DATA" #feature output dictionary -exp_dir="." -lang=zh -token_type=char -type=sound -scp=wav.scp -speed_perturb="0.9 1.0 1.1" -stage=0 -stop_stage=5 - -# feature configuration -feats_dim=80 -nj=64 - -# data -raw_data=../raw_data -data_url=www.openslr.org/resources/33 - -# exp tag -tag="exp1" - -. utils/parse_options.sh || exit 1; - -# Set bash to 'debug' mode, it will exit on : -# -e 'error', -u 'undefined variable', -o ... 'error in pipeline', -x 'print commands', -set -e -set -u -set -o pipefail - -train_set=train -valid_set=dev -test_sets="dev test" - -asr_config=conf/train_asr_branchformer.yaml -model_dir="baseline_$(basename "${asr_config}" .yaml)_${lang}_${token_type}_${tag}" - -inference_config=conf/decode_asr_transformer.yaml -inference_asr_model=valid.acc.ave_10best.pb - -# you can set gpu num for decoding here -gpuid_list=$CUDA_VISIBLE_DEVICES # set gpus for decoding, the same as training stage by default -ngpu=$(echo $gpuid_list | awk -F "," '{print NF}') - -if ${gpu_inference}; then - inference_nj=$[${ngpu}*${njob}] - _ngpu=1 -else - inference_nj=$njob - _ngpu=0 -fi - -if [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then - echo "stage -1: Data Download" - local/download_and_untar.sh ${raw_data} ${data_url} data_aishell - local/download_and_untar.sh ${raw_data} ${data_url} resource_aishell -fi - -if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then - echo "stage 0: Data preparation" - # Data preparation - local/aishell_data_prep.sh ${raw_data}/data_aishell/wav ${raw_data}/data_aishell/transcript ${feats_dir} - for x in train dev test; do - cp ${feats_dir}/data/${x}/text ${feats_dir}/data/${x}/text.org - paste -d " " <(cut -f 1 -d" " ${feats_dir}/data/${x}/text.org) <(cut -f 2- -d" " ${feats_dir}/data/${x}/text.org | tr -d " ") \ - > ${feats_dir}/data/${x}/text - utils/text2token.py -n 1 -s 1 ${feats_dir}/data/${x}/text > ${feats_dir}/data/${x}/text.org - mv ${feats_dir}/data/${x}/text.org ${feats_dir}/data/${x}/text - done -fi - -if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then - echo "stage 1: Feature and CMVN Generation" - utils/compute_cmvn.sh --fbankdir ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config_file "$asr_config" --scale 1.0 -fi - -token_list=${feats_dir}/data/${lang}_token_list/$token_type/tokens.txt -echo "dictionary: ${token_list}" -if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then - echo "stage 2: Dictionary Preparation" - mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/ - - echo "make a dictionary" - echo "" > ${token_list} - echo "" >> ${token_list} - echo "" >> ${token_list} - utils/text2token.py -s 1 -n 1 --space "" ${feats_dir}/data/$train_set/text | cut -f 2- -d" " | tr " " "\n" \ - | sort | uniq | grep -a -v -e '^\s*$' | awk '{print $0}' >> ${token_list} - echo "" >> ${token_list} -fi - -# LM Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then - echo "stage 3: LM Training" -fi - -# ASR Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then - echo "stage 4: ASR Training" - mkdir -p ${exp_dir}/exp/${model_dir} - mkdir -p ${exp_dir}/exp/${model_dir}/log - INIT_FILE=${exp_dir}/exp/${model_dir}/ddp_init - if [ -f $INIT_FILE ];then - rm -f $INIT_FILE - fi - init_method=file://$(readlink -f $INIT_FILE) - echo "$0: init method is $init_method" - for ((i = 0; i < $gpu_num; ++i)); do - { - rank=$i - local_rank=$i - gpu_id=$(echo $CUDA_VISIBLE_DEVICES | cut -d',' -f$[$i+1]) - train.py \ - --task_name asr \ - --gpu_id $gpu_id \ - --use_preprocessor true \ - --token_type $token_type \ - --token_list $token_list \ - --data_dir ${feats_dir}/data \ - --train_set ${train_set} \ - --valid_set ${valid_set} \ - --data_file_names "wav.scp,text" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --speed_perturb ${speed_perturb} \ - --resume true \ - --output_dir ${exp_dir}/exp/${model_dir} \ - --config $asr_config \ - --ngpu $gpu_num \ - --num_worker_count $count \ - --dist_init_method $init_method \ - --dist_world_size $world_size \ - --dist_rank $rank \ - --local_rank $local_rank 1> ${exp_dir}/exp/${model_dir}/log/train.log.$i 2>&1 - } & - done - wait -fi - -# Testing Stage -if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then - echo "stage 5: Inference" - for dset in ${test_sets}; do - asr_exp=${exp_dir}/exp/${model_dir} - inference_tag="$(basename "${inference_config}" .yaml)" - _dir="${asr_exp}/${inference_tag}/${inference_asr_model}/${dset}" - _logdir="${_dir}/logdir" - if [ -d ${_dir} ]; then - echo "${_dir} is already exists. if you want to decode again, please delete this dir first." - exit 0 - fi - mkdir -p "${_logdir}" - _data="${feats_dir}/data/${dset}" - key_file=${_data}/${scp} - num_scp_file="$(<${key_file} wc -l)" - _nj=$([ $inference_nj -le $num_scp_file ] && echo "$inference_nj" || echo "$num_scp_file") - split_scps= - for n in $(seq "${_nj}"); do - split_scps+=" ${_logdir}/keys.${n}.scp" - done - # shellcheck disable=SC2086 - utils/split_scp.pl "${key_file}" ${split_scps} - _opts= - if [ -n "${inference_config}" ]; then - _opts+="--config ${inference_config} " - fi - ${infer_cmd} --gpu "${_ngpu}" --max-jobs-run "${_nj}" JOB=1:"${_nj}" "${_logdir}"/asr_inference.JOB.log \ - python -m funasr.bin.asr_inference_launch \ - --batch_size 1 \ - --ngpu "${_ngpu}" \ - --njob ${njob} \ - --gpuid_list ${gpuid_list} \ - --data_path_and_name_and_type "${_data}/${scp},speech,${type}" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --key_file "${_logdir}"/keys.JOB.scp \ - --asr_train_config "${asr_exp}"/config.yaml \ - --asr_model_file "${asr_exp}"/"${inference_asr_model}" \ - --output_dir "${_logdir}"/output.JOB \ - --mode asr \ - ${_opts} - - for f in token token_int score text; do - if [ -f "${_logdir}/output.1/1best_recog/${f}" ]; then - for i in $(seq "${_nj}"); do - cat "${_logdir}/output.${i}/1best_recog/${f}" - done | sort -k1 >"${_dir}/${f}" - fi - done - python utils/proce_text.py ${_dir}/text ${_dir}/text.proc - python utils/proce_text.py ${_data}/text ${_data}/text.proc - python utils/compute_wer.py ${_data}/text.proc ${_dir}/text.proc ${_dir}/text.cer - tail -n 3 ${_dir}/text.cer > ${_dir}/text.cer.txt - cat ${_dir}/text.cer.txt - done -fi - -# Prepare files for ModelScope fine-tuning and inference -if [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then - echo "stage 6: ModelScope Preparation" - cp ${feats_dir}/data/${train_set}/cmvn/am.mvn ${exp_dir}/exp/${model_dir}/am.mvn - vocab_size=$(cat ${token_list} | wc -l) - python utils/gen_modelscope_configuration.py \ - --am_model_name $inference_asr_model \ - --mode asr \ - --model_name conformer \ - --dataset aishell \ - --output_dir $exp_dir/exp/$model_dir \ - --vocab_size $vocab_size \ - --tag $tag -fi \ No newline at end of file diff --git a/egs/aishell/branchformer/utils b/egs/aishell/branchformer/utils deleted file mode 120000 index 4072eacc1..000000000 --- a/egs/aishell/branchformer/utils +++ /dev/null @@ -1 +0,0 @@ -../transformer/utils \ No newline at end of file diff --git a/egs/aishell/conformer/README.md b/egs/aishell/conformer/README.md deleted file mode 100644 index a67b183ed..000000000 --- a/egs/aishell/conformer/README.md +++ /dev/null @@ -1,17 +0,0 @@ - -# Conformer Result - -## Training Config -- Feature info: using 80 dims fbank, global cmvn, speed perturb(0.9, 1.0, 1.1), specaugment -- Train info: lr 5e-4, batch_size 25000, 2 gpu(Tesla V100), acc_grad 1, 50 epochs -- Train config: conf/train_asr_transformer.yaml -- LM config: LM was not used -- Model size: 46M - -## Results (CER) -- Decode config: conf/decode_asr_transformer.yaml (ctc weight:0.5) - -| testset | CER(%) | -|:-----------:|:-------:| -| dev | 4.42 | -| test | 4.87 | \ No newline at end of file diff --git a/egs/aishell/conformer/conf/decode_asr_transformer.yaml b/egs/aishell/conformer/conf/decode_asr_transformer.yaml deleted file mode 100644 index a147fa79d..000000000 --- a/egs/aishell/conformer/conf/decode_asr_transformer.yaml +++ /dev/null @@ -1,6 +0,0 @@ -beam_size: 10 -penalty: 0.0 -maxlenratio: 0.0 -minlenratio: 0.0 -ctc_weight: 0.5 -lm_weight: 0.7 diff --git a/egs/aishell/conformer/conf/train_asr_conformer.yaml b/egs/aishell/conformer/conf/train_asr_conformer.yaml deleted file mode 100644 index 4814ee739..000000000 --- a/egs/aishell/conformer/conf/train_asr_conformer.yaml +++ /dev/null @@ -1,98 +0,0 @@ -# network architecture -# encoder related -encoder: conformer -encoder_conf: - output_size: 256 # dimension of attention - attention_heads: 4 - linear_units: 2048 # the number of units of position-wise feed forward - num_blocks: 12 # the number of encoder blocks - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - attention_dropout_rate: 0.0 - input_layer: conv2d # encoder architecture type - normalize_before: true - pos_enc_layer_type: rel_pos - selfattention_layer_type: rel_selfattn - activation_type: swish - macaron_style: true - use_cnn_module: true - cnn_module_kernel: 15 - -# decoder related -decoder: transformer -decoder_conf: - attention_heads: 4 - linear_units: 2048 - num_blocks: 6 - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - self_attention_dropout_rate: 0.0 - src_attention_dropout_rate: 0.0 - -# frontend related -frontend: wav_frontend -frontend_conf: - fs: 16000 - window: hamming - n_mels: 80 - frame_length: 25 - frame_shift: 10 - lfr_m: 1 - lfr_n: 1 - -# hybrid CTC/attention -model_conf: - ctc_weight: 0.3 - lsm_weight: 0.1 # label smoothing option - length_normalized_loss: false - -# optimization related -accum_grad: 1 -grad_clip: 5 -max_epoch: 150 -val_scheduler_criterion: - - valid - - acc -best_model_criterion: -- - valid - - acc - - max -keep_nbest_models: 10 - -optim: adam -optim_conf: - lr: 0.0005 -scheduler: warmuplr -scheduler_conf: - warmup_steps: 30000 - -specaug: specaug -specaug_conf: - apply_time_warp: true - time_warp_window: 5 - time_warp_mode: bicubic - apply_freq_mask: true - freq_mask_width_range: - - 0 - - 30 - num_freq_mask: 2 - apply_time_mask: true - time_mask_width_range: - - 0 - - 40 - num_time_mask: 2 - -dataset_conf: - data_names: speech,text - data_types: sound,text - shuffle: True - shuffle_conf: - shuffle_size: 2048 - sort_size: 500 - batch_conf: - batch_type: token - batch_size: 25000 - num_workers: 8 - -log_interval: 50 -normalize: None \ No newline at end of file diff --git a/egs/aishell/conformer/local/aishell_data_prep.sh b/egs/aishell/conformer/local/aishell_data_prep.sh deleted file mode 100755 index 83f489b3c..000000000 --- a/egs/aishell/conformer/local/aishell_data_prep.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash - -# Copyright 2017 Xingyu Na -# Apache 2.0 - -#. ./path.sh || exit 1; - -if [ $# != 3 ]; then - echo "Usage: $0 " - echo " $0 /export/a05/xna/data/data_aishell/wav /export/a05/xna/data/data_aishell/transcript data" - exit 1; -fi - -aishell_audio_dir=$1 -aishell_text=$2/aishell_transcript_v0.8.txt -output_dir=$3 - -train_dir=$output_dir/data/local/train -dev_dir=$output_dir/data/local/dev -test_dir=$output_dir/data/local/test -tmp_dir=$output_dir/data/local/tmp - -mkdir -p $train_dir -mkdir -p $dev_dir -mkdir -p $test_dir -mkdir -p $tmp_dir - -# data directory check -if [ ! -d $aishell_audio_dir ] || [ ! -f $aishell_text ]; then - echo "Error: $0 requires two directory arguments" - exit 1; -fi - -# find wav audio file for train, dev and test resp. -find $aishell_audio_dir -iname "*.wav" > $tmp_dir/wav.flist -n=`cat $tmp_dir/wav.flist | wc -l` -[ $n -ne 141925 ] && \ - echo Warning: expected 141925 data data files, found $n - -grep -i "wav/train" $tmp_dir/wav.flist > $train_dir/wav.flist || exit 1; -grep -i "wav/dev" $tmp_dir/wav.flist > $dev_dir/wav.flist || exit 1; -grep -i "wav/test" $tmp_dir/wav.flist > $test_dir/wav.flist || exit 1; - -rm -r $tmp_dir - -# Transcriptions preparation -for dir in $train_dir $dev_dir $test_dir; do - echo Preparing $dir transcriptions - sed -e 's/\.wav//' $dir/wav.flist | awk -F '/' '{print $NF}' > $dir/utt.list - paste -d' ' $dir/utt.list $dir/wav.flist > $dir/wav.scp_all - utils/filter_scp.pl -f 1 $dir/utt.list $aishell_text > $dir/transcripts.txt - awk '{print $1}' $dir/transcripts.txt > $dir/utt.list - utils/filter_scp.pl -f 1 $dir/utt.list $dir/wav.scp_all | sort -u > $dir/wav.scp - sort -u $dir/transcripts.txt > $dir/text -done - -mkdir -p $output_dir/data/train $output_dir/data/dev $output_dir/data/test - -for f in wav.scp text; do - cp $train_dir/$f $output_dir/data/train/$f || exit 1; - cp $dev_dir/$f $output_dir/data/dev/$f || exit 1; - cp $test_dir/$f $output_dir/data/test/$f || exit 1; -done - -echo "$0: AISHELL data preparation succeeded" -exit 0; diff --git a/egs/aishell/conformer/local/download_and_untar.sh b/egs/aishell/conformer/local/download_and_untar.sh deleted file mode 100755 index d98255915..000000000 --- a/egs/aishell/conformer/local/download_and_untar.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2014 Johns Hopkins University (author: Daniel Povey) -# 2017 Xingyu Na -# Apache 2.0 - -remove_archive=false - -if [ "$1" == --remove-archive ]; then - remove_archive=true - shift -fi - -if [ $# -ne 3 ]; then - echo "Usage: $0 [--remove-archive] " - echo "e.g.: $0 /export/a05/xna/data www.openslr.org/resources/33 data_aishell" - echo "With --remove-archive it will remove the archive after successfully un-tarring it." - echo " can be one of: data_aishell, resource_aishell." -fi - -data=$1 -url=$2 -part=$3 - -if [ ! -d "$data" ]; then - echo "$0: no such directory $data" - exit 1; -fi - -part_ok=false -list="data_aishell resource_aishell" -for x in $list; do - if [ "$part" == $x ]; then part_ok=true; fi -done -if ! $part_ok; then - echo "$0: expected to be one of $list, but got '$part'" - exit 1; -fi - -if [ -z "$url" ]; then - echo "$0: empty URL base." - exit 1; -fi - -if [ -f $data/$part/.complete ]; then - echo "$0: data part $part was already successfully extracted, nothing to do." - exit 0; -fi - -# sizes of the archive files in bytes. -sizes="15582913665 1246920" - -if [ -f $data/$part.tgz ]; then - size=$(/bin/ls -l $data/$part.tgz | awk '{print $5}') - size_ok=false - for s in $sizes; do if [ $s == $size ]; then size_ok=true; fi; done - if ! $size_ok; then - echo "$0: removing existing file $data/$part.tgz because its size in bytes $size" - echo "does not equal the size of one of the archives." - rm $data/$part.tgz - else - echo "$data/$part.tgz exists and appears to be complete." - fi -fi - -if [ ! -f $data/$part.tgz ]; then - if ! command -v wget >/dev/null; then - echo "$0: wget is not installed." - exit 1; - fi - full_url=$url/$part.tgz - echo "$0: downloading data from $full_url. This may take some time, please be patient." - - cd $data || exit 1 - if ! wget --no-check-certificate $full_url; then - echo "$0: error executing wget $full_url" - exit 1; - fi -fi - -cd $data || exit 1 - -if ! tar -xvzf $part.tgz; then - echo "$0: error un-tarring archive $data/$part.tgz" - exit 1; -fi - -touch $data/$part/.complete - -if [ $part == "data_aishell" ]; then - cd $data/$part/wav || exit 1 - for wav in ./*.tar.gz; do - echo "Extracting wav from $wav" - tar -zxf $wav && rm $wav - done -fi - -echo "$0: Successfully downloaded and un-tarred $data/$part.tgz" - -if $remove_archive; then - echo "$0: removing $data/$part.tgz file since --remove-archive option was supplied." - rm $data/$part.tgz -fi - -exit 0; diff --git a/egs/aishell/conformer/path.sh b/egs/aishell/conformer/path.sh deleted file mode 100755 index 7972642d0..000000000 --- a/egs/aishell/conformer/path.sh +++ /dev/null @@ -1,5 +0,0 @@ -export FUNASR_DIR=$PWD/../../.. - -# NOTE(kan-bayashi): Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C -export PYTHONIOENCODING=UTF-8 -export PATH=$FUNASR_DIR/funasr/bin:$PATH diff --git a/egs/aishell/conformer/run.sh b/egs/aishell/conformer/run.sh deleted file mode 100755 index e8643e930..000000000 --- a/egs/aishell/conformer/run.sh +++ /dev/null @@ -1,225 +0,0 @@ -#!/usr/bin/env bash - -. ./path.sh || exit 1; - -# machines configuration -CUDA_VISIBLE_DEVICES="0,1" -gpu_num=2 -count=1 -gpu_inference=true # Whether to perform gpu decoding, set false for cpu decoding -# for gpu decoding, inference_nj=ngpu*njob; for cpu decoding, inference_nj=njob -njob=5 -train_cmd=utils/run.pl -infer_cmd=utils/run.pl - -# general configuration -feats_dir="../DATA" #feature output dictionary -exp_dir="." -lang=zh -token_type=char -type=sound -scp=wav.scp -speed_perturb="0.9 1.0 1.1" -stage=0 -stop_stage=5 - -# feature configuration -feats_dim=80 -nj=64 - -# data -raw_data=../raw_data -data_url=www.openslr.org/resources/33 - -# exp tag -tag="exp1" - -. utils/parse_options.sh || exit 1; - -# Set bash to 'debug' mode, it will exit on : -# -e 'error', -u 'undefined variable', -o ... 'error in pipeline', -x 'print commands', -set -e -set -u -set -o pipefail - -train_set=train -valid_set=dev -test_sets="dev test" - -asr_config=conf/train_asr_conformer.yaml -model_dir="baseline_$(basename "${asr_config}" .yaml)_${lang}_${token_type}_${tag}" - -inference_config=conf/decode_asr_transformer.yaml -inference_asr_model=valid.acc.ave_10best.pb - -# you can set gpu num for decoding here -gpuid_list=$CUDA_VISIBLE_DEVICES # set gpus for decoding, the same as training stage by default -ngpu=$(echo $gpuid_list | awk -F "," '{print NF}') - -if ${gpu_inference}; then - inference_nj=$[${ngpu}*${njob}] - _ngpu=1 -else - inference_nj=$njob - _ngpu=0 -fi - -if [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then - echo "stage -1: Data Download" - local/download_and_untar.sh ${raw_data} ${data_url} data_aishell - local/download_and_untar.sh ${raw_data} ${data_url} resource_aishell -fi - -if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then - echo "stage 0: Data preparation" - # Data preparation - local/aishell_data_prep.sh ${raw_data}/data_aishell/wav ${raw_data}/data_aishell/transcript ${feats_dir} - for x in train dev test; do - cp ${feats_dir}/data/${x}/text ${feats_dir}/data/${x}/text.org - paste -d " " <(cut -f 1 -d" " ${feats_dir}/data/${x}/text.org) <(cut -f 2- -d" " ${feats_dir}/data/${x}/text.org | tr -d " ") \ - > ${feats_dir}/data/${x}/text - utils/text2token.py -n 1 -s 1 ${feats_dir}/data/${x}/text > ${feats_dir}/data/${x}/text.org - mv ${feats_dir}/data/${x}/text.org ${feats_dir}/data/${x}/text - done -fi - -if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then - echo "stage 1: Feature and CMVN Generation" - utils/compute_cmvn.sh --fbankdir ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config_file "$asr_config" --scale 1.0 -fi - -token_list=${feats_dir}/data/${lang}_token_list/$token_type/tokens.txt -echo "dictionary: ${token_list}" -if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then - echo "stage 2: Dictionary Preparation" - mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/ - - echo "make a dictionary" - echo "" > ${token_list} - echo "" >> ${token_list} - echo "" >> ${token_list} - utils/text2token.py -s 1 -n 1 --space "" ${feats_dir}/data/$train_set/text | cut -f 2- -d" " | tr " " "\n" \ - | sort | uniq | grep -a -v -e '^\s*$' | awk '{print $0}' >> ${token_list} - echo "" >> ${token_list} -fi - -# LM Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then - echo "stage 3: LM Training" -fi - -# ASR Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then - echo "stage 4: ASR Training" - mkdir -p ${exp_dir}/exp/${model_dir} - mkdir -p ${exp_dir}/exp/${model_dir}/log - INIT_FILE=${exp_dir}/exp/${model_dir}/ddp_init - if [ -f $INIT_FILE ];then - rm -f $INIT_FILE - fi - init_method=file://$(readlink -f $INIT_FILE) - echo "$0: init method is $init_method" - for ((i = 0; i < $gpu_num; ++i)); do - { - rank=$i - local_rank=$i - gpu_id=$(echo $CUDA_VISIBLE_DEVICES | cut -d',' -f$[$i+1]) - train.py \ - --task_name asr \ - --gpu_id $gpu_id \ - --use_preprocessor true \ - --token_type $token_type \ - --token_list $token_list \ - --data_dir ${feats_dir}/data \ - --train_set ${train_set} \ - --valid_set ${valid_set} \ - --data_file_names "wav.scp,text" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --speed_perturb ${speed_perturb} \ - --resume true \ - --output_dir ${exp_dir}/exp/${model_dir} \ - --config $asr_config \ - --ngpu $gpu_num \ - --num_worker_count $count \ - --dist_init_method $init_method \ - --dist_world_size $world_size \ - --dist_rank $rank \ - --local_rank $local_rank 1> ${exp_dir}/exp/${model_dir}/log/train.log.$i 2>&1 - } & - done - wait -fi - -# Testing Stage -if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then - echo "stage 5: Inference" - for dset in ${test_sets}; do - asr_exp=${exp_dir}/exp/${model_dir} - inference_tag="$(basename "${inference_config}" .yaml)" - _dir="${asr_exp}/${inference_tag}/${inference_asr_model}/${dset}" - _logdir="${_dir}/logdir" - if [ -d ${_dir} ]; then - echo "${_dir} is already exists. if you want to decode again, please delete this dir first." - exit 0 - fi - mkdir -p "${_logdir}" - _data="${feats_dir}/data/${dset}" - key_file=${_data}/${scp} - num_scp_file="$(<${key_file} wc -l)" - _nj=$([ $inference_nj -le $num_scp_file ] && echo "$inference_nj" || echo "$num_scp_file") - split_scps= - for n in $(seq "${_nj}"); do - split_scps+=" ${_logdir}/keys.${n}.scp" - done - # shellcheck disable=SC2086 - utils/split_scp.pl "${key_file}" ${split_scps} - _opts= - if [ -n "${inference_config}" ]; then - _opts+="--config ${inference_config} " - fi - ${infer_cmd} --gpu "${_ngpu}" --max-jobs-run "${_nj}" JOB=1:"${_nj}" "${_logdir}"/asr_inference.JOB.log \ - python -m funasr.bin.asr_inference_launch \ - --batch_size 1 \ - --ngpu "${_ngpu}" \ - --njob ${njob} \ - --gpuid_list ${gpuid_list} \ - --data_path_and_name_and_type "${_data}/${scp},speech,${type}" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --key_file "${_logdir}"/keys.JOB.scp \ - --asr_train_config "${asr_exp}"/config.yaml \ - --asr_model_file "${asr_exp}"/"${inference_asr_model}" \ - --output_dir "${_logdir}"/output.JOB \ - --mode asr \ - ${_opts} - - for f in token token_int score text; do - if [ -f "${_logdir}/output.1/1best_recog/${f}" ]; then - for i in $(seq "${_nj}"); do - cat "${_logdir}/output.${i}/1best_recog/${f}" - done | sort -k1 >"${_dir}/${f}" - fi - done - python utils/proce_text.py ${_dir}/text ${_dir}/text.proc - python utils/proce_text.py ${_data}/text ${_data}/text.proc - python utils/compute_wer.py ${_data}/text.proc ${_dir}/text.proc ${_dir}/text.cer - tail -n 3 ${_dir}/text.cer > ${_dir}/text.cer.txt - cat ${_dir}/text.cer.txt - done -fi - -# Prepare files for ModelScope fine-tuning and inference -if [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then - echo "stage 6: ModelScope Preparation" - cp ${feats_dir}/data/${train_set}/cmvn/am.mvn ${exp_dir}/exp/${model_dir}/am.mvn - vocab_size=$(cat ${token_list} | wc -l) - python utils/gen_modelscope_configuration.py \ - --am_model_name $inference_asr_model \ - --mode asr \ - --model_name conformer \ - --dataset aishell \ - --output_dir $exp_dir/exp/$model_dir \ - --vocab_size $vocab_size \ - --tag $tag -fi \ No newline at end of file diff --git a/egs/aishell/conformer/utils b/egs/aishell/conformer/utils deleted file mode 120000 index 0853fce5d..000000000 --- a/egs/aishell/conformer/utils +++ /dev/null @@ -1 +0,0 @@ -../transformer/utils/ \ No newline at end of file diff --git a/egs/aishell/data2vec_paraformer_finetune/conf/decode_asr_transformer_noctc_1best.yaml b/egs/aishell/data2vec_paraformer_finetune/conf/decode_asr_transformer_noctc_1best.yaml deleted file mode 100644 index 5436b12e4..000000000 --- a/egs/aishell/data2vec_paraformer_finetune/conf/decode_asr_transformer_noctc_1best.yaml +++ /dev/null @@ -1,6 +0,0 @@ -beam_size: 1 -penalty: 0.0 -maxlenratio: 0.0 -minlenratio: 0.0 -ctc_weight: 0.0 -lm_weight: 0.15 diff --git a/egs/aishell/data2vec_paraformer_finetune/conf/train_asr_paraformer_transformer_12e_6d_3072_768.yaml b/egs/aishell/data2vec_paraformer_finetune/conf/train_asr_paraformer_transformer_12e_6d_3072_768.yaml deleted file mode 100644 index 1e1acee21..000000000 --- a/egs/aishell/data2vec_paraformer_finetune/conf/train_asr_paraformer_transformer_12e_6d_3072_768.yaml +++ /dev/null @@ -1,121 +0,0 @@ -# network architecture -# encoder related -encoder: data2vec_encoder -encoder_conf: - extractor_mode: layer_norm - encoder_layerdrop: 0.1 - dropout_input: 0.0 - dropout_features: 0.0 - feature_grad_mult: 0.0 - encoder_embed_dim: 768 - - mask_prob: 0.65 - mask_length: 10 - - loss_beta: 0 - loss_scale: null - - instance_norm_target_layer: true - average_top_k_layers: 8 - - pos_conv_depth: 5 - conv_pos: 95 - - ema_decay: 0.999 - ema_end_decay: 0.9999 - ema_anneal_end_step: 30000 - ema_transformer_only: true - ema_layers_only: true - - require_same_masks: true - mask_dropout: 0 - -# decoder related -decoder: paraformer_decoder_san -decoder_conf: - attention_heads: 12 - linear_units: 3072 - num_blocks: 6 - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - self_attention_dropout_rate: 0.0 - src_attention_dropout_rate: 0.0 - -# frontend related -frontend: wav_frontend -frontend_conf: - fs: 16000 - window: hamming - n_mels: 80 - frame_length: 25 - frame_shift: 10 - lfr_m: 1 - lfr_n: 1 - -# hybrid CTC/attention -model: paraformer -model_conf: - ctc_weight: 0.3 - lsm_weight: 0.1 - length_normalized_loss: false - predictor_weight: 1.0 - sampling_ratio: 0.4 - -# optimization related -accum_grad: 1 -grad_clip: 5 -max_epoch: 150 -val_scheduler_criterion: - - valid - - acc -best_model_criterion: -- - valid - - acc - - max -keep_nbest_models: 10 - -optim: adam -optim_conf: - lr: 0.00002 -scheduler: warmuplr -scheduler_conf: - warmup_steps: 30000 - -specaug: specaug -specaug_conf: - apply_time_warp: true - time_warp_window: 5 - time_warp_mode: bicubic - apply_freq_mask: true - freq_mask_width_range: - - 0 - - 30 - num_freq_mask: 2 - apply_time_mask: true - time_mask_width_range: - - 0 - - 40 - num_time_mask: 2 - -predictor: cif_predictor -predictor_conf: - idim: 768 - threshold: 1.0 - l_order: 1 - r_order: 1 - -dataset_conf: - data_names: speech,text - data_types: sound,text - shuffle: True - shuffle_conf: - shuffle_size: 2048 - sort_size: 500 - batch_conf: - batch_type: token - batch_size: 25000 - num_workers: 8 - -log_interval: 50 -unused_parameters: true -normalize: None \ No newline at end of file diff --git a/egs/aishell/data2vec_paraformer_finetune/local/aishell_data_prep.sh b/egs/aishell/data2vec_paraformer_finetune/local/aishell_data_prep.sh deleted file mode 100755 index 83f489b3c..000000000 --- a/egs/aishell/data2vec_paraformer_finetune/local/aishell_data_prep.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash - -# Copyright 2017 Xingyu Na -# Apache 2.0 - -#. ./path.sh || exit 1; - -if [ $# != 3 ]; then - echo "Usage: $0 " - echo " $0 /export/a05/xna/data/data_aishell/wav /export/a05/xna/data/data_aishell/transcript data" - exit 1; -fi - -aishell_audio_dir=$1 -aishell_text=$2/aishell_transcript_v0.8.txt -output_dir=$3 - -train_dir=$output_dir/data/local/train -dev_dir=$output_dir/data/local/dev -test_dir=$output_dir/data/local/test -tmp_dir=$output_dir/data/local/tmp - -mkdir -p $train_dir -mkdir -p $dev_dir -mkdir -p $test_dir -mkdir -p $tmp_dir - -# data directory check -if [ ! -d $aishell_audio_dir ] || [ ! -f $aishell_text ]; then - echo "Error: $0 requires two directory arguments" - exit 1; -fi - -# find wav audio file for train, dev and test resp. -find $aishell_audio_dir -iname "*.wav" > $tmp_dir/wav.flist -n=`cat $tmp_dir/wav.flist | wc -l` -[ $n -ne 141925 ] && \ - echo Warning: expected 141925 data data files, found $n - -grep -i "wav/train" $tmp_dir/wav.flist > $train_dir/wav.flist || exit 1; -grep -i "wav/dev" $tmp_dir/wav.flist > $dev_dir/wav.flist || exit 1; -grep -i "wav/test" $tmp_dir/wav.flist > $test_dir/wav.flist || exit 1; - -rm -r $tmp_dir - -# Transcriptions preparation -for dir in $train_dir $dev_dir $test_dir; do - echo Preparing $dir transcriptions - sed -e 's/\.wav//' $dir/wav.flist | awk -F '/' '{print $NF}' > $dir/utt.list - paste -d' ' $dir/utt.list $dir/wav.flist > $dir/wav.scp_all - utils/filter_scp.pl -f 1 $dir/utt.list $aishell_text > $dir/transcripts.txt - awk '{print $1}' $dir/transcripts.txt > $dir/utt.list - utils/filter_scp.pl -f 1 $dir/utt.list $dir/wav.scp_all | sort -u > $dir/wav.scp - sort -u $dir/transcripts.txt > $dir/text -done - -mkdir -p $output_dir/data/train $output_dir/data/dev $output_dir/data/test - -for f in wav.scp text; do - cp $train_dir/$f $output_dir/data/train/$f || exit 1; - cp $dev_dir/$f $output_dir/data/dev/$f || exit 1; - cp $test_dir/$f $output_dir/data/test/$f || exit 1; -done - -echo "$0: AISHELL data preparation succeeded" -exit 0; diff --git a/egs/aishell/data2vec_paraformer_finetune/local/download_and_untar.sh b/egs/aishell/data2vec_paraformer_finetune/local/download_and_untar.sh deleted file mode 100755 index d98255915..000000000 --- a/egs/aishell/data2vec_paraformer_finetune/local/download_and_untar.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2014 Johns Hopkins University (author: Daniel Povey) -# 2017 Xingyu Na -# Apache 2.0 - -remove_archive=false - -if [ "$1" == --remove-archive ]; then - remove_archive=true - shift -fi - -if [ $# -ne 3 ]; then - echo "Usage: $0 [--remove-archive] " - echo "e.g.: $0 /export/a05/xna/data www.openslr.org/resources/33 data_aishell" - echo "With --remove-archive it will remove the archive after successfully un-tarring it." - echo " can be one of: data_aishell, resource_aishell." -fi - -data=$1 -url=$2 -part=$3 - -if [ ! -d "$data" ]; then - echo "$0: no such directory $data" - exit 1; -fi - -part_ok=false -list="data_aishell resource_aishell" -for x in $list; do - if [ "$part" == $x ]; then part_ok=true; fi -done -if ! $part_ok; then - echo "$0: expected to be one of $list, but got '$part'" - exit 1; -fi - -if [ -z "$url" ]; then - echo "$0: empty URL base." - exit 1; -fi - -if [ -f $data/$part/.complete ]; then - echo "$0: data part $part was already successfully extracted, nothing to do." - exit 0; -fi - -# sizes of the archive files in bytes. -sizes="15582913665 1246920" - -if [ -f $data/$part.tgz ]; then - size=$(/bin/ls -l $data/$part.tgz | awk '{print $5}') - size_ok=false - for s in $sizes; do if [ $s == $size ]; then size_ok=true; fi; done - if ! $size_ok; then - echo "$0: removing existing file $data/$part.tgz because its size in bytes $size" - echo "does not equal the size of one of the archives." - rm $data/$part.tgz - else - echo "$data/$part.tgz exists and appears to be complete." - fi -fi - -if [ ! -f $data/$part.tgz ]; then - if ! command -v wget >/dev/null; then - echo "$0: wget is not installed." - exit 1; - fi - full_url=$url/$part.tgz - echo "$0: downloading data from $full_url. This may take some time, please be patient." - - cd $data || exit 1 - if ! wget --no-check-certificate $full_url; then - echo "$0: error executing wget $full_url" - exit 1; - fi -fi - -cd $data || exit 1 - -if ! tar -xvzf $part.tgz; then - echo "$0: error un-tarring archive $data/$part.tgz" - exit 1; -fi - -touch $data/$part/.complete - -if [ $part == "data_aishell" ]; then - cd $data/$part/wav || exit 1 - for wav in ./*.tar.gz; do - echo "Extracting wav from $wav" - tar -zxf $wav && rm $wav - done -fi - -echo "$0: Successfully downloaded and un-tarred $data/$part.tgz" - -if $remove_archive; then - echo "$0: removing $data/$part.tgz file since --remove-archive option was supplied." - rm $data/$part.tgz -fi - -exit 0; diff --git a/egs/aishell/data2vec_paraformer_finetune/path.sh b/egs/aishell/data2vec_paraformer_finetune/path.sh deleted file mode 100755 index 7972642d0..000000000 --- a/egs/aishell/data2vec_paraformer_finetune/path.sh +++ /dev/null @@ -1,5 +0,0 @@ -export FUNASR_DIR=$PWD/../../.. - -# NOTE(kan-bayashi): Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C -export PYTHONIOENCODING=UTF-8 -export PATH=$FUNASR_DIR/funasr/bin:$PATH diff --git a/egs/aishell/data2vec_paraformer_finetune/run.sh b/egs/aishell/data2vec_paraformer_finetune/run.sh deleted file mode 100755 index 1f96873fd..000000000 --- a/egs/aishell/data2vec_paraformer_finetune/run.sh +++ /dev/null @@ -1,231 +0,0 @@ -#!/usr/bin/env bash - -. ./path.sh || exit 1; - -# machines configuration -CUDA_VISIBLE_DEVICES="0,1" -gpu_num=2 -count=1 -gpu_inference=true # Whether to perform gpu decoding, set false for cpu decoding -# for gpu decoding, inference_nj=ngpu*njob; for cpu decoding, inference_nj=njob -njob=1 -train_cmd=utils/run.pl -infer_cmd=utils/run.pl - -# general configuration -feats_dir="../DATA" #feature output dictionary -exp_dir="." -lang=zh -token_type=char -type=sound -scp=wav.scp -speed_perturb="0.9 1.0 1.1" -stage=0 -stop_stage=5 - -# feature configuration -feats_dim=80 -nj=64 - -# data -raw_data=../raw_data -data_url=www.openslr.org/resources/33 - -# exp tag -tag="exp1" - -model_name=damo/speech_data2vec_pretrain-zh-cn-aishell2-16k-pytorch -init_param="$HOME/.cache/modelscope/hub/$model_name/basemodel.pb" - -. utils/parse_options.sh || exit 1; - -# Set bash to 'debug' mode, it will exit on : -# -e 'error', -u 'undefined variable', -o ... 'error in pipeline', -x 'print commands', -set -e -set -u -set -o pipefail - -train_set=train -valid_set=dev -test_sets="dev test" - -asr_config=conf/train_asr_paraformer_transformer_12e_6d_3072_768.yaml -model_dir="baseline_$(basename "${asr_config}" .yaml)_${lang}_${token_type}_${tag}" - -inference_config=conf/decode_asr_transformer_noctc_1best.yaml -inference_asr_model=valid.acc.ave_10best.pb - -# you can set gpu num for decoding here -gpuid_list=$CUDA_VISIBLE_DEVICES # set gpus for decoding, the same as training stage by default -ngpu=$(echo $gpuid_list | awk -F "," '{print NF}') - -if ${gpu_inference}; then - inference_nj=$[${ngpu}*${njob}] - _ngpu=1 -else - inference_nj=$njob - _ngpu=0 -fi - -if [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then - echo "stage -1: Data Download" - local/download_and_untar.sh ${raw_data} ${data_url} data_aishell - local/download_and_untar.sh ${raw_data} ${data_url} resource_aishell -fi - -if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then - echo "stage 0: Data preparation" - # Data preparation - local/aishell_data_prep.sh ${raw_data}/data_aishell/wav ${raw_data}/data_aishell/transcript ${feats_dir} - for x in train dev test; do - cp ${feats_dir}/data/${x}/text ${feats_dir}/data/${x}/text.org - paste -d " " <(cut -f 1 -d" " ${feats_dir}/data/${x}/text.org) <(cut -f 2- -d" " ${feats_dir}/data/${x}/text.org | tr -d " ") \ - > ${feats_dir}/data/${x}/text - utils/text2token.py -n 1 -s 1 ${feats_dir}/data/${x}/text > ${feats_dir}/data/${x}/text.org - mv ${feats_dir}/data/${x}/text.org ${feats_dir}/data/${x}/text - done -fi - -if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then - echo "stage 1: Feature and CMVN Generation" - utils/compute_cmvn.sh --fbankdir ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config_file "$asr_config" --scale 1.0 -fi - -token_list=${feats_dir}/data/${lang}_token_list/$token_type/tokens.txt -echo "dictionary: ${token_list}" -if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then - echo "stage 2: Dictionary Preparation" - mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/ - - echo "make a dictionary" - echo "" > ${token_list} - echo "" >> ${token_list} - echo "" >> ${token_list} - utils/text2token.py -s 1 -n 1 --space "" ${feats_dir}/data/$train_set/text | cut -f 2- -d" " | tr " " "\n" \ - | sort | uniq | grep -a -v -e '^\s*$' | awk '{print $0}' >> ${token_list} - echo "" >> ${token_list} -fi - -# LM Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then - echo "stage 3: LM Training" -fi - -# ASR Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then - echo "stage 4: ASR Training" - python utils/download_model.py --model_name ${model_name} # download pretrained model on ModelScope - mkdir -p ${exp_dir}/exp/${model_dir} - mkdir -p ${exp_dir}/exp/${model_dir}/log - INIT_FILE=${exp_dir}/exp/${model_dir}/ddp_init - if [ -f $INIT_FILE ];then - rm -f $INIT_FILE - fi - init_method=file://$(readlink -f $INIT_FILE) - echo "$0: init method is $init_method" - for ((i = 0; i < $gpu_num; ++i)); do - { - rank=$i - local_rank=$i - gpu_id=$(echo $CUDA_VISIBLE_DEVICES | cut -d',' -f$[$i+1]) - train.py \ - --task_name asr \ - --gpu_id $gpu_id \ - --use_preprocessor true \ - --token_type $token_type \ - --token_list $token_list \ - --data_dir ${feats_dir}/data \ - --train_set ${train_set} \ - --valid_set ${valid_set} \ - --data_file_names "wav.scp,text" \ - --init_param ${init_param} \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --resume true \ - --output_dir ${exp_dir}/exp/${model_dir} \ - --config $asr_config \ - --ngpu $gpu_num \ - --num_worker_count $count \ - --dist_init_method $init_method \ - --dist_world_size $world_size \ - --dist_rank $rank \ - --local_rank $local_rank 1> ${exp_dir}/exp/${model_dir}/log/train.log.$i 2>&1 - } & - done - wait -fi - -# Testing Stage -if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then - echo "stage 5: Inference" - for dset in ${test_sets}; do - asr_exp=${exp_dir}/exp/${model_dir} - inference_tag="$(basename "${inference_config}" .yaml)" - _dir="${asr_exp}/${inference_tag}/${inference_asr_model}/${dset}" - _logdir="${_dir}/logdir" - if [ -d ${_dir} ]; then - echo "${_dir} is already exists. if you want to decode again, please delete this dir first." - exit 0 - fi - mkdir -p "${_logdir}" - _data="${feats_dir}/data/${dset}" - key_file=${_data}/${scp} - num_scp_file="$(<${key_file} wc -l)" - _nj=$([ $inference_nj -le $num_scp_file ] && echo "$inference_nj" || echo "$num_scp_file") - split_scps= - for n in $(seq "${_nj}"); do - split_scps+=" ${_logdir}/keys.${n}.scp" - done - # shellcheck disable=SC2086 - utils/split_scp.pl "${key_file}" ${split_scps} - _opts= - if [ -n "${inference_config}" ]; then - _opts+="--config ${inference_config} " - fi - ${infer_cmd} --gpu "${_ngpu}" --max-jobs-run "${_nj}" JOB=1:"${_nj}" "${_logdir}"/asr_inference.JOB.log \ - python -m funasr.bin.asr_inference_launch \ - --batch_size 1 \ - --ngpu "${_ngpu}" \ - --njob ${njob} \ - --gpuid_list ${gpuid_list} \ - --data_path_and_name_and_type "${_data}/${scp},speech,${type}" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --speed_perturb ${speed_perturb} \ - --key_file "${_logdir}"/keys.JOB.scp \ - --asr_train_config "${asr_exp}"/config.yaml \ - --asr_model_file "${asr_exp}"/"${inference_asr_model}" \ - --output_dir "${_logdir}"/output.JOB \ - --mode paraformer \ - ${_opts} - - for f in token token_int score text; do - if [ -f "${_logdir}/output.1/1best_recog/${f}" ]; then - for i in $(seq "${_nj}"); do - cat "${_logdir}/output.${i}/1best_recog/${f}" - done | sort -k1 >"${_dir}/${f}" - fi - done - python utils/proce_text.py ${_dir}/text ${_dir}/text.proc - python utils/proce_text.py ${_data}/text ${_data}/text.proc - python utils/compute_wer.py ${_data}/text.proc ${_dir}/text.proc ${_dir}/text.cer - tail -n 3 ${_dir}/text.cer > ${_dir}/text.cer.txt - cat ${_dir}/text.cer.txt - done -fi - -# Prepare files for ModelScope fine-tuning and inference -if [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then - echo "stage 6: ModelScope Preparation" - cp ${feats_dir}/data/${train_set}/cmvn/am.mvn ${exp_dir}/exp/${model_dir}/am.mvn - vocab_size=$(cat ${token_list} | wc -l) - python utils/gen_modelscope_configuration.py \ - --am_model_name $inference_asr_model \ - --mode paraformer \ - --model_name data2vec_finetune_paraformer \ - --dataset aishell \ - --output_dir $exp_dir/exp/$model_dir \ - --vocab_size $vocab_size \ - --nat _nat \ - --tag $tag -fi \ No newline at end of file diff --git a/egs/aishell/data2vec_paraformer_finetune/utils b/egs/aishell/data2vec_paraformer_finetune/utils deleted file mode 120000 index fe070dd3a..000000000 --- a/egs/aishell/data2vec_paraformer_finetune/utils +++ /dev/null @@ -1 +0,0 @@ -../../aishell/transformer/utils \ No newline at end of file diff --git a/egs/aishell/data2vec_transformer_finetune/conf/decode_asr_transformer.yaml b/egs/aishell/data2vec_transformer_finetune/conf/decode_asr_transformer.yaml deleted file mode 100644 index 61ec03c86..000000000 --- a/egs/aishell/data2vec_transformer_finetune/conf/decode_asr_transformer.yaml +++ /dev/null @@ -1,6 +0,0 @@ -beam_size: 10 -penalty: 0.0 -maxlenratio: 0.0 -minlenratio: 0.0 -ctc_weight: 1.0 -lm_weight: 0.7 diff --git a/egs/aishell/data2vec_transformer_finetune/conf/train_asr_transformer_12e_6d_3072_768.yaml b/egs/aishell/data2vec_transformer_finetune/conf/train_asr_transformer_12e_6d_3072_768.yaml deleted file mode 100644 index 32a7b5bb0..000000000 --- a/egs/aishell/data2vec_transformer_finetune/conf/train_asr_transformer_12e_6d_3072_768.yaml +++ /dev/null @@ -1,112 +0,0 @@ -# network architecture -# encoder related -encoder: data2vec_encoder -encoder_conf: - extractor_mode: layer_norm - encoder_layerdrop: 0.1 - dropout_input: 0.0 - dropout_features: 0.0 - feature_grad_mult: 0.0 - encoder_embed_dim: 768 - - mask_prob: 0.65 - mask_length: 10 - - loss_beta: 0 - loss_scale: null - - instance_norm_target_layer: true - average_top_k_layers: 8 - - pos_conv_depth: 5 - conv_pos: 95 - - ema_decay: 0.999 - ema_end_decay: 0.9999 - ema_anneal_end_step: 30000 - ema_transformer_only: true - ema_layers_only: true - - require_same_masks: true - mask_dropout: 0 - -# frontend related -frontend: wav_frontend -frontend_conf: - fs: 16000 - window: hamming - n_mels: 80 - frame_length: 25 - frame_shift: 10 - lfr_m: 1 - lfr_n: 1 - -# hybrid CTC/attention -model_conf: - ctc_weight: 1.0 - lsm_weight: 0.1 # label smoothing option - length_normalized_loss: false - -# optimization related -accum_grad: 1 -grad_clip: 5 -patience: none -max_epoch: 150 -val_scheduler_criterion: - - valid - - acc -best_model_criterion: -- - valid - - cer_ctc - - min -keep_nbest_models: 10 - -# NoamLR is deprecated. Use WarmupLR. -# The following is equivalent setting for NoamLR: -# -# optim: adam -# optim_conf: -# lr: 10. -# scheduler: noamlr -# scheduler_conf: -# model_size: 256 -# warmup_steps: 25000 -# -optim: adam -optim_conf: - lr: 0.00005 -scheduler: warmuplr # pytorch v1.1.0+ required -scheduler_conf: - warmup_steps: 25000 - -specaug: specaug -specaug_conf: - apply_time_warp: true - time_warp_window: 5 - time_warp_mode: bicubic - apply_freq_mask: true - freq_mask_width_range: - - 0 - - 30 - num_freq_mask: 2 - apply_time_mask: true - time_mask_width_range: - - 0 - - 40 - num_time_mask: 2 - -dataset_conf: - data_names: speech,text - data_types: sound,text - shuffle: True - shuffle_conf: - shuffle_size: 2048 - sort_size: 500 - batch_conf: - batch_type: token - batch_size: 25000 - num_workers: 8 - -log_interval: 50 -unused_parameters: true -normalize: None \ No newline at end of file diff --git a/egs/aishell/data2vec_transformer_finetune/local/aishell_data_prep.sh b/egs/aishell/data2vec_transformer_finetune/local/aishell_data_prep.sh deleted file mode 100755 index 83f489b3c..000000000 --- a/egs/aishell/data2vec_transformer_finetune/local/aishell_data_prep.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash - -# Copyright 2017 Xingyu Na -# Apache 2.0 - -#. ./path.sh || exit 1; - -if [ $# != 3 ]; then - echo "Usage: $0 " - echo " $0 /export/a05/xna/data/data_aishell/wav /export/a05/xna/data/data_aishell/transcript data" - exit 1; -fi - -aishell_audio_dir=$1 -aishell_text=$2/aishell_transcript_v0.8.txt -output_dir=$3 - -train_dir=$output_dir/data/local/train -dev_dir=$output_dir/data/local/dev -test_dir=$output_dir/data/local/test -tmp_dir=$output_dir/data/local/tmp - -mkdir -p $train_dir -mkdir -p $dev_dir -mkdir -p $test_dir -mkdir -p $tmp_dir - -# data directory check -if [ ! -d $aishell_audio_dir ] || [ ! -f $aishell_text ]; then - echo "Error: $0 requires two directory arguments" - exit 1; -fi - -# find wav audio file for train, dev and test resp. -find $aishell_audio_dir -iname "*.wav" > $tmp_dir/wav.flist -n=`cat $tmp_dir/wav.flist | wc -l` -[ $n -ne 141925 ] && \ - echo Warning: expected 141925 data data files, found $n - -grep -i "wav/train" $tmp_dir/wav.flist > $train_dir/wav.flist || exit 1; -grep -i "wav/dev" $tmp_dir/wav.flist > $dev_dir/wav.flist || exit 1; -grep -i "wav/test" $tmp_dir/wav.flist > $test_dir/wav.flist || exit 1; - -rm -r $tmp_dir - -# Transcriptions preparation -for dir in $train_dir $dev_dir $test_dir; do - echo Preparing $dir transcriptions - sed -e 's/\.wav//' $dir/wav.flist | awk -F '/' '{print $NF}' > $dir/utt.list - paste -d' ' $dir/utt.list $dir/wav.flist > $dir/wav.scp_all - utils/filter_scp.pl -f 1 $dir/utt.list $aishell_text > $dir/transcripts.txt - awk '{print $1}' $dir/transcripts.txt > $dir/utt.list - utils/filter_scp.pl -f 1 $dir/utt.list $dir/wav.scp_all | sort -u > $dir/wav.scp - sort -u $dir/transcripts.txt > $dir/text -done - -mkdir -p $output_dir/data/train $output_dir/data/dev $output_dir/data/test - -for f in wav.scp text; do - cp $train_dir/$f $output_dir/data/train/$f || exit 1; - cp $dev_dir/$f $output_dir/data/dev/$f || exit 1; - cp $test_dir/$f $output_dir/data/test/$f || exit 1; -done - -echo "$0: AISHELL data preparation succeeded" -exit 0; diff --git a/egs/aishell/data2vec_transformer_finetune/local/download_and_untar.sh b/egs/aishell/data2vec_transformer_finetune/local/download_and_untar.sh deleted file mode 100755 index d98255915..000000000 --- a/egs/aishell/data2vec_transformer_finetune/local/download_and_untar.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2014 Johns Hopkins University (author: Daniel Povey) -# 2017 Xingyu Na -# Apache 2.0 - -remove_archive=false - -if [ "$1" == --remove-archive ]; then - remove_archive=true - shift -fi - -if [ $# -ne 3 ]; then - echo "Usage: $0 [--remove-archive] " - echo "e.g.: $0 /export/a05/xna/data www.openslr.org/resources/33 data_aishell" - echo "With --remove-archive it will remove the archive after successfully un-tarring it." - echo " can be one of: data_aishell, resource_aishell." -fi - -data=$1 -url=$2 -part=$3 - -if [ ! -d "$data" ]; then - echo "$0: no such directory $data" - exit 1; -fi - -part_ok=false -list="data_aishell resource_aishell" -for x in $list; do - if [ "$part" == $x ]; then part_ok=true; fi -done -if ! $part_ok; then - echo "$0: expected to be one of $list, but got '$part'" - exit 1; -fi - -if [ -z "$url" ]; then - echo "$0: empty URL base." - exit 1; -fi - -if [ -f $data/$part/.complete ]; then - echo "$0: data part $part was already successfully extracted, nothing to do." - exit 0; -fi - -# sizes of the archive files in bytes. -sizes="15582913665 1246920" - -if [ -f $data/$part.tgz ]; then - size=$(/bin/ls -l $data/$part.tgz | awk '{print $5}') - size_ok=false - for s in $sizes; do if [ $s == $size ]; then size_ok=true; fi; done - if ! $size_ok; then - echo "$0: removing existing file $data/$part.tgz because its size in bytes $size" - echo "does not equal the size of one of the archives." - rm $data/$part.tgz - else - echo "$data/$part.tgz exists and appears to be complete." - fi -fi - -if [ ! -f $data/$part.tgz ]; then - if ! command -v wget >/dev/null; then - echo "$0: wget is not installed." - exit 1; - fi - full_url=$url/$part.tgz - echo "$0: downloading data from $full_url. This may take some time, please be patient." - - cd $data || exit 1 - if ! wget --no-check-certificate $full_url; then - echo "$0: error executing wget $full_url" - exit 1; - fi -fi - -cd $data || exit 1 - -if ! tar -xvzf $part.tgz; then - echo "$0: error un-tarring archive $data/$part.tgz" - exit 1; -fi - -touch $data/$part/.complete - -if [ $part == "data_aishell" ]; then - cd $data/$part/wav || exit 1 - for wav in ./*.tar.gz; do - echo "Extracting wav from $wav" - tar -zxf $wav && rm $wav - done -fi - -echo "$0: Successfully downloaded and un-tarred $data/$part.tgz" - -if $remove_archive; then - echo "$0: removing $data/$part.tgz file since --remove-archive option was supplied." - rm $data/$part.tgz -fi - -exit 0; diff --git a/egs/aishell/data2vec_transformer_finetune/path.sh b/egs/aishell/data2vec_transformer_finetune/path.sh deleted file mode 100755 index 7972642d0..000000000 --- a/egs/aishell/data2vec_transformer_finetune/path.sh +++ /dev/null @@ -1,5 +0,0 @@ -export FUNASR_DIR=$PWD/../../.. - -# NOTE(kan-bayashi): Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C -export PYTHONIOENCODING=UTF-8 -export PATH=$FUNASR_DIR/funasr/bin:$PATH diff --git a/egs/aishell/data2vec_transformer_finetune/run.sh b/egs/aishell/data2vec_transformer_finetune/run.sh deleted file mode 100755 index 7b01a5f19..000000000 --- a/egs/aishell/data2vec_transformer_finetune/run.sh +++ /dev/null @@ -1,230 +0,0 @@ -#!/usr/bin/env bash - -. ./path.sh || exit 1; - -# machines configuration -CUDA_VISIBLE_DEVICES="0,1" -gpu_num=2 -count=1 -gpu_inference=true # Whether to perform gpu decoding, set false for cpu decoding -# for gpu decoding, inference_nj=ngpu*njob; for cpu decoding, inference_nj=njob -njob=5 -train_cmd=utils/run.pl -infer_cmd=utils/run.pl - -# general configuration -feats_dir="../DATA" #feature output dictionary -exp_dir="." -lang=zh -token_type=char -type=sound -scp=wav.scp -speed_perturb="0.9 1.0 1.1" -stage=0 -stop_stage=5 - -# feature configuration -feats_dim=80 -nj=64 - -# data -raw_data=../raw_data -data_url=www.openslr.org/resources/33 - -# exp tag -tag="exp1" - -model_name=damo/speech_data2vec_pretrain-zh-cn-aishell2-16k-pytorch -init_param="$HOME/.cache/modelscope/hub/$model_name/basemodel.pb" - -. utils/parse_options.sh || exit 1; - -# Set bash to 'debug' mode, it will exit on : -# -e 'error', -u 'undefined variable', -o ... 'error in pipeline', -x 'print commands', -set -e -set -u -set -o pipefail - -train_set=train -valid_set=dev -test_sets="dev test" - -asr_config=conf/train_asr_transformer_12e_6d_3072_768.yaml -model_dir="baseline_$(basename "${asr_config}" .yaml)_${lang}_${token_type}_${tag}" - -inference_config=conf/decode_asr_transformer.yaml -inference_asr_model=valid.cer_ctc.ave_10best.pb - -# you can set gpu num for decoding here -gpuid_list=$CUDA_VISIBLE_DEVICES # set gpus for decoding, the same as training stage by default -ngpu=$(echo $gpuid_list | awk -F "," '{print NF}') - -if ${gpu_inference}; then - inference_nj=$[${ngpu}*${njob}] - _ngpu=1 -else - inference_nj=$njob - _ngpu=0 -fi - -if [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then - echo "stage -1: Data Download" - local/download_and_untar.sh ${raw_data} ${data_url} data_aishell - local/download_and_untar.sh ${raw_data} ${data_url} resource_aishell -fi - -if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then - echo "stage 0: Data preparation" - # Data preparation - local/aishell_data_prep.sh ${raw_data}/data_aishell/wav ${raw_data}/data_aishell/transcript ${feats_dir} - for x in train dev test; do - cp ${feats_dir}/data/${x}/text ${feats_dir}/data/${x}/text.org - paste -d " " <(cut -f 1 -d" " ${feats_dir}/data/${x}/text.org) <(cut -f 2- -d" " ${feats_dir}/data/${x}/text.org | tr -d " ") \ - > ${feats_dir}/data/${x}/text - utils/text2token.py -n 1 -s 1 ${feats_dir}/data/${x}/text > ${feats_dir}/data/${x}/text.org - mv ${feats_dir}/data/${x}/text.org ${feats_dir}/data/${x}/text - done -fi - -if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then - echo "stage 1: Feature and CMVN Generation" - utils/compute_cmvn.sh --fbankdir ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config_file "$asr_config" --scale 1.0 -fi - -token_list=${feats_dir}/data/${lang}_token_list/$token_type/tokens.txt -echo "dictionary: ${token_list}" -if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then - echo "stage 2: Dictionary Preparation" - mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/ - - echo "make a dictionary" - echo "" > ${token_list} - echo "" >> ${token_list} - echo "" >> ${token_list} - utils/text2token.py -s 1 -n 1 --space "" ${feats_dir}/data/$train_set/text | cut -f 2- -d" " | tr " " "\n" \ - | sort | uniq | grep -a -v -e '^\s*$' | awk '{print $0}' >> ${token_list} - echo "" >> ${token_list} -fi - -# LM Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then - echo "stage 3: LM Training" -fi - -# ASR Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then - echo "stage 4: ASR Training" - python utils/download_model.py --model_name ${model_name} # download pretrained model on ModelScope - mkdir -p ${exp_dir}/exp/${model_dir} - mkdir -p ${exp_dir}/exp/${model_dir}/log - INIT_FILE=${exp_dir}/exp/${model_dir}/ddp_init - if [ -f $INIT_FILE ];then - rm -f $INIT_FILE - fi - init_method=file://$(readlink -f $INIT_FILE) - echo "$0: init method is $init_method" - for ((i = 0; i < $gpu_num; ++i)); do - { - rank=$i - local_rank=$i - gpu_id=$(echo $CUDA_VISIBLE_DEVICES | cut -d',' -f$[$i+1]) - train.py \ - --task_name asr \ - --gpu_id $gpu_id \ - --use_preprocessor true \ - --token_type $token_type \ - --token_list $token_list \ - --data_dir ${feats_dir}/data \ - --train_set ${train_set} \ - --valid_set ${valid_set} \ - --data_file_names "wav.scp,text" \ - --init_param ${init_param} \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --speed_perturb ${speed_perturb} \ - --resume true \ - --output_dir ${exp_dir}/exp/${model_dir} \ - --config $asr_config \ - --ngpu $gpu_num \ - --num_worker_count $count \ - --dist_init_method $init_method \ - --dist_world_size $world_size \ - --dist_rank $rank \ - --local_rank $local_rank 1> ${exp_dir}/exp/${model_dir}/log/train.log.$i 2>&1 - } & - done - wait -fi - -# Testing Stage -if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then - echo "stage 5: Inference" - for dset in ${test_sets}; do - asr_exp=${exp_dir}/exp/${model_dir} - inference_tag="$(basename "${inference_config}" .yaml)" - _dir="${asr_exp}/${inference_tag}/${inference_asr_model}/${dset}" - _logdir="${_dir}/logdir" - if [ -d ${_dir} ]; then - echo "${_dir} is already exists. if you want to decode again, please delete this dir first." - exit 0 - fi - mkdir -p "${_logdir}" - _data="${feats_dir}/data/${dset}" - key_file=${_data}/${scp} - num_scp_file="$(<${key_file} wc -l)" - _nj=$([ $inference_nj -le $num_scp_file ] && echo "$inference_nj" || echo "$num_scp_file") - split_scps= - for n in $(seq "${_nj}"); do - split_scps+=" ${_logdir}/keys.${n}.scp" - done - # shellcheck disable=SC2086 - utils/split_scp.pl "${key_file}" ${split_scps} - _opts= - if [ -n "${inference_config}" ]; then - _opts+="--config ${inference_config} " - fi - ${infer_cmd} --gpu "${_ngpu}" --max-jobs-run "${_nj}" JOB=1:"${_nj}" "${_logdir}"/asr_inference.JOB.log \ - python -m funasr.bin.asr_inference_launch \ - --batch_size 1 \ - --ngpu "${_ngpu}" \ - --njob ${njob} \ - --gpuid_list ${gpuid_list} \ - --data_path_and_name_and_type "${_data}/${scp},speech,${type}" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --key_file "${_logdir}"/keys.JOB.scp \ - --asr_train_config "${asr_exp}"/config.yaml \ - --asr_model_file "${asr_exp}"/"${inference_asr_model}" \ - --output_dir "${_logdir}"/output.JOB \ - --mode asr \ - ${_opts} - - for f in token token_int score text; do - if [ -f "${_logdir}/output.1/1best_recog/${f}" ]; then - for i in $(seq "${_nj}"); do - cat "${_logdir}/output.${i}/1best_recog/${f}" - done | sort -k1 >"${_dir}/${f}" - fi - done - python utils/proce_text.py ${_dir}/text ${_dir}/text.proc - python utils/proce_text.py ${_data}/text ${_data}/text.proc - python utils/compute_wer.py ${_data}/text.proc ${_dir}/text.proc ${_dir}/text.cer - tail -n 3 ${_dir}/text.cer > ${_dir}/text.cer.txt - cat ${_dir}/text.cer.txt - done -fi - -# Prepare files for ModelScope fine-tuning and inference -if [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then - echo "stage 6: ModelScope Preparation" - cp ${feats_dir}/data/${train_set}/cmvn/am.mvn ${exp_dir}/exp/${model_dir}/am.mvn - vocab_size=$(cat ${token_list} | wc -l) - python utils/gen_modelscope_configuration.py \ - --am_model_name $inference_asr_model \ - --mode asr \ - --model_name data2vec_finetune_transformer \ - --dataset aishell \ - --output_dir $exp_dir/exp/$model_dir \ - --vocab_size $vocab_size \ - --tag $tag -fi \ No newline at end of file diff --git a/egs/aishell/data2vec_transformer_finetune/utils b/egs/aishell/data2vec_transformer_finetune/utils deleted file mode 120000 index 0853fce5d..000000000 --- a/egs/aishell/data2vec_transformer_finetune/utils +++ /dev/null @@ -1 +0,0 @@ -../transformer/utils/ \ No newline at end of file diff --git a/egs/aishell/e_branchformer/README.md b/egs/aishell/e_branchformer/README.md deleted file mode 100644 index 9b6b23843..000000000 --- a/egs/aishell/e_branchformer/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# E-Branchformer Result - -## Training Config -- Feature info: using raw speech, extracting 80 dims fbank online, global cmvn, speed perturb(0.9, 1.0, 1.1), specaugment -- Train info: lr 0.001, batch_size 10000, 4 gpu(Tesla V100), acc_grad 1, 180 epochs -- Train config: conf/train_asr_e_branchformer.yaml -- LM config: LM was not used - -## Results (CER) -- Decode config: conf/decode_asr_transformer.yaml (ctc weight:0.4) - -| testset | CER(%) | -|:-----------:|:-------:| -| dev | 4.10 | -| test | 4.52 | \ No newline at end of file diff --git a/egs/aishell/e_branchformer/conf/decode_asr_transformer.yaml b/egs/aishell/e_branchformer/conf/decode_asr_transformer.yaml deleted file mode 100644 index e87a2937f..000000000 --- a/egs/aishell/e_branchformer/conf/decode_asr_transformer.yaml +++ /dev/null @@ -1,6 +0,0 @@ -beam_size: 10 -penalty: 0.0 -maxlenratio: 0.0 -minlenratio: 0.0 -ctc_weight: 0.4 -lm_weight: 0.0 diff --git a/egs/aishell/e_branchformer/conf/train_asr_e_branchformer.yaml b/egs/aishell/e_branchformer/conf/train_asr_e_branchformer.yaml deleted file mode 100644 index a30e9a23b..000000000 --- a/egs/aishell/e_branchformer/conf/train_asr_e_branchformer.yaml +++ /dev/null @@ -1,101 +0,0 @@ -# network architecture -# encoder related -encoder: e_branchformer -encoder_conf: - output_size: 256 - attention_heads: 4 - attention_layer_type: rel_selfattn - pos_enc_layer_type: rel_pos - rel_pos_type: latest - cgmlp_linear_units: 1024 - cgmlp_conv_kernel: 31 - use_linear_after_conv: false - gate_activation: identity - num_blocks: 12 - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - attention_dropout_rate: 0.1 - input_layer: conv2d - layer_drop_rate: 0.0 - linear_units: 1024 - positionwise_layer_type: linear - use_ffn: true - macaron_ffn: true - merge_conv_kernel: 31 - -# decoder related -decoder: transformer -decoder_conf: - attention_heads: 4 - linear_units: 2048 - num_blocks: 6 - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - self_attention_dropout_rate: 0. - src_attention_dropout_rate: 0. - -# frontend related -frontend: wav_frontend -frontend_conf: - fs: 16000 - window: hamming - n_mels: 80 - frame_length: 25 - frame_shift: 10 - lfr_m: 1 - lfr_n: 1 - -# hybrid CTC/attention -model_conf: - ctc_weight: 0.3 - lsm_weight: 0.1 # label smoothing option - length_normalized_loss: false - -# optimization related -accum_grad: 1 -grad_clip: 5 -max_epoch: 180 -best_model_criterion: -- - valid - - acc - - max -keep_nbest_models: 10 - -optim: adam -optim_conf: - lr: 0.001 - weight_decay: 0.000001 -scheduler: warmuplr -scheduler_conf: - warmup_steps: 35000 - -specaug: specaug -specaug_conf: - apply_time_warp: true - time_warp_window: 5 - time_warp_mode: bicubic - apply_freq_mask: true - freq_mask_width_range: - - 0 - - 27 - num_freq_mask: 2 - apply_time_mask: true - time_mask_width_ratio_range: - - 0. - - 0.05 - num_time_mask: 10 - -dataset_conf: - data_names: speech,text - data_types: sound,text - shuffle: True - shuffle_conf: - shuffle_size: 2048 - sort_size: 500 - batch_conf: - batch_type: token - batch_size: 10000 - num_workers: 8 - -log_interval: 50 -normalize: None \ No newline at end of file diff --git a/egs/aishell/e_branchformer/local/aishell_data_prep.sh b/egs/aishell/e_branchformer/local/aishell_data_prep.sh deleted file mode 100755 index 83f489b3c..000000000 --- a/egs/aishell/e_branchformer/local/aishell_data_prep.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash - -# Copyright 2017 Xingyu Na -# Apache 2.0 - -#. ./path.sh || exit 1; - -if [ $# != 3 ]; then - echo "Usage: $0 " - echo " $0 /export/a05/xna/data/data_aishell/wav /export/a05/xna/data/data_aishell/transcript data" - exit 1; -fi - -aishell_audio_dir=$1 -aishell_text=$2/aishell_transcript_v0.8.txt -output_dir=$3 - -train_dir=$output_dir/data/local/train -dev_dir=$output_dir/data/local/dev -test_dir=$output_dir/data/local/test -tmp_dir=$output_dir/data/local/tmp - -mkdir -p $train_dir -mkdir -p $dev_dir -mkdir -p $test_dir -mkdir -p $tmp_dir - -# data directory check -if [ ! -d $aishell_audio_dir ] || [ ! -f $aishell_text ]; then - echo "Error: $0 requires two directory arguments" - exit 1; -fi - -# find wav audio file for train, dev and test resp. -find $aishell_audio_dir -iname "*.wav" > $tmp_dir/wav.flist -n=`cat $tmp_dir/wav.flist | wc -l` -[ $n -ne 141925 ] && \ - echo Warning: expected 141925 data data files, found $n - -grep -i "wav/train" $tmp_dir/wav.flist > $train_dir/wav.flist || exit 1; -grep -i "wav/dev" $tmp_dir/wav.flist > $dev_dir/wav.flist || exit 1; -grep -i "wav/test" $tmp_dir/wav.flist > $test_dir/wav.flist || exit 1; - -rm -r $tmp_dir - -# Transcriptions preparation -for dir in $train_dir $dev_dir $test_dir; do - echo Preparing $dir transcriptions - sed -e 's/\.wav//' $dir/wav.flist | awk -F '/' '{print $NF}' > $dir/utt.list - paste -d' ' $dir/utt.list $dir/wav.flist > $dir/wav.scp_all - utils/filter_scp.pl -f 1 $dir/utt.list $aishell_text > $dir/transcripts.txt - awk '{print $1}' $dir/transcripts.txt > $dir/utt.list - utils/filter_scp.pl -f 1 $dir/utt.list $dir/wav.scp_all | sort -u > $dir/wav.scp - sort -u $dir/transcripts.txt > $dir/text -done - -mkdir -p $output_dir/data/train $output_dir/data/dev $output_dir/data/test - -for f in wav.scp text; do - cp $train_dir/$f $output_dir/data/train/$f || exit 1; - cp $dev_dir/$f $output_dir/data/dev/$f || exit 1; - cp $test_dir/$f $output_dir/data/test/$f || exit 1; -done - -echo "$0: AISHELL data preparation succeeded" -exit 0; diff --git a/egs/aishell/e_branchformer/local/download_and_untar.sh b/egs/aishell/e_branchformer/local/download_and_untar.sh deleted file mode 100755 index d98255915..000000000 --- a/egs/aishell/e_branchformer/local/download_and_untar.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2014 Johns Hopkins University (author: Daniel Povey) -# 2017 Xingyu Na -# Apache 2.0 - -remove_archive=false - -if [ "$1" == --remove-archive ]; then - remove_archive=true - shift -fi - -if [ $# -ne 3 ]; then - echo "Usage: $0 [--remove-archive] " - echo "e.g.: $0 /export/a05/xna/data www.openslr.org/resources/33 data_aishell" - echo "With --remove-archive it will remove the archive after successfully un-tarring it." - echo " can be one of: data_aishell, resource_aishell." -fi - -data=$1 -url=$2 -part=$3 - -if [ ! -d "$data" ]; then - echo "$0: no such directory $data" - exit 1; -fi - -part_ok=false -list="data_aishell resource_aishell" -for x in $list; do - if [ "$part" == $x ]; then part_ok=true; fi -done -if ! $part_ok; then - echo "$0: expected to be one of $list, but got '$part'" - exit 1; -fi - -if [ -z "$url" ]; then - echo "$0: empty URL base." - exit 1; -fi - -if [ -f $data/$part/.complete ]; then - echo "$0: data part $part was already successfully extracted, nothing to do." - exit 0; -fi - -# sizes of the archive files in bytes. -sizes="15582913665 1246920" - -if [ -f $data/$part.tgz ]; then - size=$(/bin/ls -l $data/$part.tgz | awk '{print $5}') - size_ok=false - for s in $sizes; do if [ $s == $size ]; then size_ok=true; fi; done - if ! $size_ok; then - echo "$0: removing existing file $data/$part.tgz because its size in bytes $size" - echo "does not equal the size of one of the archives." - rm $data/$part.tgz - else - echo "$data/$part.tgz exists and appears to be complete." - fi -fi - -if [ ! -f $data/$part.tgz ]; then - if ! command -v wget >/dev/null; then - echo "$0: wget is not installed." - exit 1; - fi - full_url=$url/$part.tgz - echo "$0: downloading data from $full_url. This may take some time, please be patient." - - cd $data || exit 1 - if ! wget --no-check-certificate $full_url; then - echo "$0: error executing wget $full_url" - exit 1; - fi -fi - -cd $data || exit 1 - -if ! tar -xvzf $part.tgz; then - echo "$0: error un-tarring archive $data/$part.tgz" - exit 1; -fi - -touch $data/$part/.complete - -if [ $part == "data_aishell" ]; then - cd $data/$part/wav || exit 1 - for wav in ./*.tar.gz; do - echo "Extracting wav from $wav" - tar -zxf $wav && rm $wav - done -fi - -echo "$0: Successfully downloaded and un-tarred $data/$part.tgz" - -if $remove_archive; then - echo "$0: removing $data/$part.tgz file since --remove-archive option was supplied." - rm $data/$part.tgz -fi - -exit 0; diff --git a/egs/aishell/e_branchformer/path.sh b/egs/aishell/e_branchformer/path.sh deleted file mode 100755 index 7972642d0..000000000 --- a/egs/aishell/e_branchformer/path.sh +++ /dev/null @@ -1,5 +0,0 @@ -export FUNASR_DIR=$PWD/../../.. - -# NOTE(kan-bayashi): Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C -export PYTHONIOENCODING=UTF-8 -export PATH=$FUNASR_DIR/funasr/bin:$PATH diff --git a/egs/aishell/e_branchformer/run.sh b/egs/aishell/e_branchformer/run.sh deleted file mode 100755 index bcba2d75f..000000000 --- a/egs/aishell/e_branchformer/run.sh +++ /dev/null @@ -1,225 +0,0 @@ -#!/usr/bin/env bash - -. ./path.sh || exit 1; - -# machines configuration -CUDA_VISIBLE_DEVICES="0,1,2,3" -gpu_num=4 -count=1 -gpu_inference=true # Whether to perform gpu decoding, set false for cpu decoding -# for gpu decoding, inference_nj=ngpu*njob; for cpu decoding, inference_nj=njob -njob=5 -train_cmd=utils/run.pl -infer_cmd=utils/run.pl - -# general configuration -feats_dir="../DATA" #feature output dictionary -exp_dir="." -lang=zh -token_type=char -type=sound -scp=wav.scp -speed_perturb="0.9 1.0 1.1" -stage=0 -stop_stage=5 - -# feature configuration -feats_dim=80 -nj=64 - -# data -raw_data=../raw_data -data_url=www.openslr.org/resources/33 - -# exp tag -tag="exp1" - -. utils/parse_options.sh || exit 1; - -# Set bash to 'debug' mode, it will exit on : -# -e 'error', -u 'undefined variable', -o ... 'error in pipeline', -x 'print commands', -set -e -set -u -set -o pipefail - -train_set=train -valid_set=dev -test_sets="dev test" - -asr_config=conf/train_asr_e_branchformer.yaml -model_dir="baseline_$(basename "${asr_config}" .yaml)_${lang}_${token_type}_${tag}" - -inference_config=conf/decode_asr_transformer.yaml -inference_asr_model=valid.acc.ave_10best.pb - -# you can set gpu num for decoding here -gpuid_list=$CUDA_VISIBLE_DEVICES # set gpus for decoding, the same as training stage by default -ngpu=$(echo $gpuid_list | awk -F "," '{print NF}') - -if ${gpu_inference}; then - inference_nj=$[${ngpu}*${njob}] - _ngpu=1 -else - inference_nj=$njob - _ngpu=0 -fi - -if [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then - echo "stage -1: Data Download" - local/download_and_untar.sh ${raw_data} ${data_url} data_aishell - local/download_and_untar.sh ${raw_data} ${data_url} resource_aishell -fi - -if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then - echo "stage 0: Data preparation" - # Data preparation - local/aishell_data_prep.sh ${raw_data}/data_aishell/wav ${raw_data}/data_aishell/transcript ${feats_dir} - for x in train dev test; do - cp ${feats_dir}/data/${x}/text ${feats_dir}/data/${x}/text.org - paste -d " " <(cut -f 1 -d" " ${feats_dir}/data/${x}/text.org) <(cut -f 2- -d" " ${feats_dir}/data/${x}/text.org | tr -d " ") \ - > ${feats_dir}/data/${x}/text - utils/text2token.py -n 1 -s 1 ${feats_dir}/data/${x}/text > ${feats_dir}/data/${x}/text.org - mv ${feats_dir}/data/${x}/text.org ${feats_dir}/data/${x}/text - done -fi - -if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then - echo "stage 1: Feature and CMVN Generation" - utils/compute_cmvn.sh --fbankdir ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config_file "$asr_config" --scale 1.0 -fi - -token_list=${feats_dir}/data/${lang}_token_list/$token_type/tokens.txt -echo "dictionary: ${token_list}" -if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then - echo "stage 2: Dictionary Preparation" - mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/ - - echo "make a dictionary" - echo "" > ${token_list} - echo "" >> ${token_list} - echo "" >> ${token_list} - utils/text2token.py -s 1 -n 1 --space "" ${feats_dir}/data/$train_set/text | cut -f 2- -d" " | tr " " "\n" \ - | sort | uniq | grep -a -v -e '^\s*$' | awk '{print $0}' >> ${token_list} - echo "" >> ${token_list} -fi - -# LM Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then - echo "stage 3: LM Training" -fi - -# ASR Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then - echo "stage 4: ASR Training" - mkdir -p ${exp_dir}/exp/${model_dir} - mkdir -p ${exp_dir}/exp/${model_dir}/log - INIT_FILE=${exp_dir}/exp/${model_dir}/ddp_init - if [ -f $INIT_FILE ];then - rm -f $INIT_FILE - fi - init_method=file://$(readlink -f $INIT_FILE) - echo "$0: init method is $init_method" - for ((i = 0; i < $gpu_num; ++i)); do - { - rank=$i - local_rank=$i - gpu_id=$(echo $CUDA_VISIBLE_DEVICES | cut -d',' -f$[$i+1]) - train.py \ - --task_name asr \ - --gpu_id $gpu_id \ - --use_preprocessor true \ - --token_type $token_type \ - --token_list $token_list \ - --data_dir ${feats_dir}/data \ - --train_set ${train_set} \ - --valid_set ${valid_set} \ - --data_file_names "wav.scp,text" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --speed_perturb ${speed_perturb} \ - --resume true \ - --output_dir ${exp_dir}/exp/${model_dir} \ - --config $asr_config \ - --ngpu $gpu_num \ - --num_worker_count $count \ - --dist_init_method $init_method \ - --dist_world_size $world_size \ - --dist_rank $rank \ - --local_rank $local_rank 1> ${exp_dir}/exp/${model_dir}/log/train.log.$i 2>&1 - } & - done - wait -fi - -# Testing Stage -if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then - echo "stage 5: Inference" - for dset in ${test_sets}; do - asr_exp=${exp_dir}/exp/${model_dir} - inference_tag="$(basename "${inference_config}" .yaml)" - _dir="${asr_exp}/${inference_tag}/${inference_asr_model}/${dset}" - _logdir="${_dir}/logdir" - if [ -d ${_dir} ]; then - echo "${_dir} is already exists. if you want to decode again, please delete this dir first." - exit 0 - fi - mkdir -p "${_logdir}" - _data="${feats_dir}/data/${dset}" - key_file=${_data}/${scp} - num_scp_file="$(<${key_file} wc -l)" - _nj=$([ $inference_nj -le $num_scp_file ] && echo "$inference_nj" || echo "$num_scp_file") - split_scps= - for n in $(seq "${_nj}"); do - split_scps+=" ${_logdir}/keys.${n}.scp" - done - # shellcheck disable=SC2086 - utils/split_scp.pl "${key_file}" ${split_scps} - _opts= - if [ -n "${inference_config}" ]; then - _opts+="--config ${inference_config} " - fi - ${infer_cmd} --gpu "${_ngpu}" --max-jobs-run "${_nj}" JOB=1:"${_nj}" "${_logdir}"/asr_inference.JOB.log \ - python -m funasr.bin.asr_inference_launch \ - --batch_size 1 \ - --ngpu "${_ngpu}" \ - --njob ${njob} \ - --gpuid_list ${gpuid_list} \ - --data_path_and_name_and_type "${_data}/${scp},speech,${type}" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --key_file "${_logdir}"/keys.JOB.scp \ - --asr_train_config "${asr_exp}"/config.yaml \ - --asr_model_file "${asr_exp}"/"${inference_asr_model}" \ - --output_dir "${_logdir}"/output.JOB \ - --mode asr \ - ${_opts} - - for f in token token_int score text; do - if [ -f "${_logdir}/output.1/1best_recog/${f}" ]; then - for i in $(seq "${_nj}"); do - cat "${_logdir}/output.${i}/1best_recog/${f}" - done | sort -k1 >"${_dir}/${f}" - fi - done - python utils/proce_text.py ${_dir}/text ${_dir}/text.proc - python utils/proce_text.py ${_data}/text ${_data}/text.proc - python utils/compute_wer.py ${_data}/text.proc ${_dir}/text.proc ${_dir}/text.cer - tail -n 3 ${_dir}/text.cer > ${_dir}/text.cer.txt - cat ${_dir}/text.cer.txt - done -fi - -# Prepare files for ModelScope fine-tuning and inference -if [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then - echo "stage 6: ModelScope Preparation" - cp ${feats_dir}/data/${train_set}/cmvn/am.mvn ${exp_dir}/exp/${model_dir}/am.mvn - vocab_size=$(cat ${token_list} | wc -l) - python utils/gen_modelscope_configuration.py \ - --am_model_name $inference_asr_model \ - --mode asr \ - --model_name conformer \ - --dataset aishell \ - --output_dir $exp_dir/exp/$model_dir \ - --vocab_size $vocab_size \ - --tag $tag -fi \ No newline at end of file diff --git a/egs/aishell/e_branchformer/utils b/egs/aishell/e_branchformer/utils deleted file mode 120000 index 4072eacc1..000000000 --- a/egs/aishell/e_branchformer/utils +++ /dev/null @@ -1 +0,0 @@ -../transformer/utils \ No newline at end of file diff --git a/egs/aishell/paraformer/README.md b/egs/aishell/paraformer/README.md deleted file mode 100644 index c0385db86..000000000 --- a/egs/aishell/paraformer/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Paraformer -pretrained model in [ModelScope](https://www.modelscope.cn/home):[speech_paraformer_asr_nat-aishell1-pytorch](https://www.modelscope.cn/models/damo/speech_paraformer_asr_nat-aishell1-pytorch/summary) - -## Training Config -- Feature info: using 80 dims fbank, global cmvn, speed perturb(0.9, 1.0, 1.1), specaugment -- Train info: lr 5e-4, batch_size 25000, 2 gpu(Tesla V100), acc_grad 1, 50 epochs -- Train config: conf/train_asr_paraformer_conformer_12e_6d_2048_256.yaml -- LM config: LM was not used - -## Results (CER) - -- Decode config: conf/decode_asr_transformer_noctc_1best.yaml (ctc weight:0.0) - -| testset | CER(%) | -|:-----------:|:-------:| -| dev | 4.66 | -| test | 5.11 | - -- Decode config: conf/decode_asr_transformer.yaml (ctc weight:0.5) - -| testset | CER(%) | -|:-----------:|:-------:| -| dev | 4.52 | -| test | 4.94 | \ No newline at end of file diff --git a/egs/aishell/paraformer/conf/decode_asr_transformer.yaml b/egs/aishell/paraformer/conf/decode_asr_transformer.yaml deleted file mode 100644 index a147fa79d..000000000 --- a/egs/aishell/paraformer/conf/decode_asr_transformer.yaml +++ /dev/null @@ -1,6 +0,0 @@ -beam_size: 10 -penalty: 0.0 -maxlenratio: 0.0 -minlenratio: 0.0 -ctc_weight: 0.5 -lm_weight: 0.7 diff --git a/egs/aishell/paraformer/conf/decode_asr_transformer_noctc_1best.yaml b/egs/aishell/paraformer/conf/decode_asr_transformer_noctc_1best.yaml deleted file mode 100644 index 5436b12e4..000000000 --- a/egs/aishell/paraformer/conf/decode_asr_transformer_noctc_1best.yaml +++ /dev/null @@ -1,6 +0,0 @@ -beam_size: 1 -penalty: 0.0 -maxlenratio: 0.0 -minlenratio: 0.0 -ctc_weight: 0.0 -lm_weight: 0.15 diff --git a/egs/aishell/paraformer/conf/train_asr_paraformer_conformer_12e_6d_2048_256.yaml b/egs/aishell/paraformer/conf/train_asr_paraformer_conformer_12e_6d_2048_256.yaml deleted file mode 100644 index 9dd3fb304..000000000 --- a/egs/aishell/paraformer/conf/train_asr_paraformer_conformer_12e_6d_2048_256.yaml +++ /dev/null @@ -1,109 +0,0 @@ -# network architecture -# encoder related -encoder: conformer -encoder_conf: - output_size: 256 # dimension of attention - attention_heads: 4 - linear_units: 2048 # the number of units of position-wise feed forward - num_blocks: 12 # the number of encoder blocks - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - attention_dropout_rate: 0.0 - input_layer: conv2d # encoder architecture type - normalize_before: true - pos_enc_layer_type: rel_pos - selfattention_layer_type: rel_selfattn - activation_type: swish - macaron_style: true - use_cnn_module: true - cnn_module_kernel: 15 - -# decoder related -decoder: paraformer_decoder_san -decoder_conf: - attention_heads: 4 - linear_units: 2048 - num_blocks: 6 - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - self_attention_dropout_rate: 0.0 - src_attention_dropout_rate: 0.0 - -# frontend related -frontend: wav_frontend -frontend_conf: - fs: 16000 - window: hamming - n_mels: 80 - frame_length: 25 - frame_shift: 10 - lfr_m: 1 - lfr_n: 1 - -model: paraformer -model_conf: - ctc_weight: 0.3 - lsm_weight: 0.1 - length_normalized_loss: false - predictor_weight: 1.0 - sampling_ratio: 0.4 - use_1st_decoder_loss: true - -# optimization related -accum_grad: 1 -grad_clip: 5 -max_epoch: 150 -val_scheduler_criterion: - - valid - - acc -best_model_criterion: -- - valid - - acc - - max -keep_nbest_models: 10 - -optim: adam -optim_conf: - lr: 0.0005 -scheduler: warmuplr -scheduler_conf: - warmup_steps: 30000 - -specaug: specaug -specaug_conf: - apply_time_warp: true - time_warp_window: 5 - time_warp_mode: bicubic - apply_freq_mask: true - freq_mask_width_range: - - 0 - - 30 - num_freq_mask: 2 - apply_time_mask: true - time_mask_width_range: - - 0 - - 40 - num_time_mask: 2 - -predictor: cif_predictor -predictor_conf: - idim: 256 - threshold: 1.0 - l_order: 1 - r_order: 1 - tail_threshold: 0.45 - -dataset_conf: - data_names: speech,text - data_types: sound,text - shuffle: True - shuffle_conf: - shuffle_size: 2048 - sort_size: 500 - batch_conf: - batch_type: token - batch_size: 25000 - num_workers: 8 - -log_interval: 50 -normalize: None \ No newline at end of file diff --git a/egs/aishell/paraformer/local/aishell_data_prep.sh b/egs/aishell/paraformer/local/aishell_data_prep.sh deleted file mode 100755 index 83f489b3c..000000000 --- a/egs/aishell/paraformer/local/aishell_data_prep.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash - -# Copyright 2017 Xingyu Na -# Apache 2.0 - -#. ./path.sh || exit 1; - -if [ $# != 3 ]; then - echo "Usage: $0 " - echo " $0 /export/a05/xna/data/data_aishell/wav /export/a05/xna/data/data_aishell/transcript data" - exit 1; -fi - -aishell_audio_dir=$1 -aishell_text=$2/aishell_transcript_v0.8.txt -output_dir=$3 - -train_dir=$output_dir/data/local/train -dev_dir=$output_dir/data/local/dev -test_dir=$output_dir/data/local/test -tmp_dir=$output_dir/data/local/tmp - -mkdir -p $train_dir -mkdir -p $dev_dir -mkdir -p $test_dir -mkdir -p $tmp_dir - -# data directory check -if [ ! -d $aishell_audio_dir ] || [ ! -f $aishell_text ]; then - echo "Error: $0 requires two directory arguments" - exit 1; -fi - -# find wav audio file for train, dev and test resp. -find $aishell_audio_dir -iname "*.wav" > $tmp_dir/wav.flist -n=`cat $tmp_dir/wav.flist | wc -l` -[ $n -ne 141925 ] && \ - echo Warning: expected 141925 data data files, found $n - -grep -i "wav/train" $tmp_dir/wav.flist > $train_dir/wav.flist || exit 1; -grep -i "wav/dev" $tmp_dir/wav.flist > $dev_dir/wav.flist || exit 1; -grep -i "wav/test" $tmp_dir/wav.flist > $test_dir/wav.flist || exit 1; - -rm -r $tmp_dir - -# Transcriptions preparation -for dir in $train_dir $dev_dir $test_dir; do - echo Preparing $dir transcriptions - sed -e 's/\.wav//' $dir/wav.flist | awk -F '/' '{print $NF}' > $dir/utt.list - paste -d' ' $dir/utt.list $dir/wav.flist > $dir/wav.scp_all - utils/filter_scp.pl -f 1 $dir/utt.list $aishell_text > $dir/transcripts.txt - awk '{print $1}' $dir/transcripts.txt > $dir/utt.list - utils/filter_scp.pl -f 1 $dir/utt.list $dir/wav.scp_all | sort -u > $dir/wav.scp - sort -u $dir/transcripts.txt > $dir/text -done - -mkdir -p $output_dir/data/train $output_dir/data/dev $output_dir/data/test - -for f in wav.scp text; do - cp $train_dir/$f $output_dir/data/train/$f || exit 1; - cp $dev_dir/$f $output_dir/data/dev/$f || exit 1; - cp $test_dir/$f $output_dir/data/test/$f || exit 1; -done - -echo "$0: AISHELL data preparation succeeded" -exit 0; diff --git a/egs/aishell/paraformer/local/download_and_untar.sh b/egs/aishell/paraformer/local/download_and_untar.sh deleted file mode 100755 index d98255915..000000000 --- a/egs/aishell/paraformer/local/download_and_untar.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2014 Johns Hopkins University (author: Daniel Povey) -# 2017 Xingyu Na -# Apache 2.0 - -remove_archive=false - -if [ "$1" == --remove-archive ]; then - remove_archive=true - shift -fi - -if [ $# -ne 3 ]; then - echo "Usage: $0 [--remove-archive] " - echo "e.g.: $0 /export/a05/xna/data www.openslr.org/resources/33 data_aishell" - echo "With --remove-archive it will remove the archive after successfully un-tarring it." - echo " can be one of: data_aishell, resource_aishell." -fi - -data=$1 -url=$2 -part=$3 - -if [ ! -d "$data" ]; then - echo "$0: no such directory $data" - exit 1; -fi - -part_ok=false -list="data_aishell resource_aishell" -for x in $list; do - if [ "$part" == $x ]; then part_ok=true; fi -done -if ! $part_ok; then - echo "$0: expected to be one of $list, but got '$part'" - exit 1; -fi - -if [ -z "$url" ]; then - echo "$0: empty URL base." - exit 1; -fi - -if [ -f $data/$part/.complete ]; then - echo "$0: data part $part was already successfully extracted, nothing to do." - exit 0; -fi - -# sizes of the archive files in bytes. -sizes="15582913665 1246920" - -if [ -f $data/$part.tgz ]; then - size=$(/bin/ls -l $data/$part.tgz | awk '{print $5}') - size_ok=false - for s in $sizes; do if [ $s == $size ]; then size_ok=true; fi; done - if ! $size_ok; then - echo "$0: removing existing file $data/$part.tgz because its size in bytes $size" - echo "does not equal the size of one of the archives." - rm $data/$part.tgz - else - echo "$data/$part.tgz exists and appears to be complete." - fi -fi - -if [ ! -f $data/$part.tgz ]; then - if ! command -v wget >/dev/null; then - echo "$0: wget is not installed." - exit 1; - fi - full_url=$url/$part.tgz - echo "$0: downloading data from $full_url. This may take some time, please be patient." - - cd $data || exit 1 - if ! wget --no-check-certificate $full_url; then - echo "$0: error executing wget $full_url" - exit 1; - fi -fi - -cd $data || exit 1 - -if ! tar -xvzf $part.tgz; then - echo "$0: error un-tarring archive $data/$part.tgz" - exit 1; -fi - -touch $data/$part/.complete - -if [ $part == "data_aishell" ]; then - cd $data/$part/wav || exit 1 - for wav in ./*.tar.gz; do - echo "Extracting wav from $wav" - tar -zxf $wav && rm $wav - done -fi - -echo "$0: Successfully downloaded and un-tarred $data/$part.tgz" - -if $remove_archive; then - echo "$0: removing $data/$part.tgz file since --remove-archive option was supplied." - rm $data/$part.tgz -fi - -exit 0; diff --git a/egs/aishell/paraformer/path.sh b/egs/aishell/paraformer/path.sh deleted file mode 100755 index 7972642d0..000000000 --- a/egs/aishell/paraformer/path.sh +++ /dev/null @@ -1,5 +0,0 @@ -export FUNASR_DIR=$PWD/../../.. - -# NOTE(kan-bayashi): Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C -export PYTHONIOENCODING=UTF-8 -export PATH=$FUNASR_DIR/funasr/bin:$PATH diff --git a/egs/aishell/paraformer/run.sh b/egs/aishell/paraformer/run.sh deleted file mode 100755 index 7d79211c5..000000000 --- a/egs/aishell/paraformer/run.sh +++ /dev/null @@ -1,227 +0,0 @@ -#!/usr/bin/env bash - -. ./path.sh || exit 1; - -# machines configuration -CUDA_VISIBLE_DEVICES="0,1" -gpu_num=2 -count=1 -gpu_inference=true # Whether to perform gpu decoding, set false for cpu decoding -# for gpu decoding, inference_nj=ngpu*njob; for cpu decoding, inference_nj=njob -njob=1 -train_cmd=utils/run.pl -infer_cmd=utils/run.pl - -# general configuration -feats_dir="../DATA" #feature output dictionary -exp_dir="." -lang=zh -token_type=char -type=sound -scp=wav.scp -speed_perturb="0.9 1.0 1.1" -stage=0 -stop_stage=5 - -# feature configuration -feats_dim=80 -nj=64 - -# data -raw_data=../raw_data -data_url=www.openslr.org/resources/33 - -# exp tag -tag="exp1" - -. utils/parse_options.sh || exit 1; - -# Set bash to 'debug' mode, it will exit on : -# -e 'error', -u 'undefined variable', -o ... 'error in pipeline', -x 'print commands', -set -e -set -u -set -o pipefail - -train_set=train -valid_set=dev -test_sets="dev test" - -asr_config=conf/train_asr_paraformer_conformer_12e_6d_2048_256.yaml -model_dir="baseline_$(basename "${asr_config}" .yaml)_${lang}_${token_type}_${tag}" - -inference_config=conf/decode_asr_transformer_noctc_1best.yaml -inference_asr_model=valid.acc.ave_10best.pb - -# you can set gpu num for decoding here -gpuid_list=$CUDA_VISIBLE_DEVICES # set gpus for decoding, the same as training stage by default -ngpu=$(echo $gpuid_list | awk -F "," '{print NF}') - -if ${gpu_inference}; then - inference_nj=$[${ngpu}*${njob}] - _ngpu=1 -else - inference_nj=$njob - _ngpu=0 -fi - -if [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then - echo "stage -1: Data Download" - local/download_and_untar.sh ${raw_data} ${data_url} data_aishell - local/download_and_untar.sh ${raw_data} ${data_url} resource_aishell -fi - -if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then - echo "stage 0: Data preparation" - # Data preparation - local/aishell_data_prep.sh ${raw_data}/data_aishell/wav ${raw_data}/data_aishell/transcript ${feats_dir} - for x in train dev test; do - cp ${feats_dir}/data/${x}/text ${feats_dir}/data/${x}/text.org - paste -d " " <(cut -f 1 -d" " ${feats_dir}/data/${x}/text.org) <(cut -f 2- -d" " ${feats_dir}/data/${x}/text.org | tr -d " ") \ - > ${feats_dir}/data/${x}/text - utils/text2token.py -n 1 -s 1 ${feats_dir}/data/${x}/text > ${feats_dir}/data/${x}/text.org - mv ${feats_dir}/data/${x}/text.org ${feats_dir}/data/${x}/text - done -fi - -if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then - echo "stage 1: Feature and CMVN Generation" - utils/compute_cmvn.sh --fbankdir ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config_file "$asr_config" --scale 1.0 -fi - -token_list=${feats_dir}/data/${lang}_token_list/$token_type/tokens.txt -echo "dictionary: ${token_list}" -if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then - echo "stage 2: Dictionary Preparation" - mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/ - - echo "make a dictionary" - echo "" > ${token_list} - echo "" >> ${token_list} - echo "" >> ${token_list} - utils/text2token.py -s 1 -n 1 --space "" ${feats_dir}/data/$train_set/text | cut -f 2- -d" " | tr " " "\n" \ - | sort | uniq | grep -a -v -e '^\s*$' | awk '{print $0}' >> ${token_list} - echo "" >> ${token_list} -fi - -# LM Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then - echo "stage 3: LM Training" -fi - -# ASR Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then - echo "stage 4: ASR Training" - mkdir -p ${exp_dir}/exp/${model_dir} - mkdir -p ${exp_dir}/exp/${model_dir}/log - INIT_FILE=${exp_dir}/exp/${model_dir}/ddp_init - if [ -f $INIT_FILE ];then - rm -f $INIT_FILE - fi - init_method=file://$(readlink -f $INIT_FILE) - echo "$0: init method is $init_method" - for ((i = 0; i < $gpu_num; ++i)); do - { - rank=$i - local_rank=$i - gpu_id=$(echo $CUDA_VISIBLE_DEVICES | cut -d',' -f$[$i+1]) - train.py \ - --task_name asr \ - --gpu_id $gpu_id \ - --use_preprocessor true \ - --token_type $token_type \ - --token_list $token_list \ - --dataset_type small \ - --data_dir ${feats_dir}/data \ - --train_set ${train_set} \ - --valid_set ${valid_set} \ - --data_file_names "wav.scp,text" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --speed_perturb ${speed_perturb} \ - --resume true \ - --output_dir ${exp_dir}/exp/${model_dir} \ - --config $asr_config \ - --ngpu $gpu_num \ - --num_worker_count $count \ - --dist_init_method $init_method \ - --dist_world_size $world_size \ - --dist_rank $rank \ - --local_rank $local_rank 1> ${exp_dir}/exp/${model_dir}/log/train.log.$i 2>&1 - } & - done - wait -fi - -# Testing Stage -if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then - echo "stage 5: Inference" - for dset in ${test_sets}; do - asr_exp=${exp_dir}/exp/${model_dir} - inference_tag="$(basename "${inference_config}" .yaml)" - _dir="${asr_exp}/${inference_tag}/${inference_asr_model}/${dset}" - _logdir="${_dir}/logdir" - if [ -d ${_dir} ]; then - echo "${_dir} is already exists. if you want to decode again, please delete this dir first." - exit 0 - fi - mkdir -p "${_logdir}" - _data="${feats_dir}/data/${dset}" - key_file=${_data}/${scp} - num_scp_file="$(<${key_file} wc -l)" - _nj=$([ $inference_nj -le $num_scp_file ] && echo "$inference_nj" || echo "$num_scp_file") - split_scps= - for n in $(seq "${_nj}"); do - split_scps+=" ${_logdir}/keys.${n}.scp" - done - # shellcheck disable=SC2086 - utils/split_scp.pl "${key_file}" ${split_scps} - _opts= - if [ -n "${inference_config}" ]; then - _opts+="--config ${inference_config} " - fi - ${infer_cmd} --gpu "${_ngpu}" --max-jobs-run "${_nj}" JOB=1:"${_nj}" "${_logdir}"/asr_inference.JOB.log \ - python -m funasr.bin.asr_inference_launch \ - --batch_size 1 \ - --ngpu "${_ngpu}" \ - --njob ${njob} \ - --gpuid_list ${gpuid_list} \ - --data_path_and_name_and_type "${_data}/${scp},speech,${type}" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --key_file "${_logdir}"/keys.JOB.scp \ - --asr_train_config "${asr_exp}"/config.yaml \ - --asr_model_file "${asr_exp}"/"${inference_asr_model}" \ - --output_dir "${_logdir}"/output.JOB \ - --mode paraformer \ - ${_opts} - - for f in token token_int score text; do - if [ -f "${_logdir}/output.1/1best_recog/${f}" ]; then - for i in $(seq "${_nj}"); do - cat "${_logdir}/output.${i}/1best_recog/${f}" - done | sort -k1 >"${_dir}/${f}" - fi - done - python utils/proce_text.py ${_dir}/text ${_dir}/text.proc - python utils/proce_text.py ${_data}/text ${_data}/text.proc - python utils/compute_wer.py ${_data}/text.proc ${_dir}/text.proc ${_dir}/text.cer - tail -n 3 ${_dir}/text.cer > ${_dir}/text.cer.txt - cat ${_dir}/text.cer.txt - done -fi - -# Prepare files for ModelScope fine-tuning and inference -if [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then - echo "stage 6: ModelScope Preparation" - cp ${feats_dir}/data/${train_set}/cmvn/am.mvn ${exp_dir}/exp/${model_dir}/am.mvn - vocab_size=$(cat ${token_list} | wc -l) - python utils/gen_modelscope_configuration.py \ - --am_model_name $inference_asr_model \ - --mode paraformer \ - --model_name paraformer \ - --dataset aishell \ - --output_dir $exp_dir/exp/$model_dir \ - --vocab_size $vocab_size \ - --nat _nat \ - --tag $tag -fi \ No newline at end of file diff --git a/egs/aishell/paraformer/utils b/egs/aishell/paraformer/utils deleted file mode 120000 index 0853fce5d..000000000 --- a/egs/aishell/paraformer/utils +++ /dev/null @@ -1 +0,0 @@ -../transformer/utils/ \ No newline at end of file diff --git a/egs/aishell/paraformerbert/README.md b/egs/aishell/paraformerbert/README.md deleted file mode 100644 index ffce9493e..000000000 --- a/egs/aishell/paraformerbert/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# ParaformerBert + specaug + speed perturbation + specaugmentation -## Environments -- date: `Mon Nov 21 13:25:30 CST 2022` -- python version: `3.7.12` -- FunASR version: `0.1.0` -- pytorch version: `pytorch 1.7.0` - -## Config files -- train config: conf/train_asr_paraformerbert_conformer_12e_6d_2048_256.yaml -- model size: 46M -- lm config: LM was not used -- decode config: conf/decode_asr_transformer_noctc_1best.yaml (CTC was not used) - -## Results (CER) -| testset | CER(%) | -|:-----------:|:-------:| -| dev | 4.30 | -| test | 4.80 | \ No newline at end of file diff --git a/egs/aishell/paraformerbert/conf/decode_asr_transformer.yaml b/egs/aishell/paraformerbert/conf/decode_asr_transformer.yaml deleted file mode 100644 index a147fa79d..000000000 --- a/egs/aishell/paraformerbert/conf/decode_asr_transformer.yaml +++ /dev/null @@ -1,6 +0,0 @@ -beam_size: 10 -penalty: 0.0 -maxlenratio: 0.0 -minlenratio: 0.0 -ctc_weight: 0.5 -lm_weight: 0.7 diff --git a/egs/aishell/paraformerbert/conf/decode_asr_transformer_noctc_1best.yaml b/egs/aishell/paraformerbert/conf/decode_asr_transformer_noctc_1best.yaml deleted file mode 100644 index 5436b12e4..000000000 --- a/egs/aishell/paraformerbert/conf/decode_asr_transformer_noctc_1best.yaml +++ /dev/null @@ -1,6 +0,0 @@ -beam_size: 1 -penalty: 0.0 -maxlenratio: 0.0 -minlenratio: 0.0 -ctc_weight: 0.0 -lm_weight: 0.15 diff --git a/egs/aishell/paraformerbert/conf/train_asr_paraformerbert_conformer_12e_6d_2048_256.yaml b/egs/aishell/paraformerbert/conf/train_asr_paraformerbert_conformer_12e_6d_2048_256.yaml deleted file mode 100644 index f2652e8e1..000000000 --- a/egs/aishell/paraformerbert/conf/train_asr_paraformerbert_conformer_12e_6d_2048_256.yaml +++ /dev/null @@ -1,112 +0,0 @@ -# network architecture -# encoder related -encoder: conformer -encoder_conf: - output_size: 256 # dimension of attention - attention_heads: 4 - linear_units: 2048 # the number of units of position-wise feed forward - num_blocks: 12 # the number of encoder blocks - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - attention_dropout_rate: 0.0 - input_layer: conv2d # encoder architecture type - normalize_before: true - pos_enc_layer_type: rel_pos - selfattention_layer_type: rel_selfattn - activation_type: swish - macaron_style: true - use_cnn_module: true - cnn_module_kernel: 15 - -# decoder related -decoder: paraformer_decoder_san -decoder_conf: - attention_heads: 4 - linear_units: 2048 - num_blocks: 6 - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - self_attention_dropout_rate: 0.0 - src_attention_dropout_rate: 0.0 - -# frontend related -frontend: wav_frontend -frontend_conf: - fs: 16000 - window: hamming - n_mels: 80 - frame_length: 25 - frame_shift: 10 - lfr_m: 1 - lfr_n: 1 - -# hybrid CTC/attention -model: paraformer_bert -model_conf: - ctc_weight: 0.3 - lsm_weight: 0.1 # label smoothing option - length_normalized_loss: false - predictor_weight: 1.0 - sampling_ratio: 0.4 - embeds_id: 3 - embed_dims: 768 - embeds_loss_weight: 2.0 - -# optimization related -accum_grad: 1 -grad_clip: 5 -max_epoch: 150 -val_scheduler_criterion: - - valid - - acc -best_model_criterion: -- - valid - - acc - - max -keep_nbest_models: 10 - -optim: adam -optim_conf: - lr: 0.0005 -scheduler: warmuplr -scheduler_conf: - warmup_steps: 30000 - -specaug: specaug -specaug_conf: - apply_time_warp: true - time_warp_window: 5 - time_warp_mode: bicubic - apply_freq_mask: true - freq_mask_width_range: - - 0 - - 30 - num_freq_mask: 2 - apply_time_mask: true - time_mask_width_range: - - 0 - - 40 - num_time_mask: 2 - -predictor: cif_predictor -predictor_conf: - idim: 256 - threshold: 1.0 - l_order: 1 - r_order: 1 - tail_threshold: 0.45 - -dataset_conf: - data_names: speech,text,embed - data_types: sound,text,kaldi_ark - shuffle: True - shuffle_conf: - shuffle_size: 2048 - sort_size: 500 - batch_conf: - batch_type: token - batch_size: 25000 - num_workers: 8 - -log_interval: 50 -normalize: None \ No newline at end of file diff --git a/egs/aishell/paraformerbert/local/aishell_data_prep.sh b/egs/aishell/paraformerbert/local/aishell_data_prep.sh deleted file mode 100755 index 83f489b3c..000000000 --- a/egs/aishell/paraformerbert/local/aishell_data_prep.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash - -# Copyright 2017 Xingyu Na -# Apache 2.0 - -#. ./path.sh || exit 1; - -if [ $# != 3 ]; then - echo "Usage: $0 " - echo " $0 /export/a05/xna/data/data_aishell/wav /export/a05/xna/data/data_aishell/transcript data" - exit 1; -fi - -aishell_audio_dir=$1 -aishell_text=$2/aishell_transcript_v0.8.txt -output_dir=$3 - -train_dir=$output_dir/data/local/train -dev_dir=$output_dir/data/local/dev -test_dir=$output_dir/data/local/test -tmp_dir=$output_dir/data/local/tmp - -mkdir -p $train_dir -mkdir -p $dev_dir -mkdir -p $test_dir -mkdir -p $tmp_dir - -# data directory check -if [ ! -d $aishell_audio_dir ] || [ ! -f $aishell_text ]; then - echo "Error: $0 requires two directory arguments" - exit 1; -fi - -# find wav audio file for train, dev and test resp. -find $aishell_audio_dir -iname "*.wav" > $tmp_dir/wav.flist -n=`cat $tmp_dir/wav.flist | wc -l` -[ $n -ne 141925 ] && \ - echo Warning: expected 141925 data data files, found $n - -grep -i "wav/train" $tmp_dir/wav.flist > $train_dir/wav.flist || exit 1; -grep -i "wav/dev" $tmp_dir/wav.flist > $dev_dir/wav.flist || exit 1; -grep -i "wav/test" $tmp_dir/wav.flist > $test_dir/wav.flist || exit 1; - -rm -r $tmp_dir - -# Transcriptions preparation -for dir in $train_dir $dev_dir $test_dir; do - echo Preparing $dir transcriptions - sed -e 's/\.wav//' $dir/wav.flist | awk -F '/' '{print $NF}' > $dir/utt.list - paste -d' ' $dir/utt.list $dir/wav.flist > $dir/wav.scp_all - utils/filter_scp.pl -f 1 $dir/utt.list $aishell_text > $dir/transcripts.txt - awk '{print $1}' $dir/transcripts.txt > $dir/utt.list - utils/filter_scp.pl -f 1 $dir/utt.list $dir/wav.scp_all | sort -u > $dir/wav.scp - sort -u $dir/transcripts.txt > $dir/text -done - -mkdir -p $output_dir/data/train $output_dir/data/dev $output_dir/data/test - -for f in wav.scp text; do - cp $train_dir/$f $output_dir/data/train/$f || exit 1; - cp $dev_dir/$f $output_dir/data/dev/$f || exit 1; - cp $test_dir/$f $output_dir/data/test/$f || exit 1; -done - -echo "$0: AISHELL data preparation succeeded" -exit 0; diff --git a/egs/aishell/paraformerbert/local/download_and_untar.sh b/egs/aishell/paraformerbert/local/download_and_untar.sh deleted file mode 100755 index d98255915..000000000 --- a/egs/aishell/paraformerbert/local/download_and_untar.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2014 Johns Hopkins University (author: Daniel Povey) -# 2017 Xingyu Na -# Apache 2.0 - -remove_archive=false - -if [ "$1" == --remove-archive ]; then - remove_archive=true - shift -fi - -if [ $# -ne 3 ]; then - echo "Usage: $0 [--remove-archive] " - echo "e.g.: $0 /export/a05/xna/data www.openslr.org/resources/33 data_aishell" - echo "With --remove-archive it will remove the archive after successfully un-tarring it." - echo " can be one of: data_aishell, resource_aishell." -fi - -data=$1 -url=$2 -part=$3 - -if [ ! -d "$data" ]; then - echo "$0: no such directory $data" - exit 1; -fi - -part_ok=false -list="data_aishell resource_aishell" -for x in $list; do - if [ "$part" == $x ]; then part_ok=true; fi -done -if ! $part_ok; then - echo "$0: expected to be one of $list, but got '$part'" - exit 1; -fi - -if [ -z "$url" ]; then - echo "$0: empty URL base." - exit 1; -fi - -if [ -f $data/$part/.complete ]; then - echo "$0: data part $part was already successfully extracted, nothing to do." - exit 0; -fi - -# sizes of the archive files in bytes. -sizes="15582913665 1246920" - -if [ -f $data/$part.tgz ]; then - size=$(/bin/ls -l $data/$part.tgz | awk '{print $5}') - size_ok=false - for s in $sizes; do if [ $s == $size ]; then size_ok=true; fi; done - if ! $size_ok; then - echo "$0: removing existing file $data/$part.tgz because its size in bytes $size" - echo "does not equal the size of one of the archives." - rm $data/$part.tgz - else - echo "$data/$part.tgz exists and appears to be complete." - fi -fi - -if [ ! -f $data/$part.tgz ]; then - if ! command -v wget >/dev/null; then - echo "$0: wget is not installed." - exit 1; - fi - full_url=$url/$part.tgz - echo "$0: downloading data from $full_url. This may take some time, please be patient." - - cd $data || exit 1 - if ! wget --no-check-certificate $full_url; then - echo "$0: error executing wget $full_url" - exit 1; - fi -fi - -cd $data || exit 1 - -if ! tar -xvzf $part.tgz; then - echo "$0: error un-tarring archive $data/$part.tgz" - exit 1; -fi - -touch $data/$part/.complete - -if [ $part == "data_aishell" ]; then - cd $data/$part/wav || exit 1 - for wav in ./*.tar.gz; do - echo "Extracting wav from $wav" - tar -zxf $wav && rm $wav - done -fi - -echo "$0: Successfully downloaded and un-tarred $data/$part.tgz" - -if $remove_archive; then - echo "$0: removing $data/$part.tgz file since --remove-archive option was supplied." - rm $data/$part.tgz -fi - -exit 0; diff --git a/egs/aishell/paraformerbert/local/extract_embeds.sh b/egs/aishell/paraformerbert/local/extract_embeds.sh deleted file mode 100755 index ca0c878ec..000000000 --- a/egs/aishell/paraformerbert/local/extract_embeds.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env bash - -stage=1 -stop_stage=3 - -bert_model_name="bert-base-chinese" -raw_dataset_path="../DATA" -nj=64 -model_path=${bert_model_name} - -. utils/parse_options.sh || exit 1; - -for data_set in train dev test;do - scp=$raw_dataset_path/data/${data_set}/text - local_scp_dir_raw=${raw_dataset_path}/data/embeds/${data_set} - local_scp_dir=$local_scp_dir_raw/split$nj - local_records_dir=$local_scp_dir_raw/ark - - mkdir -p $local_records_dir - mkdir -p $local_scp_dir - - split_scps="" - for JOB in $(seq ${nj}); do - split_scps="$split_scps $local_scp_dir/data.$JOB.text" - done - - utils/split_scp.pl $scp ${split_scps} - - - for num in {0..7};do - tmp=`expr $num \* 4` - - if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then - for idx in {1..4}; do - JOB=`expr $tmp + $idx` - echo "proces jobid=$JOB" - { - beg=0 - gpu=`expr $beg + $idx` - echo ${local_scp_dir}/log.${JOB} - python utils/extract_embeds.py $local_scp_dir/data.$JOB.text ${local_records_dir}/embeds.${JOB}.ark ${local_records_dir}/embeds.${JOB}.scp ${local_records_dir}/embeds.${JOB}.shape ${gpu} ${model_path} &> ${local_scp_dir}/log.${JOB} - } & - done - wait - fi - done - - if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then - for JOB in $(seq ${nj}); do - cat ${local_records_dir}/embeds.${JOB}.scp || exit 1; - done > ${local_scp_dir_raw}/embeds.scp - - for JOB in $(seq ${nj}); do - cat ${local_records_dir}/embeds.${JOB}.shape || exit 1; - done > ${local_scp_dir_raw}/embeds.shape - fi - - cp ${local_scp_dir_raw}/embeds.scp ${raw_dataset_path}/data/${data_set}/embeds.scp -done - -echo "embeds is in: ${local_scp_dir_raw}" -echo "success" \ No newline at end of file diff --git a/egs/aishell/paraformerbert/path.sh b/egs/aishell/paraformerbert/path.sh deleted file mode 100755 index 7972642d0..000000000 --- a/egs/aishell/paraformerbert/path.sh +++ /dev/null @@ -1,5 +0,0 @@ -export FUNASR_DIR=$PWD/../../.. - -# NOTE(kan-bayashi): Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C -export PYTHONIOENCODING=UTF-8 -export PATH=$FUNASR_DIR/funasr/bin:$PATH diff --git a/egs/aishell/paraformerbert/run.sh b/egs/aishell/paraformerbert/run.sh deleted file mode 100755 index efc831fda..000000000 --- a/egs/aishell/paraformerbert/run.sh +++ /dev/null @@ -1,237 +0,0 @@ -#!/usr/bin/env bash - -. ./path.sh || exit 1; - -# machines configuration -CUDA_VISIBLE_DEVICES="0,1" -gpu_num=2 -count=1 -gpu_inference=true # Whether to perform gpu decoding, set false for cpu decoding -# for gpu decoding, inference_nj=ngpu*njob; for cpu decoding, inference_nj=njob -njob=1 -train_cmd=utils/run.pl -infer_cmd=utils/run.pl - -# general configuration -feats_dir="../DATA" #feature output dictionary, for large data -exp_dir="." -lang=zh -token_type=char -type=sound -scp=wav.scp -speed_perturb="0.9 1.0 1.1" -stage=0 -stop_stage=5 - -skip_extract_embed=false -bert_model_name="bert-base-chinese" - -# feature configuration -feats_dim=80 -nj=64 - -# data -raw_data=../raw_data -data_url=www.openslr.org/resources/33 - -# exp tag -tag="exp1" - -. utils/parse_options.sh || exit 1; - -# Set bash to 'debug' mode, it will exit on : -# -e 'error', -u 'undefined variable', -o ... 'error in pipeline', -x 'print commands', -set -e -set -u -set -o pipefail - -train_set=train -valid_set=dev -test_sets="dev test" - -asr_config=conf/train_asr_paraformerbert_conformer_12e_6d_2048_256.yaml -model_dir="baseline_$(basename "${asr_config}" .yaml)_${lang}_${token_type}_${tag}" - -inference_config=conf/decode_asr_transformer_noctc_1best.yaml -inference_asr_model=valid.acc.ave_10best.pb - -# you can set gpu num for decoding here -gpuid_list=$CUDA_VISIBLE_DEVICES # set gpus for decoding, the same as training stage by default -ngpu=$(echo $gpuid_list | awk -F "," '{print NF}') - -if ${gpu_inference}; then - inference_nj=$[${ngpu}*${njob}] - _ngpu=1 -else - inference_nj=$njob - _ngpu=0 -fi - -if [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then - echo "stage -1: Data Download" - local/download_and_untar.sh ${raw_data} ${data_url} data_aishell - local/download_and_untar.sh ${raw_data} ${data_url} resource_aishell -fi - - -if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then - echo "stage 0: Data preparation" - # Data preparation - local/aishell_data_prep.sh ${raw_data}/data_aishell/wav ${raw_data}/data_aishell/transcript ${feats_dir} - for x in train dev test; do - cp ${feats_dir}/data/${x}/text ${feats_dir}/data/${x}/text.org - paste -d " " <(cut -f 1 -d" " ${feats_dir}/data/${x}/text.org) <(cut -f 2- -d" " ${feats_dir}/data/${x}/text.org | tr -d " ") \ - > ${feats_dir}/data/${x}/text - utils/text2token.py -n 1 -s 1 ${feats_dir}/data/${x}/text > ${feats_dir}/data/${x}/text.org - mv ${feats_dir}/data/${x}/text.org ${feats_dir}/data/${x}/text - done -fi - -if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then - echo "stage 1: Feature and CMVN Generation" - utils/compute_cmvn.sh --fbankdir ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config_file "$asr_config" --scale 1.0 -fi - -token_list=${feats_dir}/data/${lang}_token_list/$token_type/tokens.txt -echo "dictionary: ${token_list}" -if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then - echo "stage 2: Dictionary Preparation" - mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/ - - echo "make a dictionary" - echo "" > ${token_list} - echo "" >> ${token_list} - echo "" >> ${token_list} - utils/text2token.py -s 1 -n 1 --space "" ${feats_dir}/data/$train_set/text | cut -f 2- -d" " | tr " " "\n" \ - | sort | uniq | grep -a -v -e '^\s*$' | awk '{print $0}' >> ${token_list} - echo "" >> ${token_list} -fi - -# LM Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then - echo "stage 3: LM Training" -fi - -# ASR Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then - echo "stage 4: ASR Training" - if ! "${skip_extract_embed}"; then - echo "extract embeddings..." - local/extract_embeds.sh \ - --bert_model_name ${bert_model_name} \ - --raw_dataset_path ${feats_dir} \ - --nj $nj - fi - mkdir -p ${exp_dir}/exp/${model_dir} - mkdir -p ${exp_dir}/exp/${model_dir}/log - INIT_FILE=${exp_dir}/exp/${model_dir}/ddp_init - if [ -f $INIT_FILE ];then - rm -f $INIT_FILE - fi - init_method=file://$(readlink -f $INIT_FILE) - echo "$0: init method is $init_method" - for ((i = 0; i < $gpu_num; ++i)); do - { - rank=$i - local_rank=$i - gpu_id=$(echo $CUDA_VISIBLE_DEVICES | cut -d',' -f$[$i+1]) - train.py \ - --task_name asr \ - --gpu_id $gpu_id \ - --use_preprocessor true \ - --token_type $token_type \ - --token_list $token_list \ - --data_dir ${feats_dir}/data \ - --train_set ${train_set} \ - --valid_set ${valid_set} \ - --data_file_names "wav.scp,text,embeds.scp" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --speed_perturb ${speed_perturb} \ - --resume true \ - --output_dir ${exp_dir}/exp/${model_dir} \ - --config $asr_config \ - --ngpu $gpu_num \ - --num_worker_count $count \ - --dist_init_method $init_method \ - --dist_world_size $world_size \ - --dist_rank $rank \ - --local_rank $local_rank 1> ${exp_dir}/exp/${model_dir}/log/train.log.$i 2>&1 - } & - done - wait -fi - -# Testing Stage -if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then - echo "stage 5: Inference" - for dset in ${test_sets}; do - asr_exp=${exp_dir}/exp/${model_dir} - inference_tag="$(basename "${inference_config}" .yaml)" - _dir="${asr_exp}/${inference_tag}/${inference_asr_model}/${dset}" - _logdir="${_dir}/logdir" - if [ -d ${_dir} ]; then - echo "${_dir} is already exists. if you want to decode again, please delete this dir first." - exit 0 - fi - mkdir -p "${_logdir}" - _data="${feats_dir}/data/${dset}" - key_file=${_data}/${scp} - num_scp_file="$(<${key_file} wc -l)" - _nj=$([ $inference_nj -le $num_scp_file ] && echo "$inference_nj" || echo "$num_scp_file") - split_scps= - for n in $(seq "${_nj}"); do - split_scps+=" ${_logdir}/keys.${n}.scp" - done - # shellcheck disable=SC2086 - utils/split_scp.pl "${key_file}" ${split_scps} - _opts= - if [ -n "${inference_config}" ]; then - _opts+="--config ${inference_config} " - fi - ${infer_cmd} --gpu "${_ngpu}" --max-jobs-run "${_nj}" JOB=1:"${_nj}" "${_logdir}"/asr_inference.JOB.log \ - python -m funasr.bin.asr_inference_launch \ - --batch_size 1 \ - --ngpu "${_ngpu}" \ - --njob ${njob} \ - --gpuid_list ${gpuid_list} \ - --data_path_and_name_and_type "${_data}/${scp},speech,${type}" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --key_file "${_logdir}"/keys.JOB.scp \ - --asr_train_config "${asr_exp}"/config.yaml \ - --asr_model_file "${asr_exp}"/"${inference_asr_model}" \ - --output_dir "${_logdir}"/output.JOB \ - --mode paraformer \ - ${_opts} - - for f in token token_int score text; do - if [ -f "${_logdir}/output.1/1best_recog/${f}" ]; then - for i in $(seq "${_nj}"); do - cat "${_logdir}/output.${i}/1best_recog/${f}" - done | sort -k1 >"${_dir}/${f}" - fi - done - python utils/proce_text.py ${_dir}/text ${_dir}/text.proc - python utils/proce_text.py ${_data}/text ${_data}/text.proc - python utils/compute_wer.py ${_data}/text.proc ${_dir}/text.proc ${_dir}/text.cer - tail -n 3 ${_dir}/text.cer > ${_dir}/text.cer.txt - cat ${_dir}/text.cer.txt - done -fi - -# Prepare files for ModelScope fine-tuning and inference -if [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then - echo "stage 6: ModelScope Preparation" - cp ${feats_dir}/data/${train_set}/cmvn/am.mvn ${exp_dir}/exp/${model_dir}/am.mvn - vocab_size=$(cat ${token_list} | wc -l) - python utils/gen_modelscope_configuration.py \ - --am_model_name $inference_asr_model \ - --mode paraformer \ - --model_name paraformer_bert \ - --dataset aishell \ - --output_dir $exp_dir/exp/$model_dir \ - --vocab_size $vocab_size \ - --nat _nat \ - --tag $tag -fi \ No newline at end of file diff --git a/egs/aishell/paraformerbert/utils b/egs/aishell/paraformerbert/utils deleted file mode 120000 index 0853fce5d..000000000 --- a/egs/aishell/paraformerbert/utils +++ /dev/null @@ -1 +0,0 @@ -../transformer/utils/ \ No newline at end of file diff --git a/egs/aishell/rnnt/README.md b/egs/aishell/rnnt/README.md deleted file mode 100644 index 817c9b2c0..000000000 --- a/egs/aishell/rnnt/README.md +++ /dev/null @@ -1,18 +0,0 @@ - -# Streaming RNN-T Result - -## Training Config -- 8 gpu(Tesla V100) -- Feature info: using 80 dims fbank, global cmvn, speed perturb(0.9, 1.0, 1.1), specaugment -- Train config: conf/train_conformer_rnnt_unified.yaml -- chunk config: chunk size 16, 1 left chunk -- LM config: LM was not used -- Model size: 90M - -## Results (CER) -- Decode config: conf/decode_rnnt_conformer_streaming.yaml - -| testset | CER(%) | -|:-----------:|:-------:| -| dev | 5.43 | -| test | 6.04 | diff --git a/egs/aishell/rnnt/conf/decode_rnnt_conformer_streaming.yaml b/egs/aishell/rnnt/conf/decode_rnnt_conformer_streaming.yaml deleted file mode 100644 index 26e43c64d..000000000 --- a/egs/aishell/rnnt/conf/decode_rnnt_conformer_streaming.yaml +++ /dev/null @@ -1,8 +0,0 @@ -# The conformer transducer decoding configuration from @jeon30c -beam_size: 10 -simu_streaming: false -streaming: true -chunk_size: 16 -left_context: 16 -right_context: 0 - diff --git a/egs/aishell/rnnt/conf/decode_rnnt_conformer_streaming_simu.yaml b/egs/aishell/rnnt/conf/decode_rnnt_conformer_streaming_simu.yaml deleted file mode 100644 index dc3eff2a5..000000000 --- a/egs/aishell/rnnt/conf/decode_rnnt_conformer_streaming_simu.yaml +++ /dev/null @@ -1,5 +0,0 @@ -# The conformer transducer decoding configuration from @jeon30c -beam_size: 10 -simu_streaming: true -streaming: false -chunk_size: 16 diff --git a/egs/aishell/rnnt/conf/train_conformer_rnnt_unified.yaml b/egs/aishell/rnnt/conf/train_conformer_rnnt_unified.yaml deleted file mode 100644 index a1f27a3dd..000000000 --- a/egs/aishell/rnnt/conf/train_conformer_rnnt_unified.yaml +++ /dev/null @@ -1,99 +0,0 @@ -encoder: chunk_conformer -encoder_conf: - activation_type: swish - positional_dropout_rate: 0.5 - time_reduction_factor: 2 - unified_model_training: true - default_chunk_size: 16 - jitter_range: 4 - left_chunk_size: 1 - embed_vgg_like: false - subsampling_factor: 4 - linear_units: 2048 - output_size: 512 - attention_heads: 8 - dropout_rate: 0.5 - positional_dropout_rate: 0.5 - attention_dropout_rate: 0.5 - cnn_module_kernel: 15 - num_blocks: 12 - -# decoder related -rnnt_decoder: rnnt -rnnt_decoder_conf: - embed_size: 512 - hidden_size: 512 - embed_dropout_rate: 0.5 - dropout_rate: 0.5 -joint_network_conf: - joint_space_size: 512 - -# frontend related -frontend: wav_frontend -frontend_conf: - fs: 16000 - window: hamming - n_mels: 80 - frame_length: 25 - frame_shift: 10 - lfr_m: 1 - lfr_n: 1 - - -# Auxiliary CTC -model: rnnt_unified -model_conf: - auxiliary_ctc_weight: 0.0 - -# minibatch related -use_amp: true - -# optimization related -accum_grad: 1 -grad_clip: 5 -max_epoch: 120 -val_scheduler_criterion: - - valid - - loss -best_model_criterion: -- - valid - - cer_transducer_chunk - - min -keep_nbest_models: 10 - -optim: adam -optim_conf: - lr: 0.001 -scheduler: warmuplr -scheduler_conf: - warmup_steps: 25000 - -specaug: specaug -specaug_conf: - apply_time_warp: true - time_warp_window: 5 - time_warp_mode: bicubic - apply_freq_mask: true - freq_mask_width_range: - - 0 - - 40 - num_freq_mask: 2 - apply_time_mask: true - time_mask_width_range: - - 0 - - 50 - num_time_mask: 5 - -dataset_conf: - data_names: speech,text - data_types: sound,text - shuffle: True - shuffle_conf: - shuffle_size: 2048 - sort_size: 500 - batch_conf: - batch_type: token - batch_size: 16000 - num_workers: 8 - -log_interval: 50 diff --git a/egs/aishell/rnnt/local/aishell_data_prep.sh b/egs/aishell/rnnt/local/aishell_data_prep.sh deleted file mode 100755 index 83f489b3c..000000000 --- a/egs/aishell/rnnt/local/aishell_data_prep.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash - -# Copyright 2017 Xingyu Na -# Apache 2.0 - -#. ./path.sh || exit 1; - -if [ $# != 3 ]; then - echo "Usage: $0 " - echo " $0 /export/a05/xna/data/data_aishell/wav /export/a05/xna/data/data_aishell/transcript data" - exit 1; -fi - -aishell_audio_dir=$1 -aishell_text=$2/aishell_transcript_v0.8.txt -output_dir=$3 - -train_dir=$output_dir/data/local/train -dev_dir=$output_dir/data/local/dev -test_dir=$output_dir/data/local/test -tmp_dir=$output_dir/data/local/tmp - -mkdir -p $train_dir -mkdir -p $dev_dir -mkdir -p $test_dir -mkdir -p $tmp_dir - -# data directory check -if [ ! -d $aishell_audio_dir ] || [ ! -f $aishell_text ]; then - echo "Error: $0 requires two directory arguments" - exit 1; -fi - -# find wav audio file for train, dev and test resp. -find $aishell_audio_dir -iname "*.wav" > $tmp_dir/wav.flist -n=`cat $tmp_dir/wav.flist | wc -l` -[ $n -ne 141925 ] && \ - echo Warning: expected 141925 data data files, found $n - -grep -i "wav/train" $tmp_dir/wav.flist > $train_dir/wav.flist || exit 1; -grep -i "wav/dev" $tmp_dir/wav.flist > $dev_dir/wav.flist || exit 1; -grep -i "wav/test" $tmp_dir/wav.flist > $test_dir/wav.flist || exit 1; - -rm -r $tmp_dir - -# Transcriptions preparation -for dir in $train_dir $dev_dir $test_dir; do - echo Preparing $dir transcriptions - sed -e 's/\.wav//' $dir/wav.flist | awk -F '/' '{print $NF}' > $dir/utt.list - paste -d' ' $dir/utt.list $dir/wav.flist > $dir/wav.scp_all - utils/filter_scp.pl -f 1 $dir/utt.list $aishell_text > $dir/transcripts.txt - awk '{print $1}' $dir/transcripts.txt > $dir/utt.list - utils/filter_scp.pl -f 1 $dir/utt.list $dir/wav.scp_all | sort -u > $dir/wav.scp - sort -u $dir/transcripts.txt > $dir/text -done - -mkdir -p $output_dir/data/train $output_dir/data/dev $output_dir/data/test - -for f in wav.scp text; do - cp $train_dir/$f $output_dir/data/train/$f || exit 1; - cp $dev_dir/$f $output_dir/data/dev/$f || exit 1; - cp $test_dir/$f $output_dir/data/test/$f || exit 1; -done - -echo "$0: AISHELL data preparation succeeded" -exit 0; diff --git a/egs/aishell/rnnt/path.sh b/egs/aishell/rnnt/path.sh deleted file mode 100644 index 7972642d0..000000000 --- a/egs/aishell/rnnt/path.sh +++ /dev/null @@ -1,5 +0,0 @@ -export FUNASR_DIR=$PWD/../../.. - -# NOTE(kan-bayashi): Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C -export PYTHONIOENCODING=UTF-8 -export PATH=$FUNASR_DIR/funasr/bin:$PATH diff --git a/egs/aishell/rnnt/run.sh b/egs/aishell/rnnt/run.sh deleted file mode 100755 index 9facc8ba6..000000000 --- a/egs/aishell/rnnt/run.sh +++ /dev/null @@ -1,210 +0,0 @@ -#!/usr/bin/env bash - -. ./path.sh || exit 1; - -# machines configuration -CUDA_VISIBLE_DEVICES="0,1,2,3,4,5,6,7" -gpu_num=8 -count=1 -gpu_inference=true # Whether to perform gpu decoding, set false for cpu decoding -# for gpu decoding, inference_nj=ngpu*njob; for cpu decoding, inference_nj=njob -njob=5 -train_cmd=utils/run.pl -infer_cmd=utils/run.pl - -# general configuration -feats_dir="../DATA" #feature output dictionary -exp_dir="." -lang=zh -token_type=char -type=sound -scp=wav.scp -speed_perturb="0.9 1.0 1.1" -stage=0 -stop_stage=5 - -# feature configuration -feats_dim=80 -nj=64 - -# data -raw_data=../raw_data -data_url=www.openslr.org/resources/33 - -# exp tag -tag="exp1" - -. utils/parse_options.sh || exit 1; - -# Set bash to 'debug' mode, it will exit on : -# -e 'error', -u 'undefined variable', -o ... 'error in pipeline', -x 'print commands', -set -e -set -u -set -o pipefail - -train_set=train -valid_set=dev -test_sets="dev test" - -asr_config=conf/train_conformer_rnnt_unified.yaml -model_dir="baseline_$(basename "${asr_config}" .yaml)_${lang}_${token_type}_${tag}" - -inference_config=conf/decode_rnnt_conformer_streaming.yaml -inference_asr_model=valid.cer_transducer_chunk.ave_10best.pb - -# you can set gpu num for decoding here -gpuid_list=$CUDA_VISIBLE_DEVICES # set gpus for decoding, the same as training stage by default -ngpu=$(echo $gpuid_list | awk -F "," '{print NF}') - -if ${gpu_inference}; then - inference_nj=$[${ngpu}*${njob}] - _ngpu=1 -else - inference_nj=$njob - _ngpu=0 -fi - -if [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then - echo "stage -1: Data Download" - local/download_and_untar.sh ${raw_data} ${data_url} data_aishell - local/download_and_untar.sh ${raw_data} ${data_url} resource_aishell -fi - -if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then - echo "stage 0: Data preparation" - # Data preparation - local/aishell_data_prep.sh ${raw_data}/data_aishell/wav ${raw_data}/data_aishell/transcript ${feats_dir} - for x in train dev test; do - cp ${feats_dir}/data/${x}/text ${feats_dir}/data/${x}/text.org - paste -d " " <(cut -f 1 -d" " ${feats_dir}/data/${x}/text.org) <(cut -f 2- -d" " ${feats_dir}/data/${x}/text.org | tr -d " ") \ - > ${feats_dir}/data/${x}/text - utils/text2token.py -n 1 -s 1 ${feats_dir}/data/${x}/text > ${feats_dir}/data/${x}/text.org - mv ${feats_dir}/data/${x}/text.org ${feats_dir}/data/${x}/text - done -fi - -if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then - echo "stage 1: Feature and CMVN Generation" - utils/compute_cmvn.sh --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} ${feats_dir}/data/${train_set} -fi - -token_list=${feats_dir}/data/${lang}_token_list/char/tokens.txt -echo "dictionary: ${token_list}" -if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then - echo "stage 2: Dictionary Preparation" - mkdir -p ${feats_dir}/data/${lang}_token_list/char/ - - echo "make a dictionary" - echo "" > ${token_list} - echo "" >> ${token_list} - echo "" >> ${token_list} - utils/text2token.py -s 1 -n 1 --space "" ${feats_dir}/data/$train_set/text | cut -f 2- -d" " | tr " " "\n" \ - | sort | uniq | grep -a -v -e '^\s*$' | awk '{print $0}' >> ${token_list} - echo "" >> ${token_list} -fi - -# LM Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then - echo "stage 3: LM Training" -fi - -# ASR Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then - echo "stage 4: ASR Training" - mkdir -p ${exp_dir}/exp/${model_dir} - mkdir -p ${exp_dir}/exp/${model_dir}/log - INIT_FILE=./ddp_init - if [ -f $INIT_FILE ];then - rm -f $INIT_FILE - fi - init_method=file://$(readlink -f $INIT_FILE) - echo "$0: init method is $init_method" - for ((i = 0; i < $gpu_num; ++i)); do - { - rank=$i - local_rank=$i - gpu_id=$(echo $CUDA_VISIBLE_DEVICES | cut -d',' -f$[$i+1]) - train.py \ - --task_name asr \ - --gpu_id $gpu_id \ - --use_preprocessor true \ - --token_type char \ - --token_list $token_list \ - --data_dir ${feats_dir}/data \ - --train_set ${train_set} \ - --valid_set ${valid_set} \ - --data_file_names "wav.scp,text" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/cmvn.mvn \ - --speed_perturb ${speed_perturb} \ - --resume true \ - --output_dir ${exp_dir}/exp/${model_dir} \ - --config $asr_config \ - --ngpu $gpu_num \ - --num_worker_count $count \ - --dist_init_method $init_method \ - --dist_world_size $world_size \ - --dist_rank $rank \ - --local_rank $local_rank 1> ${exp_dir}/exp/${model_dir}/log/train.log.$i 2>&1 - } & - done - wait -fi - -# Testing Stage -if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then - echo "stage 5: Inference" - for dset in ${test_sets}; do - asr_exp=${exp_dir}/exp/${model_dir} - inference_tag="$(basename "${inference_config}" .yaml)" - _dir="${asr_exp}/${inference_tag}/${inference_asr_model}/${dset}" - _logdir="${_dir}/logdir" - if [ -d ${_dir} ]; then - echo "${_dir} is already exists. if you want to decode again, please delete this dir first." - exit 0 - fi - mkdir -p "${_logdir}" - _data="${feats_dir}/data/${dset}" - key_file=${_data}/${scp} - num_scp_file="$(<${key_file} wc -l)" - _nj=$([ $inference_nj -le $num_scp_file ] && echo "$inference_nj" || echo "$num_scp_file") - split_scps= - for n in $(seq "${_nj}"); do - split_scps+=" ${_logdir}/keys.${n}.scp" - done - # shellcheck disable=SC2086 - utils/split_scp.pl "${key_file}" ${split_scps} - _opts= - if [ -n "${inference_config}" ]; then - _opts+="--config ${inference_config} " - fi - ${infer_cmd} --gpu "${_ngpu}" --max-jobs-run "${_nj}" JOB=1:"${_nj}" "${_logdir}"/asr_inference.JOB.log \ - python -m funasr.bin.asr_inference_launch \ - --batch_size 1 \ - --ngpu "${_ngpu}" \ - --njob ${njob} \ - --gpuid_list ${gpuid_list} \ - --data_path_and_name_and_type "${_data}/${scp},speech,${type}" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/cmvn.mvn \ - --key_file "${_logdir}"/keys.JOB.scp \ - --asr_train_config "${asr_exp}"/config.yaml \ - --asr_model_file "${asr_exp}"/"${inference_asr_model}" \ - --output_dir "${_logdir}"/output.JOB \ - --mode rnnt \ - ${_opts} - - for f in token token_int score text; do - if [ -f "${_logdir}/output.1/1best_recog/${f}" ]; then - for i in $(seq "${_nj}"); do - cat "${_logdir}/output.${i}/1best_recog/${f}" - done | sort -k1 >"${_dir}/${f}" - fi - done - python utils/proce_text.py ${_dir}/text ${_dir}/text.proc - python utils/proce_text.py ${_data}/text ${_data}/text.proc - python utils/compute_wer.py ${_data}/text.proc ${_dir}/text.proc ${_dir}/text.cer - tail -n 3 ${_dir}/text.cer > ${_dir}/text.cer.txt - cat ${_dir}/text.cer.txt - done -fi diff --git a/egs/aishell/rnnt/utils b/egs/aishell/rnnt/utils deleted file mode 120000 index 4072eacc1..000000000 --- a/egs/aishell/rnnt/utils +++ /dev/null @@ -1 +0,0 @@ -../transformer/utils \ No newline at end of file diff --git a/egs/aishell/transformer/conf/decode_asr_transformer.yaml b/egs/aishell/transformer/conf/decode_asr_transformer.yaml deleted file mode 100644 index a147fa79d..000000000 --- a/egs/aishell/transformer/conf/decode_asr_transformer.yaml +++ /dev/null @@ -1,6 +0,0 @@ -beam_size: 10 -penalty: 0.0 -maxlenratio: 0.0 -minlenratio: 0.0 -ctc_weight: 0.5 -lm_weight: 0.7 diff --git a/egs/aishell/transformer/conf/train_asr_transformer.yaml b/egs/aishell/transformer/conf/train_asr_transformer.yaml deleted file mode 100644 index b38656514..000000000 --- a/egs/aishell/transformer/conf/train_asr_transformer.yaml +++ /dev/null @@ -1,88 +0,0 @@ -# network architecture -# encoder related -encoder: transformer -encoder_conf: - output_size: 256 # dimension of attention - attention_heads: 4 - linear_units: 2048 # the number of units of position-wise feed forward - num_blocks: 12 # the number of encoder blocks - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - attention_dropout_rate: 0.0 - input_layer: conv2d # encoder architecture type - normalize_before: true - -# decoder related -decoder: transformer -decoder_conf: - attention_heads: 4 - linear_units: 2048 - num_blocks: 6 - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - self_attention_dropout_rate: 0.0 - src_attention_dropout_rate: 0.0 - -# frontend related -frontend: wav_frontend -frontend_conf: - fs: 16000 - window: hamming - n_mels: 80 - frame_length: 25 - frame_shift: 10 - lfr_m: 1 - lfr_n: 1 - -# hybrid CTC/attention -model_conf: - ctc_weight: 0.3 - lsm_weight: 0.1 # label smoothing option - length_normalized_loss: false - -# optimization related -accum_grad: 1 -grad_clip: 5 -patience: none -max_epoch: 60 -val_scheduler_criterion: - - valid - - acc -best_model_criterion: -- - valid - - acc - - max -keep_nbest_models: 10 - -# NoamLR is deprecated. Use WarmupLR. -# The following is equivalent setting for NoamLR: -# -# optim: adam -# optim_conf: -# lr: 10. -# scheduler: noamlr -# scheduler_conf: -# model_size: 256 -# warmup_steps: 25000 -# -optim: adam -optim_conf: - lr: 0.002 -scheduler: warmuplr # pytorch v1.1.0+ required -scheduler_conf: - warmup_steps: 25000 - -dataset_conf: - data_names: speech,text - data_types: sound,text - shuffle: True - shuffle_conf: - shuffle_size: 2048 - sort_size: 500 - batch_conf: - batch_type: token - batch_size: 25000 - num_workers: 8 - -log_interval: 50 -normalize: None diff --git a/egs/aishell/transformer/local/aishell_data_prep.sh b/egs/aishell/transformer/local/aishell_data_prep.sh deleted file mode 100755 index 83f489b3c..000000000 --- a/egs/aishell/transformer/local/aishell_data_prep.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash - -# Copyright 2017 Xingyu Na -# Apache 2.0 - -#. ./path.sh || exit 1; - -if [ $# != 3 ]; then - echo "Usage: $0 " - echo " $0 /export/a05/xna/data/data_aishell/wav /export/a05/xna/data/data_aishell/transcript data" - exit 1; -fi - -aishell_audio_dir=$1 -aishell_text=$2/aishell_transcript_v0.8.txt -output_dir=$3 - -train_dir=$output_dir/data/local/train -dev_dir=$output_dir/data/local/dev -test_dir=$output_dir/data/local/test -tmp_dir=$output_dir/data/local/tmp - -mkdir -p $train_dir -mkdir -p $dev_dir -mkdir -p $test_dir -mkdir -p $tmp_dir - -# data directory check -if [ ! -d $aishell_audio_dir ] || [ ! -f $aishell_text ]; then - echo "Error: $0 requires two directory arguments" - exit 1; -fi - -# find wav audio file for train, dev and test resp. -find $aishell_audio_dir -iname "*.wav" > $tmp_dir/wav.flist -n=`cat $tmp_dir/wav.flist | wc -l` -[ $n -ne 141925 ] && \ - echo Warning: expected 141925 data data files, found $n - -grep -i "wav/train" $tmp_dir/wav.flist > $train_dir/wav.flist || exit 1; -grep -i "wav/dev" $tmp_dir/wav.flist > $dev_dir/wav.flist || exit 1; -grep -i "wav/test" $tmp_dir/wav.flist > $test_dir/wav.flist || exit 1; - -rm -r $tmp_dir - -# Transcriptions preparation -for dir in $train_dir $dev_dir $test_dir; do - echo Preparing $dir transcriptions - sed -e 's/\.wav//' $dir/wav.flist | awk -F '/' '{print $NF}' > $dir/utt.list - paste -d' ' $dir/utt.list $dir/wav.flist > $dir/wav.scp_all - utils/filter_scp.pl -f 1 $dir/utt.list $aishell_text > $dir/transcripts.txt - awk '{print $1}' $dir/transcripts.txt > $dir/utt.list - utils/filter_scp.pl -f 1 $dir/utt.list $dir/wav.scp_all | sort -u > $dir/wav.scp - sort -u $dir/transcripts.txt > $dir/text -done - -mkdir -p $output_dir/data/train $output_dir/data/dev $output_dir/data/test - -for f in wav.scp text; do - cp $train_dir/$f $output_dir/data/train/$f || exit 1; - cp $dev_dir/$f $output_dir/data/dev/$f || exit 1; - cp $test_dir/$f $output_dir/data/test/$f || exit 1; -done - -echo "$0: AISHELL data preparation succeeded" -exit 0; diff --git a/egs/aishell/transformer/local/download_and_untar.sh b/egs/aishell/transformer/local/download_and_untar.sh deleted file mode 100755 index d98255915..000000000 --- a/egs/aishell/transformer/local/download_and_untar.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2014 Johns Hopkins University (author: Daniel Povey) -# 2017 Xingyu Na -# Apache 2.0 - -remove_archive=false - -if [ "$1" == --remove-archive ]; then - remove_archive=true - shift -fi - -if [ $# -ne 3 ]; then - echo "Usage: $0 [--remove-archive] " - echo "e.g.: $0 /export/a05/xna/data www.openslr.org/resources/33 data_aishell" - echo "With --remove-archive it will remove the archive after successfully un-tarring it." - echo " can be one of: data_aishell, resource_aishell." -fi - -data=$1 -url=$2 -part=$3 - -if [ ! -d "$data" ]; then - echo "$0: no such directory $data" - exit 1; -fi - -part_ok=false -list="data_aishell resource_aishell" -for x in $list; do - if [ "$part" == $x ]; then part_ok=true; fi -done -if ! $part_ok; then - echo "$0: expected to be one of $list, but got '$part'" - exit 1; -fi - -if [ -z "$url" ]; then - echo "$0: empty URL base." - exit 1; -fi - -if [ -f $data/$part/.complete ]; then - echo "$0: data part $part was already successfully extracted, nothing to do." - exit 0; -fi - -# sizes of the archive files in bytes. -sizes="15582913665 1246920" - -if [ -f $data/$part.tgz ]; then - size=$(/bin/ls -l $data/$part.tgz | awk '{print $5}') - size_ok=false - for s in $sizes; do if [ $s == $size ]; then size_ok=true; fi; done - if ! $size_ok; then - echo "$0: removing existing file $data/$part.tgz because its size in bytes $size" - echo "does not equal the size of one of the archives." - rm $data/$part.tgz - else - echo "$data/$part.tgz exists and appears to be complete." - fi -fi - -if [ ! -f $data/$part.tgz ]; then - if ! command -v wget >/dev/null; then - echo "$0: wget is not installed." - exit 1; - fi - full_url=$url/$part.tgz - echo "$0: downloading data from $full_url. This may take some time, please be patient." - - cd $data || exit 1 - if ! wget --no-check-certificate $full_url; then - echo "$0: error executing wget $full_url" - exit 1; - fi -fi - -cd $data || exit 1 - -if ! tar -xvzf $part.tgz; then - echo "$0: error un-tarring archive $data/$part.tgz" - exit 1; -fi - -touch $data/$part/.complete - -if [ $part == "data_aishell" ]; then - cd $data/$part/wav || exit 1 - for wav in ./*.tar.gz; do - echo "Extracting wav from $wav" - tar -zxf $wav && rm $wav - done -fi - -echo "$0: Successfully downloaded and un-tarred $data/$part.tgz" - -if $remove_archive; then - echo "$0: removing $data/$part.tgz file since --remove-archive option was supplied." - rm $data/$part.tgz -fi - -exit 0; diff --git a/egs/aishell/transformer/path.sh b/egs/aishell/transformer/path.sh deleted file mode 100755 index b4064e152..000000000 --- a/egs/aishell/transformer/path.sh +++ /dev/null @@ -1,7 +0,0 @@ -export FUNASR_DIR=$PWD/../../.. - -# NOTE(kan-bayashi): Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C -export PYTHONIOENCODING=UTF-8 -export PATH=$FUNASR_DIR/funasr/bin:$PATH - -export OMP_NUM_THREADS=1 diff --git a/egs/aishell/transformer/run.sh b/egs/aishell/transformer/run.sh deleted file mode 100755 index e492fb201..000000000 --- a/egs/aishell/transformer/run.sh +++ /dev/null @@ -1,225 +0,0 @@ -#!/usr/bin/env bash - -. ./path.sh || exit 1; - -# machines configuration -CUDA_VISIBLE_DEVICES="0,1" -gpu_num=2 -count=1 -gpu_inference=true # Whether to perform gpu decoding, set false for cpu decoding -# for gpu decoding, inference_nj=ngpu*njob; for cpu decoding, inference_nj=njob -njob=5 -train_cmd=utils/run.pl -infer_cmd=utils/run.pl - -# general configuration -feats_dir="../DATA" #feature output dictionary -exp_dir="." -lang=zh -token_type=char -type=sound -scp=wav.scp -speed_perturb="0.9 1.0 1.1" -stage=0 -stop_stage=5 - -# feature configuration -feats_dim=80 -nj=64 - -# data -raw_data=../raw_data -data_url=www.openslr.org/resources/33 - -# exp tag -tag="exp1" - -. utils/parse_options.sh || exit 1; - -# Set bash to 'debug' mode, it will exit on : -# -e 'error', -u 'undefined variable', -o ... 'error in pipeline', -x 'print commands', -set -e -set -u -set -o pipefail - -train_set=train -valid_set=dev -test_sets="dev test" - -asr_config=conf/train_asr_transformer.yaml -model_dir="baseline_$(basename "${asr_config}" .yaml)_${lang}_${token_type}_${tag}" - -inference_config=conf/decode_asr_transformer.yaml -inference_asr_model=valid.acc.ave_10best.pb - -# you can set gpu num for decoding here -gpuid_list=$CUDA_VISIBLE_DEVICES # set gpus for decoding, the same as training stage by default -ngpu=$(echo $gpuid_list | awk -F "," '{print NF}') - -if ${gpu_inference}; then - inference_nj=$[${ngpu}*${njob}] - _ngpu=1 -else - inference_nj=$njob - _ngpu=0 -fi - -if [ ${stage} -le -1 ] && [ ${stop_stage} -ge -1 ]; then - echo "stage -1: Data Download" - local/download_and_untar.sh ${raw_data} ${data_url} data_aishell - local/download_and_untar.sh ${raw_data} ${data_url} resource_aishell -fi - -if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then - echo "stage 0: Data preparation" - # Data preparation - local/aishell_data_prep.sh ${raw_data}/data_aishell/wav ${raw_data}/data_aishell/transcript ${feats_dir} - for x in train dev test; do - cp ${feats_dir}/data/${x}/text ${feats_dir}/data/${x}/text.org - paste -d " " <(cut -f 1 -d" " ${feats_dir}/data/${x}/text.org) <(cut -f 2- -d" " ${feats_dir}/data/${x}/text.org | tr -d " ") \ - > ${feats_dir}/data/${x}/text - utils/text2token.py -n 1 -s 1 ${feats_dir}/data/${x}/text > ${feats_dir}/data/${x}/text.org - mv ${feats_dir}/data/${x}/text.org ${feats_dir}/data/${x}/text - done -fi - -if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then - echo "stage 1: Feature and CMVN Generation" - utils/compute_cmvn.sh --fbankdir ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config_file "$asr_config" --scale 1.0 -fi - -token_list=${feats_dir}/data/${lang}_token_list/$token_type/tokens.txt -echo "dictionary: ${token_list}" -if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then - echo "stage 2: Dictionary Preparation" - mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/ - - echo "make a dictionary" - echo "" > ${token_list} - echo "" >> ${token_list} - echo "" >> ${token_list} - utils/text2token.py -s 1 -n 1 --space "" ${feats_dir}/data/$train_set/text | cut -f 2- -d" " | tr " " "\n" \ - | sort | uniq | grep -a -v -e '^\s*$' | awk '{print $0}' >> ${token_list} - echo "" >> ${token_list} -fi - -# LM Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then - echo "stage 3: LM Training" -fi - -# ASR Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then - echo "stage 4: ASR Training" - mkdir -p ${exp_dir}/exp/${model_dir} - mkdir -p ${exp_dir}/exp/${model_dir}/log - INIT_FILE=${exp_dir}/exp/${model_dir}/ddp_init - if [ -f $INIT_FILE ];then - rm -f $INIT_FILE - fi - init_method=file://$(readlink -f $INIT_FILE) - echo "$0: init method is $init_method" - for ((i = 0; i < $gpu_num; ++i)); do - { - rank=$i - local_rank=$i - gpu_id=$(echo $CUDA_VISIBLE_DEVICES | cut -d',' -f$[$i+1]) - train.py \ - --task_name asr \ - --gpu_id $gpu_id \ - --use_preprocessor true \ - --token_type $token_type \ - --token_list $token_list \ - --data_dir ${feats_dir}/data \ - --train_set ${train_set} \ - --valid_set ${valid_set} \ - --data_file_names "wav.scp,text" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --speed_perturb ${speed_perturb} \ - --resume true \ - --output_dir ${exp_dir}/exp/${model_dir} \ - --config $asr_config \ - --ngpu $gpu_num \ - --num_worker_count $count \ - --dist_init_method $init_method \ - --dist_world_size $world_size \ - --dist_rank $rank \ - --local_rank $local_rank 1> ${exp_dir}/exp/${model_dir}/log/train.log.$i 2>&1 - } & - done - wait -fi - -# Testing Stage -if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then - echo "stage 5: Inference" - for dset in ${test_sets}; do - asr_exp=${exp_dir}/exp/${model_dir} - inference_tag="$(basename "${inference_config}" .yaml)" - _dir="${asr_exp}/${inference_tag}/${inference_asr_model}/${dset}" - _logdir="${_dir}/logdir" - if [ -d ${_dir} ]; then - echo "${_dir} is already exists. if you want to decode again, please delete this dir first." - exit 0 - fi - mkdir -p "${_logdir}" - _data="${feats_dir}/data/${dset}" - key_file=${_data}/${scp} - num_scp_file="$(<${key_file} wc -l)" - _nj=$([ $inference_nj -le $num_scp_file ] && echo "$inference_nj" || echo "$num_scp_file") - split_scps= - for n in $(seq "${_nj}"); do - split_scps+=" ${_logdir}/keys.${n}.scp" - done - # shellcheck disable=SC2086 - utils/split_scp.pl "${key_file}" ${split_scps} - _opts= - if [ -n "${inference_config}" ]; then - _opts+="--config ${inference_config} " - fi - ${infer_cmd} --gpu "${_ngpu}" --max-jobs-run "${_nj}" JOB=1:"${_nj}" "${_logdir}"/asr_inference.JOB.log \ - python -m funasr.bin.asr_inference_launch \ - --batch_size 1 \ - --ngpu "${_ngpu}" \ - --njob ${njob} \ - --gpuid_list ${gpuid_list} \ - --data_path_and_name_and_type "${_data}/${scp},speech,${type}" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --key_file "${_logdir}"/keys.JOB.scp \ - --asr_train_config "${asr_exp}"/config.yaml \ - --asr_model_file "${asr_exp}"/"${inference_asr_model}" \ - --output_dir "${_logdir}"/output.JOB \ - --mode asr \ - ${_opts} - - for f in token token_int score text; do - if [ -f "${_logdir}/output.1/1best_recog/${f}" ]; then - for i in $(seq "${_nj}"); do - cat "${_logdir}/output.${i}/1best_recog/${f}" - done | sort -k1 >"${_dir}/${f}" - fi - done - python utils/proce_text.py ${_dir}/text ${_dir}/text.proc - python utils/proce_text.py ${_data}/text ${_data}/text.proc - python utils/compute_wer.py ${_data}/text.proc ${_dir}/text.proc ${_dir}/text.cer - tail -n 3 ${_dir}/text.cer > ${_dir}/text.cer.txt - cat ${_dir}/text.cer.txt - done -fi - -# Prepare files for ModelScope fine-tuning and inference -if [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then - echo "stage 6: ModelScope Preparation" - cp ${feats_dir}/data/${train_set}/cmvn/am.mvn ${exp_dir}/exp/${model_dir}/am.mvn - vocab_size=$(cat ${token_list} | wc -l) - python utils/gen_modelscope_configuration.py \ - --am_model_name $inference_asr_model \ - --mode asr \ - --model_name transformer \ - --dataset aishell \ - --output_dir $exp_dir/exp/$model_dir \ - --vocab_size $vocab_size \ - --tag $tag -fi \ No newline at end of file diff --git a/egs/aishell/transformer/utils/apply_cmvn.py b/egs/aishell/transformer/utils/apply_cmvn.py deleted file mode 100755 index b5c5086b3..000000000 --- a/egs/aishell/transformer/utils/apply_cmvn.py +++ /dev/null @@ -1,79 +0,0 @@ -from kaldiio import ReadHelper -from kaldiio import WriteHelper - -import argparse -import json -import math -import numpy as np - - -def get_parser(): - parser = argparse.ArgumentParser( - description="apply cmvn", - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - ) - parser.add_argument( - "--ark-file", - "-a", - default=False, - required=True, - type=str, - help="fbank ark file", - ) - parser.add_argument( - "--cmvn-file", - "-c", - default=False, - required=True, - type=str, - help="cmvn file", - ) - parser.add_argument( - "--ark-index", - "-i", - default=1, - required=True, - type=int, - help="ark index", - ) - parser.add_argument( - "--output-dir", - "-o", - default=False, - required=True, - type=str, - help="output dir", - ) - return parser - - -def main(): - parser = get_parser() - args = parser.parse_args() - - ark_file = args.output_dir + "/feats." + str(args.ark_index) + ".ark" - scp_file = args.output_dir + "/feats." + str(args.ark_index) + ".scp" - ark_writer = WriteHelper('ark,scp:{},{}'.format(ark_file, scp_file)) - - with open(args.cmvn_file) as f: - cmvn_stats = json.load(f) - - means = cmvn_stats['mean_stats'] - vars = cmvn_stats['var_stats'] - total_frames = cmvn_stats['total_frames'] - - for i in range(len(means)): - means[i] /= total_frames - vars[i] = vars[i] / total_frames - means[i] * means[i] - if vars[i] < 1.0e-20: - vars[i] = 1.0e-20 - vars[i] = 1.0 / math.sqrt(vars[i]) - - with ReadHelper('ark:{}'.format(args.ark_file)) as ark_reader: - for key, mat in ark_reader: - mat = (mat - means) * vars - ark_writer(key, mat) - - -if __name__ == '__main__': - main() diff --git a/egs/aishell/transformer/utils/apply_cmvn.sh b/egs/aishell/transformer/utils/apply_cmvn.sh deleted file mode 100755 index 525c993e2..000000000 --- a/egs/aishell/transformer/utils/apply_cmvn.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash - -. ./path.sh || exit 1; -# Begin configuration section. -nj=32 -cmd=./utils/run.pl - -echo "$0 $@" - -. utils/parse_options.sh || exit 1; - -fbankdir=$1 -cmvn_file=$2 -logdir=$3 -output_dir=$4 - -dump_dir=${output_dir}/ark; mkdir -p ${dump_dir} -mkdir -p ${logdir} - -#$cmd JOB=1:$nj $logdir/apply_cmvn.JOB.log \ -# python utils/apply_cmvn.py -a $fbankdir/ark/feats.JOB.ark \ -# -c $cmvn_file -i JOB -o ${dump_dir} \ -# || exit 1; - -for JOB in `seq 1 $nj`;do - { - python utils/apply_cmvn.py -a $fbankdir/ark/feats.${JOB}.ark \ - -c $cmvn_file -i ${JOB} -o ${dump_dir} || exit 1; - } &> $logdir/apply_cmvn.${JOB}.log & -done - -for n in $(seq $nj); do - cat ${dump_dir}/feats.$n.scp || exit 1 -done > ${output_dir}/feats.scp || exit 1 - -echo "$0: Succeeded apply cmvn" diff --git a/egs/aishell/transformer/utils/apply_lfr_and_cmvn.py b/egs/aishell/transformer/utils/apply_lfr_and_cmvn.py deleted file mode 100755 index 50d18d1a4..000000000 --- a/egs/aishell/transformer/utils/apply_lfr_and_cmvn.py +++ /dev/null @@ -1,143 +0,0 @@ -from kaldiio import ReadHelper, WriteHelper - -import argparse -import numpy as np - - -def build_LFR_features(inputs, m=7, n=6): - LFR_inputs = [] - T = inputs.shape[0] - T_lfr = int(np.ceil(T / n)) - left_padding = np.tile(inputs[0], ((m - 1) // 2, 1)) - inputs = np.vstack((left_padding, inputs)) - T = T + (m - 1) // 2 - for i in range(T_lfr): - if m <= T - i * n: - LFR_inputs.append(np.hstack(inputs[i * n:i * n + m])) - else: - num_padding = m - (T - i * n) - frame = np.hstack(inputs[i * n:]) - for _ in range(num_padding): - frame = np.hstack((frame, inputs[-1])) - LFR_inputs.append(frame) - return np.vstack(LFR_inputs) - - -def build_CMVN_features(inputs, mvn_file): # noqa - with open(mvn_file, 'r', encoding='utf-8') as f: - lines = f.readlines() - - add_shift_list = [] - rescale_list = [] - for i in range(len(lines)): - line_item = lines[i].split() - if line_item[0] == '': - line_item = lines[i + 1].split() - if line_item[0] == '': - add_shift_line = line_item[3:(len(line_item) - 1)] - add_shift_list = list(add_shift_line) - continue - elif line_item[0] == '': - line_item = lines[i + 1].split() - if line_item[0] == '': - rescale_line = line_item[3:(len(line_item) - 1)] - rescale_list = list(rescale_line) - continue - - for j in range(inputs.shape[0]): - for k in range(inputs.shape[1]): - add_shift_value = add_shift_list[k] - rescale_value = rescale_list[k] - inputs[j, k] = float(inputs[j, k]) + float(add_shift_value) - inputs[j, k] = float(inputs[j, k]) * float(rescale_value) - - return inputs - - -def get_parser(): - parser = argparse.ArgumentParser( - description="apply low_frame_rate and cmvn", - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - ) - parser.add_argument( - "--ark-file", - "-a", - default=False, - required=True, - type=str, - help="fbank ark file", - ) - parser.add_argument( - "--lfr", - "-f", - default=True, - type=str, - help="low frame rate", - ) - parser.add_argument( - "--lfr-m", - "-m", - default=7, - type=int, - help="number of frames to stack", - ) - parser.add_argument( - "--lfr-n", - "-n", - default=6, - type=int, - help="number of frames to skip", - ) - parser.add_argument( - "--cmvn-file", - "-c", - default=False, - required=True, - type=str, - help="global cmvn file", - ) - parser.add_argument( - "--ark-index", - "-i", - default=1, - required=True, - type=int, - help="ark index", - ) - parser.add_argument( - "--output-dir", - "-o", - default=False, - required=True, - type=str, - help="output dir", - ) - return parser - - -def main(): - parser = get_parser() - args = parser.parse_args() - - dump_ark_file = args.output_dir + "/feats." + str(args.ark_index) + ".ark" - dump_scp_file = args.output_dir + "/feats." + str(args.ark_index) + ".scp" - shape_file = args.output_dir + "/len." + str(args.ark_index) - ark_writer = WriteHelper('ark,scp:{},{}'.format(dump_ark_file, dump_scp_file)) - - shape_writer = open(shape_file, 'w') - with ReadHelper('ark:{}'.format(args.ark_file)) as ark_reader: - for key, mat in ark_reader: - if args.lfr: - lfr = build_LFR_features(mat, args.lfr_m, args.lfr_n) - else: - lfr = mat - cmvn = build_CMVN_features(lfr, args.cmvn_file) - dims = cmvn.shape[1] - lens = cmvn.shape[0] - shape_writer.write(key + " " + str(lens) + "," + str(dims) + '\n') - ark_writer(key, cmvn) - - -if __name__ == '__main__': - main() - diff --git a/egs/aishell/transformer/utils/apply_lfr_and_cmvn.sh b/egs/aishell/transformer/utils/apply_lfr_and_cmvn.sh deleted file mode 100755 index 3119fdb8f..000000000 --- a/egs/aishell/transformer/utils/apply_lfr_and_cmvn.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env bash - - -# Begin configuration section. -nj=32 -cmd=utils/run.pl - -# feature configuration -lfr=True -lfr_m=7 -lfr_n=6 - -echo "$0 $@" - -. utils/parse_options.sh || exit 1; - -fbankdir=$1 -cmvn_file=$2 -logdir=$3 -output_dir=$4 - -dump_dir=${output_dir}/ark; mkdir -p ${dump_dir} -mkdir -p ${logdir} - -$cmd JOB=1:$nj $logdir/apply_lfr_and_cmvn.JOB.log \ - python utils/apply_lfr_and_cmvn.py -a $fbankdir/ark/feats.JOB.ark \ - -f $lfr -m $lfr_m -n $lfr_n -c $cmvn_file -i JOB -o ${dump_dir} \ - || exit 1; - -for n in $(seq $nj); do - cat ${dump_dir}/feats.$n.scp || exit 1 -done > ${output_dir}/feats.scp || exit 1 - -for n in $(seq $nj); do - cat ${dump_dir}/len.$n || exit 1 -done > ${output_dir}/speech_shape || exit 1 - -echo "$0: Succeeded apply low frame rate and cmvn" diff --git a/egs/aishell/transformer/utils/cmvn_converter.py b/egs/aishell/transformer/utils/cmvn_converter.py deleted file mode 100644 index d405d1290..000000000 --- a/egs/aishell/transformer/utils/cmvn_converter.py +++ /dev/null @@ -1,51 +0,0 @@ -import argparse -import json -import numpy as np - - -def get_parser(): - parser = argparse.ArgumentParser( - description="cmvn converter", - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - ) - parser.add_argument( - "--cmvn_json", - default=False, - required=True, - type=str, - help="cmvn json file", - ) - parser.add_argument( - "--am_mvn", - default=False, - required=True, - type=str, - help="am mvn file", - ) - return parser - -def main(): - parser = get_parser() - args = parser.parse_args() - - with open(args.cmvn_json, "r") as fin: - cmvn_dict = json.load(fin) - - mean_stats = np.array(cmvn_dict["mean_stats"]) - var_stats = np.array(cmvn_dict["var_stats"]) - total_frame = np.array(cmvn_dict["total_frames"]) - - mean = -1.0 * mean_stats / total_frame - var = 1.0 / np.sqrt(var_stats / total_frame - mean * mean) - dims = mean.shape[0] - with open(args.am_mvn, 'w') as fout: - fout.write("" + "\n" + " " + str(dims) + " " + str(dims) + '\n' + "[ 0 ]" + "\n" + " " + str(dims) + " " + str(dims) + "\n") - mean_str = str(list(mean)).replace(',', '').replace('[', '[ ').replace(']', ' ]') - fout.write(" 0 " + mean_str + '\n') - fout.write(" " + str(dims) + " " + str(dims) + '\n') - var_str = str(list(var)).replace(',', '').replace('[', '[ ').replace(']', ' ]') - fout.write(" 0 " + var_str + '\n') - fout.write("" + '\n') - -if __name__ == '__main__': - main() diff --git a/egs/aishell/transformer/utils/combine_cmvn_file.py b/egs/aishell/transformer/utils/combine_cmvn_file.py deleted file mode 100755 index c52597372..000000000 --- a/egs/aishell/transformer/utils/combine_cmvn_file.py +++ /dev/null @@ -1,72 +0,0 @@ -import argparse -import json -import os - -import numpy as np - - -def get_parser(): - parser = argparse.ArgumentParser( - description="combine cmvn file", - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - ) - parser.add_argument( - "--dim", - default=80, - type=int, - help="feature dim", - ) - parser.add_argument( - "--cmvn_dir", - default=False, - required=True, - type=str, - help="cmvn dir", - ) - - parser.add_argument( - "--nj", - default=1, - required=True, - type=int, - help="num of cmvn files", - ) - parser.add_argument( - "--output_dir", - default=False, - required=True, - type=str, - help="output dir", - ) - return parser - - -def main(): - parser = get_parser() - args = parser.parse_args() - - total_means = np.zeros(args.dim) - total_vars = np.zeros(args.dim) - total_frames = 0 - - cmvn_file = os.path.join(args.output_dir, "cmvn.json") - - for i in range(1, args.nj + 1): - with open(os.path.join(args.cmvn_dir, "cmvn.{}.json".format(str(i)))) as fin: - cmvn_stats = json.load(fin) - - total_means += np.array(cmvn_stats["mean_stats"]) - total_vars += np.array(cmvn_stats["var_stats"]) - total_frames += cmvn_stats["total_frames"] - - cmvn_info = { - 'mean_stats': list(total_means.tolist()), - 'var_stats': list(total_vars.tolist()), - 'total_frames': total_frames - } - with open(cmvn_file, 'w') as fout: - fout.write(json.dumps(cmvn_info)) - - -if __name__ == '__main__': - main() diff --git a/egs/aishell/transformer/utils/compute_cmvn.py b/egs/aishell/transformer/utils/compute_cmvn.py deleted file mode 100755 index 4986a5a25..000000000 --- a/egs/aishell/transformer/utils/compute_cmvn.py +++ /dev/null @@ -1,126 +0,0 @@ -import argparse -import json -import os - -import numpy as np -import torchaudio -import torchaudio.compliance.kaldi as kaldi -import yaml - - -def get_parser(): - parser = argparse.ArgumentParser( - description="computer global cmvn", - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - ) - parser.add_argument( - "--dim", - default=80, - type=int, - help="feature dimension", - ) - parser.add_argument( - "--wav_path", - default=False, - required=True, - type=str, - help="the path of wav scps", - ) - parser.add_argument( - "--config_file", - type=str, - help="the config file for computing cmvn", - ) - parser.add_argument( - "--idx", - default=1, - required=True, - type=int, - help="index", - ) - return parser - - -def compute_fbank(wav_file, - num_mel_bins=80, - frame_length=25, - frame_shift=10, - dither=0.0, - resample_rate=16000, - speed=1.0, - window_type="hamming"): - waveform, sample_rate = torchaudio.load(wav_file) - if resample_rate != sample_rate: - waveform = torchaudio.transforms.Resample(orig_freq=sample_rate, - new_freq=resample_rate)(waveform) - if speed != 1.0: - waveform, _ = torchaudio.sox_effects.apply_effects_tensor( - waveform, resample_rate, - [['speed', str(speed)], ['rate', str(resample_rate)]] - ) - - waveform = waveform * (1 << 15) - mat = kaldi.fbank(waveform, - num_mel_bins=num_mel_bins, - frame_length=frame_length, - frame_shift=frame_shift, - dither=dither, - energy_floor=0.0, - window_type=window_type, - sample_frequency=resample_rate) - - return mat.numpy() - - -def main(): - parser = get_parser() - args = parser.parse_args() - - wav_scp_file = os.path.join(args.wav_path, "wav.{}.scp".format(args.idx)) - cmvn_file = os.path.join(args.wav_path, "cmvn.{}.json".format(args.idx)) - - mean_stats = np.zeros(args.dim) - var_stats = np.zeros(args.dim) - total_frames = 0 - - # with ReadHelper('ark:{}'.format(ark_file)) as ark_reader: - # for key, mat in ark_reader: - # mean_stats += np.sum(mat, axis=0) - # var_stats += np.sum(np.square(mat), axis=0) - # total_frames += mat.shape[0] - - with open(args.config_file) as f: - configs = yaml.safe_load(f) - frontend_configs = configs.get("frontend_conf", {}) - num_mel_bins = frontend_configs.get("n_mels", 80) - frame_length = frontend_configs.get("frame_length", 25) - frame_shift = frontend_configs.get("frame_shift", 10) - window_type = frontend_configs.get("window", "hamming") - resample_rate = frontend_configs.get("fs", 16000) - assert num_mel_bins == args.dim - - with open(wav_scp_file) as f: - lines = f.readlines() - for line in lines: - _, wav_file = line.strip().split() - fbank = compute_fbank(wav_file, - num_mel_bins=args.dim, - frame_length=frame_length, - frame_shift=frame_shift, - resample_rate=resample_rate, - window_type=window_type) - mean_stats += np.sum(fbank, axis=0) - var_stats += np.sum(np.square(fbank), axis=0) - total_frames += fbank.shape[0] - - cmvn_info = { - 'mean_stats': list(mean_stats.tolist()), - 'var_stats': list(var_stats.tolist()), - 'total_frames': total_frames - } - with open(cmvn_file, 'w') as fout: - fout.write(json.dumps(cmvn_info)) - - -if __name__ == '__main__': - main() diff --git a/egs/aishell/transformer/utils/compute_cmvn.sh b/egs/aishell/transformer/utils/compute_cmvn.sh deleted file mode 100755 index 4e7f80e06..000000000 --- a/egs/aishell/transformer/utils/compute_cmvn.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash - -. ./path.sh || exit 1; -# Begin configuration section. -fbankdir= -nj=32 -cmd=./utils/run.pl -feats_dim=80 -config_file= -scale=1.0 - -echo "$0 $@" - -. utils/parse_options.sh || exit 1; - -# shellcheck disable=SC2046 -head -n $(awk -v lines="$(wc -l < ${fbankdir}/wav.scp)" -v scale="$scale" 'BEGIN { printf "%.0f\n", lines*scale }') ${fbankdir}/wav.scp > ${fbankdir}/wav.scp.scale - -split_dir=${fbankdir}/cmvn/split_${nj}; -mkdir -p $split_dir -split_scps="" -for n in $(seq $nj); do - split_scps="$split_scps $split_dir/wav.$n.scp" -done -utils/split_scp.pl ${fbankdir}/wav.scp.scale $split_scps || exit 1; - -logdir=${fbankdir}/cmvn/log -$cmd JOB=1:$nj $logdir/cmvn.JOB.log \ - python utils/compute_cmvn.py \ - --dim ${feats_dim} \ - --wav_path $split_dir \ - --config_file $config_file \ - --idx JOB \ - -python utils/combine_cmvn_file.py --dim ${feats_dim} --cmvn_dir $split_dir --nj $nj --output_dir ${fbankdir}/cmvn - -python utils/cmvn_converter.py --cmvn_json ${fbankdir}/cmvn/cmvn.json --am_mvn ${fbankdir}/cmvn/am.mvn - -echo "$0: Succeeded compute global cmvn" diff --git a/egs/aishell/transformer/utils/compute_fbank.py b/egs/aishell/transformer/utils/compute_fbank.py deleted file mode 100755 index 9c3904f78..000000000 --- a/egs/aishell/transformer/utils/compute_fbank.py +++ /dev/null @@ -1,171 +0,0 @@ -from kaldiio import WriteHelper - -import argparse -import numpy as np -import json -import torch -import torchaudio -import torchaudio.compliance.kaldi as kaldi - - -def compute_fbank(wav_file, - num_mel_bins=80, - frame_length=25, - frame_shift=10, - dither=0.0, - resample_rate=16000, - speed=1.0, - window_type="hamming"): - - waveform, sample_rate = torchaudio.load(wav_file) - if resample_rate != sample_rate: - waveform = torchaudio.transforms.Resample(orig_freq=sample_rate, - new_freq=resample_rate)(waveform) - if speed != 1.0: - waveform, _ = torchaudio.sox_effects.apply_effects_tensor( - waveform, resample_rate, - [['speed', str(speed)], ['rate', str(resample_rate)]] - ) - - waveform = waveform * (1 << 15) - mat = kaldi.fbank(waveform, - num_mel_bins=num_mel_bins, - frame_length=frame_length, - frame_shift=frame_shift, - dither=dither, - energy_floor=0.0, - window_type=window_type, - sample_frequency=resample_rate) - - return mat.numpy() - - -def get_parser(): - parser = argparse.ArgumentParser( - description="computer features", - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - ) - parser.add_argument( - "--wav-lists", - "-w", - default=False, - required=True, - type=str, - help="input wav lists", - ) - parser.add_argument( - "--text-files", - "-t", - default=False, - required=True, - type=str, - help="input text files", - ) - parser.add_argument( - "--dims", - "-d", - default=80, - type=int, - help="feature dims", - ) - parser.add_argument( - "--max-lengths", - "-m", - default=1500, - type=int, - help="max frame numbers", - ) - parser.add_argument( - "--sample-frequency", - "-s", - default=16000, - type=int, - help="sample frequency", - ) - parser.add_argument( - "--speed-perturb", - "-p", - default="1.0", - type=str, - help="speed perturb", - ) - parser.add_argument( - "--ark-index", - "-a", - default=1, - required=True, - type=int, - help="ark index", - ) - parser.add_argument( - "--output-dir", - "-o", - default=False, - required=True, - type=str, - help="output dir", - ) - parser.add_argument( - "--window-type", - default="hamming", - required=False, - type=str, - help="window type" - ) - return parser - - -def main(): - parser = get_parser() - args = parser.parse_args() - - ark_file = args.output_dir + "/ark/feats." + str(args.ark_index) + ".ark" - scp_file = args.output_dir + "/ark/feats." + str(args.ark_index) + ".scp" - text_file = args.output_dir + "/txt/text." + str(args.ark_index) + ".txt" - feats_shape_file = args.output_dir + "/ark/len." + str(args.ark_index) - text_shape_file = args.output_dir + "/txt/len." + str(args.ark_index) - - ark_writer = WriteHelper('ark,scp:{},{}'.format(ark_file, scp_file)) - text_writer = open(text_file, 'w') - feats_shape_writer = open(feats_shape_file, 'w') - text_shape_writer = open(text_shape_file, 'w') - - speed_perturb_list = args.speed_perturb.split(',') - - for speed in speed_perturb_list: - with open(args.wav_lists, 'r', encoding='utf-8') as wavfile: - with open(args.text_files, 'r', encoding='utf-8') as textfile: - for wav, text in zip(wavfile, textfile): - s_w = wav.strip().split() - wav_id = s_w[0] - wav_file = s_w[1] - - s_t = text.strip().split() - text_id = s_t[0] - txt = s_t[1:] - fbank = compute_fbank(wav_file, - num_mel_bins=args.dims, - resample_rate=args.sample_frequency, - speed=float(speed), - window_type=args.window_type - ) - feats_dims = fbank.shape[1] - feats_lens = fbank.shape[0] - if feats_lens >= args.max_lengths: - continue - txt_lens = len(txt) - if speed == "1.0": - wav_id_sp = wav_id - else: - wav_id_sp = wav_id + "_sp" + speed - - feats_shape_writer.write(wav_id_sp + " " + str(feats_lens) + "," + str(feats_dims) + '\n') - text_shape_writer.write(wav_id_sp + " " + str(txt_lens) + '\n') - - text_writer.write(wav_id_sp + " " + " ".join(txt) + '\n') - ark_writer(wav_id_sp, fbank) - - -if __name__ == '__main__': - main() - diff --git a/egs/aishell/transformer/utils/compute_fbank.sh b/egs/aishell/transformer/utils/compute_fbank.sh deleted file mode 100755 index 8704b313c..000000000 --- a/egs/aishell/transformer/utils/compute_fbank.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env bash - -. ./path.sh || exit 1; -# Begin configuration section. -nj=32 -cmd=./utils/run.pl - -# feature configuration -feats_dim=80 -sample_frequency=16000 -speed_perturb="1.0" -window_type="hamming" -max_lengths=1500 - -echo "$0 $@" - -. utils/parse_options.sh || exit 1; - -data=$1 -logdir=$2 -fbankdir=$3 - -[ ! -f $data/wav.scp ] && echo "$0: no such file $data/wav.scp" && exit 1; -[ ! -f $data/text ] && echo "$0: no such file $data/text" && exit 1; - -python utils/split_data.py $data $data $nj - -ark_dir=${fbankdir}/ark; mkdir -p ${ark_dir} -text_dir=${fbankdir}/txt; mkdir -p ${text_dir} -mkdir -p ${logdir} - -$cmd JOB=1:$nj $logdir/make_fbank.JOB.log \ - python utils/compute_fbank.py -w $data/split${nj}/JOB/wav.scp -t $data/split${nj}/JOB/text \ - -d $feats_dim -s $sample_frequency -m ${max_lengths} -p ${speed_perturb} -a JOB -o ${fbankdir} \ - --window-type ${window_type} \ - || exit 1; - -for n in $(seq $nj); do - cat ${ark_dir}/feats.$n.scp || exit 1 -done > $fbankdir/feats.scp || exit 1 - -for n in $(seq $nj); do - cat ${text_dir}/text.$n.txt || exit 1 -done > $fbankdir/text || exit 1 - -for n in $(seq $nj); do - cat ${ark_dir}/len.$n || exit 1 -done > $fbankdir/speech_shape || exit 1 - -for n in $(seq $nj); do - cat ${text_dir}/len.$n || exit 1 -done > $fbankdir/text_shape || exit 1 - -echo "$0: Succeeded compute FBANK features" diff --git a/egs/aishell/transformer/utils/download_model.py b/egs/aishell/transformer/utils/download_model.py deleted file mode 100755 index 70ea17965..000000000 --- a/egs/aishell/transformer/utils/download_model.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python3 -import argparse - -from modelscope.pipelines import pipeline -from modelscope.utils.constant import Tasks - -if __name__ == '__main__': - parser = argparse.ArgumentParser( - description="download model configs", - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - ) - parser.add_argument("--model_name", - type=str, - default="damo/speech_data2vec_pretrain-zh-cn-aishell2-16k-pytorch", - help="model name in ModelScope") - args = parser.parse_args() - - inference_pipeline = pipeline( - task=Tasks.auto_speech_recognition, - model=args.model_name) diff --git a/egs/aishell/transformer/utils/error_rate_zh b/egs/aishell/transformer/utils/error_rate_zh deleted file mode 100755 index 6871a07fa..000000000 --- a/egs/aishell/transformer/utils/error_rate_zh +++ /dev/null @@ -1,370 +0,0 @@ -#!/usr/bin/env python3 -# coding=utf8 - -# Copyright 2021 Jiayu DU - -import sys -import argparse -import json -import logging -logging.basicConfig(stream=sys.stderr, level=logging.INFO, format='[%(levelname)s] %(message)s') - -DEBUG = None - -def GetEditType(ref_token, hyp_token): - if ref_token == None and hyp_token != None: - return 'I' - elif ref_token != None and hyp_token == None: - return 'D' - elif ref_token == hyp_token: - return 'C' - elif ref_token != hyp_token: - return 'S' - else: - raise RuntimeError - -class AlignmentArc: - def __init__(self, src, dst, ref, hyp): - self.src = src - self.dst = dst - self.ref = ref - self.hyp = hyp - self.edit_type = GetEditType(ref, hyp) - -def similarity_score_function(ref_token, hyp_token): - return 0 if (ref_token == hyp_token) else -1.0 - -def insertion_score_function(token): - return -1.0 - -def deletion_score_function(token): - return -1.0 - -def EditDistance( - ref, - hyp, - similarity_score_function = similarity_score_function, - insertion_score_function = insertion_score_function, - deletion_score_function = deletion_score_function): - assert(len(ref) != 0) - class DPState: - def __init__(self): - self.score = -float('inf') - # backpointer - self.prev_r = None - self.prev_h = None - - def print_search_grid(S, R, H, fstream): - print(file=fstream) - for r in range(R): - for h in range(H): - print(F'[{r},{h}]:{S[r][h].score:4.3f}:({S[r][h].prev_r},{S[r][h].prev_h}) ', end='', file=fstream) - print(file=fstream) - - R = len(ref) + 1 - H = len(hyp) + 1 - - # Construct DP search space, a (R x H) grid - S = [ [] for r in range(R) ] - for r in range(R): - S[r] = [ DPState() for x in range(H) ] - - # initialize DP search grid origin, S(r = 0, h = 0) - S[0][0].score = 0.0 - S[0][0].prev_r = None - S[0][0].prev_h = None - - # initialize REF axis - for r in range(1, R): - S[r][0].score = S[r-1][0].score + deletion_score_function(ref[r-1]) - S[r][0].prev_r = r-1 - S[r][0].prev_h = 0 - - # initialize HYP axis - for h in range(1, H): - S[0][h].score = S[0][h-1].score + insertion_score_function(hyp[h-1]) - S[0][h].prev_r = 0 - S[0][h].prev_h = h-1 - - best_score = S[0][0].score - best_state = (0, 0) - - for r in range(1, R): - for h in range(1, H): - sub_or_cor_score = similarity_score_function(ref[r-1], hyp[h-1]) - new_score = S[r-1][h-1].score + sub_or_cor_score - if new_score >= S[r][h].score: - S[r][h].score = new_score - S[r][h].prev_r = r-1 - S[r][h].prev_h = h-1 - - del_score = deletion_score_function(ref[r-1]) - new_score = S[r-1][h].score + del_score - if new_score >= S[r][h].score: - S[r][h].score = new_score - S[r][h].prev_r = r - 1 - S[r][h].prev_h = h - - ins_score = insertion_score_function(hyp[h-1]) - new_score = S[r][h-1].score + ins_score - if new_score >= S[r][h].score: - S[r][h].score = new_score - S[r][h].prev_r = r - S[r][h].prev_h = h-1 - - best_score = S[R-1][H-1].score - best_state = (R-1, H-1) - - if DEBUG: - print_search_grid(S, R, H, sys.stderr) - - # Backtracing best alignment path, i.e. a list of arcs - # arc = (src, dst, ref, hyp, edit_type) - # src/dst = (r, h), where r/h refers to search grid state-id along Ref/Hyp axis - best_path = [] - r, h = best_state[0], best_state[1] - prev_r, prev_h = S[r][h].prev_r, S[r][h].prev_h - score = S[r][h].score - # loop invariant: - # 1. (prev_r, prev_h) -> (r, h) is a "forward arc" on best alignment path - # 2. score is the value of point(r, h) on DP search grid - while prev_r != None or prev_h != None: - src = (prev_r, prev_h) - dst = (r, h) - if (r == prev_r + 1 and h == prev_h + 1): # Substitution or correct - arc = AlignmentArc(src, dst, ref[prev_r], hyp[prev_h]) - elif (r == prev_r + 1 and h == prev_h): # Deletion - arc = AlignmentArc(src, dst, ref[prev_r], None) - elif (r == prev_r and h == prev_h + 1): # Insertion - arc = AlignmentArc(src, dst, None, hyp[prev_h]) - else: - raise RuntimeError - best_path.append(arc) - r, h = prev_r, prev_h - prev_r, prev_h = S[r][h].prev_r, S[r][h].prev_h - score = S[r][h].score - - best_path.reverse() - return (best_path, best_score) - -def PrettyPrintAlignment(alignment, stream = sys.stderr): - def get_token_str(token): - if token == None: - return "*" - return token - - def is_double_width_char(ch): - if (ch >= '\u4e00') and (ch <= '\u9fa5'): # codepoint ranges for Chinese chars - return True - # TODO: support other double-width-char language such as Japanese, Korean - else: - return False - - def display_width(token_str): - m = 0 - for c in token_str: - if is_double_width_char(c): - m += 2 - else: - m += 1 - return m - - R = ' REF : ' - H = ' HYP : ' - E = ' EDIT : ' - for arc in alignment: - r = get_token_str(arc.ref) - h = get_token_str(arc.hyp) - e = arc.edit_type if arc.edit_type != 'C' else '' - - nr, nh, ne = display_width(r), display_width(h), display_width(e) - n = max(nr, nh, ne) + 1 - - R += r + ' ' * (n-nr) - H += h + ' ' * (n-nh) - E += e + ' ' * (n-ne) - - print(R, file=stream) - print(H, file=stream) - print(E, file=stream) - -def CountEdits(alignment): - c, s, i, d = 0, 0, 0, 0 - for arc in alignment: - if arc.edit_type == 'C': - c += 1 - elif arc.edit_type == 'S': - s += 1 - elif arc.edit_type == 'I': - i += 1 - elif arc.edit_type == 'D': - d += 1 - else: - raise RuntimeError - return (c, s, i, d) - -def ComputeTokenErrorRate(c, s, i, d): - return 100.0 * (s + d + i) / (s + d + c) - -def ComputeSentenceErrorRate(num_err_utts, num_utts): - assert(num_utts != 0) - return 100.0 * num_err_utts / num_utts - - -class EvaluationResult: - def __init__(self): - self.num_ref_utts = 0 - self.num_hyp_utts = 0 - self.num_eval_utts = 0 # seen in both ref & hyp - self.num_hyp_without_ref = 0 - - self.C = 0 - self.S = 0 - self.I = 0 - self.D = 0 - self.token_error_rate = 0.0 - - self.num_utts_with_error = 0 - self.sentence_error_rate = 0.0 - - def to_json(self): - return json.dumps(self.__dict__) - - def to_kaldi(self): - info = ( - F'%WER {self.token_error_rate:.2f} [ {self.S + self.D + self.I} / {self.C + self.S + self.D}, {self.I} ins, {self.D} del, {self.S} sub ]\n' - F'%SER {self.sentence_error_rate:.2f} [ {self.num_utts_with_error} / {self.num_eval_utts} ]\n' - ) - return info - - def to_sclite(self): - return "TODO" - - def to_espnet(self): - return "TODO" - - def to_summary(self): - #return json.dumps(self.__dict__, indent=4) - summary = ( - '==================== Overall Statistics ====================\n' - F'num_ref_utts: {self.num_ref_utts}\n' - F'num_hyp_utts: {self.num_hyp_utts}\n' - F'num_hyp_without_ref: {self.num_hyp_without_ref}\n' - F'num_eval_utts: {self.num_eval_utts}\n' - F'sentence_error_rate: {self.sentence_error_rate:.2f}%\n' - F'token_error_rate: {self.token_error_rate:.2f}%\n' - F'token_stats:\n' - F' - tokens:{self.C + self.S + self.D:>7}\n' - F' - edits: {self.S + self.I + self.D:>7}\n' - F' - cor: {self.C:>7}\n' - F' - sub: {self.S:>7}\n' - F' - ins: {self.I:>7}\n' - F' - del: {self.D:>7}\n' - '============================================================\n' - ) - return summary - - -class Utterance: - def __init__(self, uid, text): - self.uid = uid - self.text = text - - -def LoadUtterances(filepath, format): - utts = {} - if format == 'text': # utt_id word1 word2 ... - with open(filepath, 'r', encoding='utf8') as f: - for line in f: - line = line.strip() - if line: - cols = line.split(maxsplit=1) - assert(len(cols) == 2 or len(cols) == 1) - uid = cols[0] - text = cols[1] if len(cols) == 2 else '' - if utts.get(uid) != None: - raise RuntimeError(F'Found duplicated utterence id {uid}') - utts[uid] = Utterance(uid, text) - else: - raise RuntimeError(F'Unsupported text format {format}') - return utts - - -def tokenize_text(text, tokenizer): - if tokenizer == 'whitespace': - return text.split() - elif tokenizer == 'char': - return [ ch for ch in ''.join(text.split()) ] - else: - raise RuntimeError(F'ERROR: Unsupported tokenizer {tokenizer}') - - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - # optional - parser.add_argument('--tokenizer', choices=['whitespace', 'char'], default='whitespace', help='whitespace for WER, char for CER') - parser.add_argument('--ref-format', choices=['text'], default='text', help='reference format, first col is utt_id, the rest is text') - parser.add_argument('--hyp-format', choices=['text'], default='text', help='hypothesis format, first col is utt_id, the rest is text') - # required - parser.add_argument('--ref', type=str, required=True, help='input reference file') - parser.add_argument('--hyp', type=str, required=True, help='input hypothesis file') - - parser.add_argument('result_file', type=str) - args = parser.parse_args() - logging.info(args) - - ref_utts = LoadUtterances(args.ref, args.ref_format) - hyp_utts = LoadUtterances(args.hyp, args.hyp_format) - - r = EvaluationResult() - - # check valid utterances in hyp that have matched non-empty reference - eval_utts = [] - r.num_hyp_without_ref = 0 - for uid in sorted(hyp_utts.keys()): - if uid in ref_utts.keys(): # TODO: efficiency - if ref_utts[uid].text.strip(): # non-empty reference - eval_utts.append(uid) - else: - logging.warn(F'Found {uid} with empty reference, skipping...') - else: - logging.warn(F'Found {uid} without reference, skipping...') - r.num_hyp_without_ref += 1 - - r.num_hyp_utts = len(hyp_utts) - r.num_ref_utts = len(ref_utts) - r.num_eval_utts = len(eval_utts) - - with open(args.result_file, 'w+', encoding='utf8') as fo: - for uid in eval_utts: - ref = ref_utts[uid] - hyp = hyp_utts[uid] - - alignment, score = EditDistance( - tokenize_text(ref.text, args.tokenizer), - tokenize_text(hyp.text, args.tokenizer) - ) - - c, s, i, d = CountEdits(alignment) - utt_ter = ComputeTokenErrorRate(c, s, i, d) - - # utt-level evaluation result - print(F'{{"uid":{uid}, "score":{score}, "ter":{utt_ter:.2f}, "cor":{c}, "sub":{s}, "ins":{i}, "del":{d}}}', file=fo) - PrettyPrintAlignment(alignment, fo) - - r.C += c - r.S += s - r.I += i - r.D += d - - if utt_ter > 0: - r.num_utts_with_error += 1 - - # corpus level evaluation result - r.sentence_error_rate = ComputeSentenceErrorRate(r.num_utts_with_error, r.num_eval_utts) - r.token_error_rate = ComputeTokenErrorRate(r.C, r.S, r.I, r.D) - - print(r.to_summary(), file=fo) - - print(r.to_json()) - print(r.to_kaldi()) diff --git a/egs/aishell/transformer/utils/extract_embeds.py b/egs/aishell/transformer/utils/extract_embeds.py deleted file mode 100755 index 7b817d8ca..000000000 --- a/egs/aishell/transformer/utils/extract_embeds.py +++ /dev/null @@ -1,47 +0,0 @@ -from transformers import AutoTokenizer, AutoModel, pipeline -import numpy as np -import sys -import os -import torch -from kaldiio import WriteHelper -import re -text_file_json = sys.argv[1] -out_ark = sys.argv[2] -out_scp = sys.argv[3] -out_shape = sys.argv[4] -device = int(sys.argv[5]) -model_path = sys.argv[6] - -model = AutoModel.from_pretrained(model_path) -tokenizer = AutoTokenizer.from_pretrained(model_path) -extractor = pipeline(task="feature-extraction", model=model, tokenizer=tokenizer, device=device) - -with open(text_file_json, 'r') as f: - js = f.readlines() - - -f_shape = open(out_shape, "w") -with WriteHelper('ark,scp:{},{}'.format(out_ark, out_scp)) as writer: - with torch.no_grad(): - for idx, line in enumerate(js): - id, tokens = line.strip().split(" ", 1) - tokens = re.sub(" ", "", tokens.strip()) - tokens = ' '.join([j for j in tokens]) - token_num = len(tokens.split(" ")) - outputs = extractor(tokens) - outputs = np.array(outputs) - embeds = outputs[0, 1:-1, :] - - token_num_embeds, dim = embeds.shape - if token_num == token_num_embeds: - writer(id, embeds) - shape_line = "{} {},{}\n".format(id, token_num_embeds, dim) - f_shape.write(shape_line) - else: - print("{}, size has changed, {}, {}, {}".format(id, token_num, token_num_embeds, tokens)) - - - -f_shape.close() - - diff --git a/egs/aishell/transformer/utils/filter_scp.pl b/egs/aishell/transformer/utils/filter_scp.pl deleted file mode 100755 index 003530d53..000000000 --- a/egs/aishell/transformer/utils/filter_scp.pl +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env perl -# Copyright 2010-2012 Microsoft Corporation -# Johns Hopkins University (author: Daniel Povey) - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED -# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, -# MERCHANTABLITY OR NON-INFRINGEMENT. -# See the Apache 2 License for the specific language governing permissions and -# limitations under the License. - - -# This script takes a list of utterance-ids or any file whose first field -# of each line is an utterance-id, and filters an scp -# file (or any file whose "n-th" field is an utterance id), printing -# out only those lines whose "n-th" field is in id_list. The index of -# the "n-th" field is 1, by default, but can be changed by using -# the -f switch - -$exclude = 0; -$field = 1; -$shifted = 0; - -do { - $shifted=0; - if ($ARGV[0] eq "--exclude") { - $exclude = 1; - shift @ARGV; - $shifted=1; - } - if ($ARGV[0] eq "-f") { - $field = $ARGV[1]; - shift @ARGV; shift @ARGV; - $shifted=1 - } -} while ($shifted); - -if(@ARGV < 1 || @ARGV > 2) { - die "Usage: filter_scp.pl [--exclude] [-f ] id_list [in.scp] > out.scp \n" . - "Prints only the input lines whose f'th field (default: first) is in 'id_list'.\n" . - "Note: only the first field of each line in id_list matters. With --exclude, prints\n" . - "only the lines that were *not* in id_list.\n" . - "Caution: previously, the -f option was interpreted as a zero-based field index.\n" . - "If your older scripts (written before Oct 2014) stopped working and you used the\n" . - "-f option, add 1 to the argument.\n" . - "See also: scripts/filter_scp.pl .\n"; -} - - -$idlist = shift @ARGV; -open(F, "<$idlist") || die "Could not open id-list file $idlist"; -while() { - @A = split; - @A>=1 || die "Invalid id-list file line $_"; - $seen{$A[0]} = 1; -} - -if ($field == 1) { # Treat this as special case, since it is common. - while(<>) { - $_ =~ m/\s*(\S+)\s*/ || die "Bad line $_, could not get first field."; - # $1 is what we filter on. - if ((!$exclude && $seen{$1}) || ($exclude && !defined $seen{$1})) { - print $_; - } - } -} else { - while(<>) { - @A = split; - @A > 0 || die "Invalid scp file line $_"; - @A >= $field || die "Invalid scp file line $_"; - if ((!$exclude && $seen{$A[$field-1]}) || ($exclude && !defined $seen{$A[$field-1]})) { - print $_; - } - } -} - -# tests: -# the following should print "foo 1" -# ( echo foo 1; echo bar 2 ) | scripts/filter_scp.pl <(echo foo) -# the following should print "bar 2". -# ( echo foo 1; echo bar 2 ) | scripts/filter_scp.pl -f 2 <(echo 2) diff --git a/egs/aishell/transformer/utils/fix_data.sh b/egs/aishell/transformer/utils/fix_data.sh deleted file mode 100755 index b1a2bb808..000000000 --- a/egs/aishell/transformer/utils/fix_data.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash - -echo "$0 $@" -data_dir=$1 - -if [ ! -f ${data_dir}/wav.scp ]; then - echo "$0: wav.scp is not found" - exit 1; -fi - -if [ ! -f ${data_dir}/text ]; then - echo "$0: text is not found" - exit 1; -fi - - - -mkdir -p ${data_dir}/.backup - -awk '{print $1}' ${data_dir}/wav.scp > ${data_dir}/.backup/wav_id -awk '{print $1}' ${data_dir}/text > ${data_dir}/.backup/text_id - -sort ${data_dir}/.backup/wav_id ${data_dir}/.backup/text_id | uniq -d > ${data_dir}/.backup/id - -cp ${data_dir}/wav.scp ${data_dir}/.backup/wav.scp -cp ${data_dir}/text ${data_dir}/.backup/text - -mv ${data_dir}/wav.scp ${data_dir}/wav.scp.bak -mv ${data_dir}/text ${data_dir}/text.bak - -utils/filter_scp.pl -f 1 ${data_dir}/.backup/id ${data_dir}/wav.scp.bak | sort -k1,1 -u > ${data_dir}/wav.scp -utils/filter_scp.pl -f 1 ${data_dir}/.backup/id ${data_dir}/text.bak | sort -k1,1 -u > ${data_dir}/text - -rm ${data_dir}/wav.scp.bak -rm ${data_dir}/text.bak diff --git a/egs/aishell/transformer/utils/fix_data_feat.sh b/egs/aishell/transformer/utils/fix_data_feat.sh deleted file mode 100755 index 84eea36b6..000000000 --- a/egs/aishell/transformer/utils/fix_data_feat.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env bash - -echo "$0 $@" -data_dir=$1 - -if [ ! -f ${data_dir}/feats.scp ]; then - echo "$0: feats.scp is not found" - exit 1; -fi - -if [ ! -f ${data_dir}/text ]; then - echo "$0: text is not found" - exit 1; -fi - -if [ ! -f ${data_dir}/speech_shape ]; then - echo "$0: feature lengths is not found" - exit 1; -fi - -if [ ! -f ${data_dir}/text_shape ]; then - echo "$0: text lengths is not found" - exit 1; -fi - -mkdir -p ${data_dir}/.backup - -awk '{print $1}' ${data_dir}/feats.scp > ${data_dir}/.backup/wav_id -awk '{print $1}' ${data_dir}/text > ${data_dir}/.backup/text_id - -sort ${data_dir}/.backup/wav_id ${data_dir}/.backup/text_id | uniq -d > ${data_dir}/.backup/id - -cp ${data_dir}/feats.scp ${data_dir}/.backup/feats.scp -cp ${data_dir}/text ${data_dir}/.backup/text -cp ${data_dir}/speech_shape ${data_dir}/.backup/speech_shape -cp ${data_dir}/text_shape ${data_dir}/.backup/text_shape - -mv ${data_dir}/feats.scp ${data_dir}/feats.scp.bak -mv ${data_dir}/text ${data_dir}/text.bak -mv ${data_dir}/speech_shape ${data_dir}/speech_shape.bak -mv ${data_dir}/text_shape ${data_dir}/text_shape.bak - -utils/filter_scp.pl -f 1 ${data_dir}/.backup/id ${data_dir}/feats.scp.bak | sort -k1,1 -u > ${data_dir}/feats.scp -utils/filter_scp.pl -f 1 ${data_dir}/.backup/id ${data_dir}/text.bak | sort -k1,1 -u > ${data_dir}/text -utils/filter_scp.pl -f 1 ${data_dir}/.backup/id ${data_dir}/speech_shape.bak | sort -k1,1 -u > ${data_dir}/speech_shape -utils/filter_scp.pl -f 1 ${data_dir}/.backup/id ${data_dir}/text_shape.bak | sort -k1,1 -u > ${data_dir}/text_shape - -rm ${data_dir}/feats.scp.bak -rm ${data_dir}/text.bak -rm ${data_dir}/speech_shape.bak -rm ${data_dir}/text_shape.bak - diff --git a/egs/aishell/transformer/utils/gen_ark_list.sh b/egs/aishell/transformer/utils/gen_ark_list.sh deleted file mode 100755 index aebf3562d..000000000 --- a/egs/aishell/transformer/utils/gen_ark_list.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - - -# Begin configuration section. -nj=32 -cmd=./utils/run.pl - -echo "$0 $@" - -. utils/parse_options.sh || exit 1; - -ark_dir=$1 -txt_dir=$2 -output_dir=$3 - -[ ! -d ${ark_dir}/ark ] && echo "$0: ark data is required" && exit 1; -[ ! -d ${txt_dir}/txt ] && echo "$0: txt data is required" && exit 1; - -for n in $(seq $nj); do - echo "${ark_dir}/ark/feats.$n.ark ${txt_dir}/txt/text.$n.txt" || exit 1 -done > ${output_dir}/ark_txt.scp || exit 1 - diff --git a/egs/aishell/transformer/utils/gen_modelscope_configuration.py b/egs/aishell/transformer/utils/gen_modelscope_configuration.py deleted file mode 100644 index d34097058..000000000 --- a/egs/aishell/transformer/utils/gen_modelscope_configuration.py +++ /dev/null @@ -1,118 +0,0 @@ -import argparse -import json -import os - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument( - "--task", - type=str, - default="auto-speech-recognition", - help="task name", - ) - parser.add_argument( - "--type", - type=str, - default="generic-asr", - ) - parser.add_argument( - "--am_model_name", - type=str, - default="model.pb", - help="model file name", - ) - parser.add_argument( - "--mode", - type=str, - default="paraformer", - help="mode for decoding", - ) - parser.add_argument( - "--lang", - type=str, - default="zh-cn", - help="language", - ) - parser.add_argument( - "--batch_size", - type=int, - default=1, - help="batch size", - ) - parser.add_argument( - "--am_model_config", - type=str, - default="config.yaml", - help="config file", - ) - parser.add_argument( - "--mvn_file", - type=str, - default="am.mvn", - help="cmvn file", - ) - parser.add_argument( - "--model_name", - type=str, - help="model name", - ) - parser.add_argument( - "--pipeline_type", - type=str, - default="asr-inference", - help="pipeline type", - ) - parser.add_argument( - "--vocab_size", - type=int, - help="vocab_size", - ) - parser.add_argument( - "--dataset", - type=str, - help="dataset name", - ) - parser.add_argument( - "--output_dir", - type=str, - help="output path", - ) - parser.add_argument( - "--nat", - type=str, - default="", - help="nat", - ) - parser.add_argument( - "--tag", - type=str, - default="exp1", - help="model name tag", - ) - args = parser.parse_args() - - model = { - "type": args.type, - "am_model_name": args.am_model_name, - "model_config": { - "type": "pytorch", - "code_base": "funasr", - "mode": args.mode, - "lang": args.lang, - "batch_size": args.batch_size, - "am_model_config": args.am_model_config, - "mvn_file": args.mvn_file, - "model": "speech_{}_asr{}-{}-16k-{}-vocab{}-pytorch-{}".format(args.model_name, args.nat, args.lang, - args.dataset, args.vocab_size, args.tag), - } - } - pipeline = {"type": args.pipeline_type} - json_dict = { - "framework": "pytorch", - "task": args.task, - "model": model, - "pipeline": pipeline, - } - - with open(os.path.join(args.output_dir, "configuration.json"), "w") as f: - json.dump(json_dict, f, indent=4) diff --git a/egs/aishell/transformer/utils/parse_options.sh b/egs/aishell/transformer/utils/parse_options.sh deleted file mode 100755 index 71fb9e5ea..000000000 --- a/egs/aishell/transformer/utils/parse_options.sh +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2012 Johns Hopkins University (Author: Daniel Povey); -# Arnab Ghoshal, Karel Vesely - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED -# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, -# MERCHANTABLITY OR NON-INFRINGEMENT. -# See the Apache 2 License for the specific language governing permissions and -# limitations under the License. - - -# Parse command-line options. -# To be sourced by another script (as in ". parse_options.sh"). -# Option format is: --option-name arg -# and shell variable "option_name" gets set to value "arg." -# The exception is --help, which takes no arguments, but prints the -# $help_message variable (if defined). - - -### -### The --config file options have lower priority to command line -### options, so we need to import them first... -### - -# Now import all the configs specified by command-line, in left-to-right order -for ((argpos=1; argpos<$#; argpos++)); do - if [ "${!argpos}" == "--config" ]; then - argpos_plus1=$((argpos+1)) - config=${!argpos_plus1} - [ ! -r $config ] && echo "$0: missing config '$config'" && exit 1 - . $config # source the config file. - fi -done - - -### -### Now we process the command line options -### -while true; do - [ -z "${1:-}" ] && break; # break if there are no arguments - case "$1" in - # If the enclosing script is called with --help option, print the help - # message and exit. Scripts should put help messages in $help_message - --help|-h) if [ -z "$help_message" ]; then echo "No help found." 1>&2; - else printf "$help_message\n" 1>&2 ; fi; - exit 0 ;; - --*=*) echo "$0: options to scripts must be of the form --name value, got '$1'" - exit 1 ;; - # If the first command-line argument begins with "--" (e.g. --foo-bar), - # then work out the variable name as $name, which will equal "foo_bar". - --*) name=`echo "$1" | sed s/^--// | sed s/-/_/g`; - # Next we test whether the variable in question is undefned-- if so it's - # an invalid option and we die. Note: $0 evaluates to the name of the - # enclosing script. - # The test [ -z ${foo_bar+xxx} ] will return true if the variable foo_bar - # is undefined. We then have to wrap this test inside "eval" because - # foo_bar is itself inside a variable ($name). - eval '[ -z "${'$name'+xxx}" ]' && echo "$0: invalid option $1" 1>&2 && exit 1; - - oldval="`eval echo \\$$name`"; - # Work out whether we seem to be expecting a Boolean argument. - if [ "$oldval" == "true" ] || [ "$oldval" == "false" ]; then - was_bool=true; - else - was_bool=false; - fi - - # Set the variable to the right value-- the escaped quotes make it work if - # the option had spaces, like --cmd "queue.pl -sync y" - eval $name=\"$2\"; - - # Check that Boolean-valued arguments are really Boolean. - if $was_bool && [[ "$2" != "true" && "$2" != "false" ]]; then - echo "$0: expected \"true\" or \"false\": $1 $2" 1>&2 - exit 1; - fi - shift 2; - ;; - *) break; - esac -done - - -# Check for an empty argument to the --cmd option, which can easily occur as a -# result of scripting errors. -[ ! -z "${cmd+xxx}" ] && [ -z "$cmd" ] && echo "$0: empty argument to --cmd option" 1>&2 && exit 1; - - -true; # so this script returns exit code 0. diff --git a/egs/aishell/transformer/utils/prepare_checkpoint.py b/egs/aishell/transformer/utils/prepare_checkpoint.py deleted file mode 100644 index 116fa078b..000000000 --- a/egs/aishell/transformer/utils/prepare_checkpoint.py +++ /dev/null @@ -1,19 +0,0 @@ -import os -import shutil - -from modelscope.hub.snapshot_download import snapshot_download - - -if __name__ == '__main__': - import sys - - model = sys.argv[1] - checkpoint_dir = sys.argv[2] - checkpoint_name = sys.argv[3] - - try: - pretrained_model_path = snapshot_download(model, cache_dir=checkpoint_dir) - except BaseException: - raise BaseException(f"Please download pretrain model from ModelScope firstly.") - shutil.copy(os.path.join(checkpoint_dir, checkpoint_name), os.path.join(pretrained_model_path, "model.pb")) - shutil.copy(os.path.join(checkpoint_dir, "config.yaml"), os.path.join(pretrained_model_path, "config.yaml")) diff --git a/egs/aishell/transformer/utils/print_args.py b/egs/aishell/transformer/utils/print_args.py deleted file mode 100755 index b0c61e5b4..000000000 --- a/egs/aishell/transformer/utils/print_args.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python -import sys - - -def get_commandline_args(no_executable=True): - extra_chars = [ - " ", - ";", - "&", - "|", - "<", - ">", - "?", - "*", - "~", - "`", - '"', - "'", - "\\", - "{", - "}", - "(", - ")", - ] - - # Escape the extra characters for shell - argv = [ - arg.replace("'", "'\\''") - if all(char not in arg for char in extra_chars) - else "'" + arg.replace("'", "'\\''") + "'" - for arg in sys.argv - ] - - if no_executable: - return " ".join(argv[1:]) - else: - return sys.executable + " " + " ".join(argv) - - -def main(): - print(get_commandline_args()) - - -if __name__ == "__main__": - main() diff --git a/egs/aishell/transformer/utils/proc_conf_oss.py b/egs/aishell/transformer/utils/proc_conf_oss.py deleted file mode 100755 index c4a90c5c1..000000000 --- a/egs/aishell/transformer/utils/proc_conf_oss.py +++ /dev/null @@ -1,35 +0,0 @@ -from pathlib import Path - -import torch -import yaml - - -class NoAliasSafeDumper(yaml.SafeDumper): - # Disable anchor/alias in yaml because looks ugly - def ignore_aliases(self, data): - return True - - -def yaml_no_alias_safe_dump(data, stream=None, **kwargs): - """Safe-dump in yaml with no anchor/alias""" - return yaml.dump( - data, stream, allow_unicode=True, Dumper=NoAliasSafeDumper, **kwargs - ) - - -def gen_conf(file, out_dir): - conf = torch.load(file)["config"] - conf["oss_bucket"] = "null" - print(conf) - output_dir = Path(out_dir) - output_dir.mkdir(parents=True, exist_ok=True) - with (output_dir / "config.yaml").open("w", encoding="utf-8") as f: - yaml_no_alias_safe_dump(conf, f, indent=4, sort_keys=False) - - -if __name__ == "__main__": - import sys - - in_f = sys.argv[1] - out_f = sys.argv[2] - gen_conf(in_f, out_f) diff --git a/egs/aishell/transformer/utils/proce_text.py b/egs/aishell/transformer/utils/proce_text.py deleted file mode 100755 index 9e517a4e1..000000000 --- a/egs/aishell/transformer/utils/proce_text.py +++ /dev/null @@ -1,31 +0,0 @@ - -import sys -import re - -in_f = sys.argv[1] -out_f = sys.argv[2] - - -with open(in_f, "r", encoding="utf-8") as f: - lines = f.readlines() - -with open(out_f, "w", encoding="utf-8") as f: - for line in lines: - outs = line.strip().split(" ", 1) - if len(outs) == 2: - idx, text = outs - text = re.sub("", "", text) - text = re.sub("", "", text) - text = re.sub("@@", "", text) - text = re.sub("@", "", text) - text = re.sub("", "", text) - text = re.sub(" ", "", text) - text = text.lower() - else: - idx = outs[0] - text = " " - - text = [x for x in text] - text = " ".join(text) - out = "{} {}\n".format(idx, text) - f.write(out) diff --git a/egs/aishell/transformer/utils/process_opus.py b/egs/aishell/transformer/utils/process_opus.py deleted file mode 100755 index 1baa3ed13..000000000 --- a/egs/aishell/transformer/utils/process_opus.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright 2021 NPU, ASLP Group (Author: Qijie Shao) - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# process_opus.py: segmentation and downsampling of opus audio - -# usage: python3 process_opus.py wav.scp segments output_wav.scp - -from pydub import AudioSegment -import sys -import os - - -def read_file(wav_scp, segments): - wav_scp_dict = {} - with open(wav_scp, "r", encoding="UTF-8") as fin: - for line_str in fin: - wav_id, path = line_str.strip().split() - wav_scp_dict[wav_id] = path - - utt_list = [] - seg_path_list = [] - start_time_list = [] - end_time_list = [] - with open(segments, "r", encoding="UTF-8") as fin: - for line_str in fin: - arr = line_str.strip().split() - assert len(arr) == 4 - utt_list.append(arr[0]) - seg_path_list.append(wav_scp_dict[arr[1]]) - start_time_list.append(float(arr[2])) - end_time_list.append(float(arr[3])) - return utt_list, seg_path_list, start_time_list, end_time_list - - -# TODO(Qijie): Fix the process logic -def output(output_wav_scp, utt_list, seg_path_list, start_time_list, end_time_list): - num_utts = len(utt_list) - with open(output_wav_scp, "w", encoding="UTF-8") as fout: - previous_wav_path = "" - for i in range(num_utts): - utt_id = utt_list[i] - current_wav_path = seg_path_list[i] - output_dir = (os.path.dirname(current_wav_path)).replace( - "audio", "audio_seg" - ) - seg_wav_path = os.path.join(output_dir, utt_id + ".wav") - - os.makedirs(output_dir, exist_ok=True) - if current_wav_path != previous_wav_path: - source_wav = AudioSegment.from_file(current_wav_path) - previous_wav_path = current_wav_path - - start = int(start_time_list[i] * 1000) - end = int(end_time_list[i] * 1000) - target_audio = source_wav[start:end].set_frame_rate(16000).set_sample_width(2) - target_audio.export(seg_wav_path, format="wav") - - fout.write("{} {}\n".format(utt_id, seg_wav_path)) - if i % 200 == 0: - print("seg wav finished: {}%".format(int(i / num_utts))) - - -def main(): - wav_scp = sys.argv[1] - segments = sys.argv[2] - output_wav_scp = sys.argv[3] - - utt_list, seg_path_list, start_time_list, end_time_list = read_file( - wav_scp, segments - ) - output(output_wav_scp, utt_list, seg_path_list, start_time_list, end_time_list) - - -if __name__ == "__main__": - main() diff --git a/egs/aishell/transformer/utils/run.pl b/egs/aishell/transformer/utils/run.pl deleted file mode 100755 index 483f95bc6..000000000 --- a/egs/aishell/transformer/utils/run.pl +++ /dev/null @@ -1,356 +0,0 @@ -#!/usr/bin/env perl -use warnings; #sed replacement for -w perl parameter -# In general, doing -# run.pl some.log a b c is like running the command a b c in -# the bash shell, and putting the standard error and output into some.log. -# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) -# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB -# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. -# If any of the jobs fails, this script will fail. - -# A typical example is: -# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz -# and run.pl will run something like: -# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log -# -# Basically it takes the command-line arguments, quotes them -# as necessary to preserve spaces, and evaluates them with bash. -# In addition it puts the command line at the top of the log, and -# the start and end times of the command at the beginning and end. -# The reason why this is useful is so that we can create a different -# version of this program that uses a queueing system instead. - -#use Data::Dumper; - -@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; - -#print STDERR "COMMAND-LINE: " . Dumper(\@ARGV) . "\n"; -$job_pick = 'all'; -$max_jobs_run = -1; -$jobstart = 1; -$jobend = 1; -$ignored_opts = ""; # These will be ignored. - -# First parse an option like JOB=1:4, and any -# options that would normally be given to -# queue.pl, which we will just discard. - -for (my $x = 1; $x <= 2; $x++) { # This for-loop is to - # allow the JOB=1:n option to be interleaved with the - # options to qsub. - while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { - # parse any options that would normally go to qsub, but which will be ignored here. - my $switch = shift @ARGV; - if ($switch eq "-V") { - $ignored_opts .= "-V "; - } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { - # we do support the option --max-jobs-run n, and its GridEngine form -tc n. - # if the command appears multiple times uses the smallest option. - if ( $max_jobs_run <= 0 ) { - $max_jobs_run = shift @ARGV; - } else { - my $new_constraint = shift @ARGV; - if ( ($new_constraint < $max_jobs_run) ) { - $max_jobs_run = $new_constraint; - } - } - - if (! ($max_jobs_run > 0)) { - die "run.pl: invalid option --max-jobs-run $max_jobs_run"; - } - } else { - my $argument = shift @ARGV; - if ($argument =~ m/^--/) { - print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; - } - if ($switch eq "-sync" && $argument =~ m/^[yY]/) { - $ignored_opts .= "-sync "; # Note: in the - # corresponding code in queue.pl it says instead, just "$sync = 1;". - } elsif ($switch eq "-pe") { # e.g. -pe smp 5 - my $argument2 = shift @ARGV; - $ignored_opts .= "$switch $argument $argument2 "; - } elsif ($switch eq "--gpu") { - $using_gpu = $argument; - } elsif ($switch eq "--pick") { - if($argument =~ m/^(all|failed|incomplete)$/) { - $job_pick = $argument; - } else { - print STDERR "run.pl: ERROR: --pick argument must be one of 'all', 'failed' or 'incomplete'" - } - } else { - # Ignore option. - $ignored_opts .= "$switch $argument "; - } - } - } - if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 - $jobname = $1; - $jobstart = $2; - $jobend = $3; - if ($jobstart > $jobend) { - die "run.pl: invalid job range $ARGV[0]"; - } - if ($jobstart <= 0) { - die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; - } - shift; - } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. - $jobname = $1; - $jobstart = $2; - $jobend = $2; - shift; - } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { - print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; - } -} - -# Users found this message confusing so we are removing it. -# if ($ignored_opts ne "") { -# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; -# } - -if ($max_jobs_run == -1) { # If --max-jobs-run option not set, - # then work out the number of processors if possible, - # and set it based on that. - $max_jobs_run = 0; - if ($using_gpu) { - if (open(P, "nvidia-smi -L |")) { - $max_jobs_run++ while (

); - close(P); - } - if ($max_jobs_run == 0) { - $max_jobs_run = 1; - print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; - } - } elsif (open(P, ") { if (m/^processor/) { $max_jobs_run++; } } - if ($max_jobs_run == 0) { - print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; - $max_jobs_run = 10; # reasonable default. - } - close(P); - } elsif (open(P, "sysctl -a |")) { # BSD/Darwin - while (

) { - if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 - $max_jobs_run = $1; - last; - } - } - close(P); - if ($max_jobs_run == 0) { - print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; - $max_jobs_run = 10; # reasonable default. - } - } else { - # allow at most 32 jobs at once, on non-UNIX systems; change this code - # if you need to change this default. - $max_jobs_run = 32; - } - # The just-computed value of $max_jobs_run is just the number of processors - # (or our best guess); and if it happens that the number of jobs we need to - # run is just slightly above $max_jobs_run, it will make sense to increase - # $max_jobs_run to equal the number of jobs, so we don't have a small number - # of leftover jobs. - $num_jobs = $jobend - $jobstart + 1; - if (!$using_gpu && - $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { - $max_jobs_run = $num_jobs; - } -} - -sub pick_or_exit { - # pick_or_exit ( $logfile ) - # Invoked before each job is started helps to run jobs selectively. - # - # Given the name of the output logfile decides whether the job must be - # executed (by returning from the subroutine) or not (by terminating the - # process calling exit) - # - # PRE: $job_pick is a global variable set by command line switch --pick - # and indicates which class of jobs must be executed. - # - # 1) If a failed job is not executed the process exit code will indicate - # failure, just as if the task was just executed and failed. - # - # 2) If a task is incomplete it will be executed. Incomplete may be either - # a job whose log file does not contain the accounting notes in the end, - # or a job whose log file does not exist. - # - # 3) If the $job_pick is set to 'all' (default behavior) a task will be - # executed regardless of the result of previous attempts. - # - # This logic could have been implemented in the main execution loop - # but a subroutine to preserve the current level of readability of - # that part of the code. - # - # Alexandre Felipe, (o.alexandre.felipe@gmail.com) 14th of August of 2020 - # - if($job_pick eq 'all'){ - return; # no need to bother with the previous log - } - open my $fh, "<", $_[0] or return; # job not executed yet - my $log_line; - my $cur_line; - while ($cur_line = <$fh>) { - if( $cur_line =~ m/# Ended \(code .*/ ) { - $log_line = $cur_line; - } - } - close $fh; - if (! defined($log_line)){ - return; # incomplete - } - if ( $log_line =~ m/# Ended \(code 0\).*/ ) { - exit(0); # complete - } elsif ( $log_line =~ m/# Ended \(code \d+(; signal \d+)?\).*/ ){ - if ($job_pick !~ m/^(failed|all)$/) { - exit(1); # failed but not going to run - } else { - return; # failed - } - } elsif ( $log_line =~ m/.*\S.*/ ) { - return; # incomplete jobs are always run - } -} - - -$logfile = shift @ARGV; - -if (defined $jobname && $logfile !~ m/$jobname/ && - $jobend > $jobstart) { - print STDERR "run.pl: you are trying to run a parallel job but " - . "you are putting the output into just one log file ($logfile)\n"; - exit(1); -} - -$cmd = ""; - -foreach $x (@ARGV) { - if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } - elsif ($x =~ m:\":) { $cmd .= "'$x' "; } - else { $cmd .= "\"$x\" "; } -} - -#$Data::Dumper::Indent=0; -$ret = 0; -$numfail = 0; -%active_pids=(); - -use POSIX ":sys_wait_h"; -for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { - if (scalar(keys %active_pids) >= $max_jobs_run) { - - # Lets wait for a change in any child's status - # Then we have to work out which child finished - $r = waitpid(-1, 0); - $code = $?; - if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. - if ( defined $active_pids{$r} ) { - $jid=$active_pids{$r}; - $fail[$jid]=$code; - if ($code !=0) { $numfail++;} - delete $active_pids{$r}; - # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; - } else { - die "run.pl: Cannot find the PID of the child process that just finished."; - } - - # In theory we could do a non-blocking waitpid over all jobs running just - # to find out if only one or more jobs finished during the previous waitpid() - # However, we just omit this and will reap the next one in the next pass - # through the for(;;) cycle - } - $childpid = fork(); - if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } - if ($childpid == 0) { # We're in the child... this branch - # executes the job and returns (possibly with an error status). - if (defined $jobname) { - $cmd =~ s/$jobname/$jobid/g; - $logfile =~ s/$jobname/$jobid/g; - } - # exit if the job does not need to be executed - pick_or_exit( $logfile ); - - system("mkdir -p `dirname $logfile` 2>/dev/null"); - open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; - print F "# " . $cmd . "\n"; - print F "# Started at " . `date`; - $starttime = `date +'%s'`; - print F "#\n"; - close(F); - - # Pipe into bash.. make sure we're not using any other shell. - open(B, "|bash") || die "run.pl: Error opening shell command"; - print B "( " . $cmd . ") 2>>$logfile >> $logfile"; - close(B); # If there was an error, exit status is in $? - $ret = $?; - - $lowbits = $ret & 127; - $highbits = $ret >> 8; - if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } - else { $return_str = "code $highbits"; } - - $endtime = `date +'%s'`; - open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; - $enddate = `date`; - chop $enddate; - print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; - print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; - close(F); - exit($ret == 0 ? 0 : 1); - } else { - $pid[$jobid] = $childpid; - $active_pids{$childpid} = $jobid; - # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; - } -} - -# Now we have submitted all the jobs, lets wait until all the jobs finish -foreach $child (keys %active_pids) { - $jobid=$active_pids{$child}; - $r = waitpid($pid[$jobid], 0); - $code = $?; - if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. - if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully -} - -# Some sanity checks: -# The $fail array should not contain undefined codes -# The number of non-zeros in that array should be equal to $numfail -# We cannot do foreach() here, as the JOB ids do not start at zero -$failed_jids=0; -for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { - $job_return = $fail[$jobid]; - if (not defined $job_return ) { - # print Dumper(\@fail); - - die "run.pl: Sanity check failed: we have indication that some jobs are running " . - "even after we waited for all jobs to finish" ; - } - if ($job_return != 0 ){ $failed_jids++;} -} -if ($failed_jids != $numfail) { - die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." -} -if ($numfail > 0) { $ret = 1; } - -if ($ret != 0) { - $njobs = $jobend - $jobstart + 1; - if ($njobs == 1) { - if (defined $jobname) { - $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with - # that job. - } - print STDERR "run.pl: job failed, log is in $logfile\n"; - if ($logfile =~ m/JOB/) { - print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; - } - } - else { - $logfile =~ s/$jobname/*/g; - print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; - } -} - - -exit ($ret); diff --git a/egs/aishell/transformer/utils/shuffle_list.pl b/egs/aishell/transformer/utils/shuffle_list.pl deleted file mode 100755 index a116200f4..000000000 --- a/egs/aishell/transformer/utils/shuffle_list.pl +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env perl - -# Copyright 2013 Johns Hopkins University (author: Daniel Povey) - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED -# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, -# MERCHANTABLITY OR NON-INFRINGEMENT. -# See the Apache 2 License for the specific language governing permissions and -# limitations under the License. - - -if ($ARGV[0] eq "--srand") { - $n = $ARGV[1]; - $n =~ m/\d+/ || die "Bad argument to --srand option: \"$n\""; - srand($ARGV[1]); - shift; - shift; -} else { - srand(0); # Gives inconsistent behavior if we don't seed. -} - -if (@ARGV > 1 || $ARGV[0] =~ m/^-.+/) { # >1 args, or an option we - # don't understand. - print "Usage: shuffle_list.pl [--srand N] [input file] > output\n"; - print "randomizes the order of lines of input.\n"; - exit(1); -} - -@lines; -while (<>) { - push @lines, [ (rand(), $_)] ; -} - -@lines = sort { $a->[0] cmp $b->[0] } @lines; -foreach $l (@lines) { - print $l->[1]; -} \ No newline at end of file diff --git a/egs/aishell/transformer/utils/split_data.py b/egs/aishell/transformer/utils/split_data.py deleted file mode 100755 index 060eae6d3..000000000 --- a/egs/aishell/transformer/utils/split_data.py +++ /dev/null @@ -1,60 +0,0 @@ -import os -import sys -import random - - -in_dir = sys.argv[1] -out_dir = sys.argv[2] -num_split = sys.argv[3] - - -def split_scp(scp, num): - assert len(scp) >= num - avg = len(scp) // num - out = [] - begin = 0 - - for i in range(num): - if i == num - 1: - out.append(scp[begin:]) - else: - out.append(scp[begin:begin+avg]) - begin += avg - - return out - - -os.path.exists("{}/wav.scp".format(in_dir)) -os.path.exists("{}/text".format(in_dir)) - -with open("{}/wav.scp".format(in_dir), 'r') as infile: - wav_list = infile.readlines() - -with open("{}/text".format(in_dir), 'r') as infile: - text_list = infile.readlines() - -assert len(wav_list) == len(text_list) - -x = list(zip(wav_list, text_list)) -random.shuffle(x) -wav_shuffle_list, text_shuffle_list = zip(*x) - -num_split = int(num_split) -wav_split_list = split_scp(wav_shuffle_list, num_split) -text_split_list = split_scp(text_shuffle_list, num_split) - -for idx, wav_list in enumerate(wav_split_list, 1): - path = out_dir + "/split" + str(num_split) + "/" + str(idx) - if not os.path.exists(path): - os.makedirs(path) - with open("{}/wav.scp".format(path), 'w') as wav_writer: - for line in wav_list: - wav_writer.write(line) - -for idx, text_list in enumerate(text_split_list, 1): - path = out_dir + "/split" + str(num_split) + "/" + str(idx) - if not os.path.exists(path): - os.makedirs(path) - with open("{}/text".format(path), 'w') as text_writer: - for line in text_list: - text_writer.write(line) diff --git a/egs/aishell/transformer/utils/split_scp.pl b/egs/aishell/transformer/utils/split_scp.pl deleted file mode 100755 index 0876dcb6d..000000000 --- a/egs/aishell/transformer/utils/split_scp.pl +++ /dev/null @@ -1,246 +0,0 @@ -#!/usr/bin/env perl - -# Copyright 2010-2011 Microsoft Corporation - -# See ../../COPYING for clarification regarding multiple authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED -# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, -# MERCHANTABLITY OR NON-INFRINGEMENT. -# See the Apache 2 License for the specific language governing permissions and -# limitations under the License. - - -# This program splits up any kind of .scp or archive-type file. -# If there is no utt2spk option it will work on any text file and -# will split it up with an approximately equal number of lines in -# each but. -# With the --utt2spk option it will work on anything that has the -# utterance-id as the first entry on each line; the utt2spk file is -# of the form "utterance speaker" (on each line). -# It splits it into equal size chunks as far as it can. If you use the utt2spk -# option it will make sure these chunks coincide with speaker boundaries. In -# this case, if there are more chunks than speakers (and in some other -# circumstances), some of the resulting chunks will be empty and it will print -# an error message and exit with nonzero status. -# You will normally call this like: -# split_scp.pl scp scp.1 scp.2 scp.3 ... -# or -# split_scp.pl --utt2spk=utt2spk scp scp.1 scp.2 scp.3 ... -# Note that you can use this script to split the utt2spk file itself, -# e.g. split_scp.pl --utt2spk=utt2spk utt2spk utt2spk.1 utt2spk.2 ... - -# You can also call the scripts like: -# split_scp.pl -j 3 0 scp scp.0 -# [note: with this option, it assumes zero-based indexing of the split parts, -# i.e. the second number must be 0 <= n < num-jobs.] - -use warnings; - -$num_jobs = 0; -$job_id = 0; -$utt2spk_file = ""; -$one_based = 0; - -for ($x = 1; $x <= 3 && @ARGV > 0; $x++) { - if ($ARGV[0] eq "-j") { - shift @ARGV; - $num_jobs = shift @ARGV; - $job_id = shift @ARGV; - } - if ($ARGV[0] =~ /--utt2spk=(.+)/) { - $utt2spk_file=$1; - shift; - } - if ($ARGV[0] eq '--one-based') { - $one_based = 1; - shift @ARGV; - } -} - -if ($num_jobs != 0 && ($num_jobs < 0 || $job_id - $one_based < 0 || - $job_id - $one_based >= $num_jobs)) { - die "$0: Invalid job number/index values for '-j $num_jobs $job_id" . - ($one_based ? " --one-based" : "") . "'\n" -} - -$one_based - and $job_id--; - -if(($num_jobs == 0 && @ARGV < 2) || ($num_jobs > 0 && (@ARGV < 1 || @ARGV > 2))) { - die -"Usage: split_scp.pl [--utt2spk=] in.scp out1.scp out2.scp ... - or: split_scp.pl -j num-jobs job-id [--one-based] [--utt2spk=] in.scp [out.scp] - ... where 0 <= job-id < num-jobs, or 1 <= job-id <- num-jobs if --one-based.\n"; -} - -$error = 0; -$inscp = shift @ARGV; -if ($num_jobs == 0) { # without -j option - @OUTPUTS = @ARGV; -} else { - for ($j = 0; $j < $num_jobs; $j++) { - if ($j == $job_id) { - if (@ARGV > 0) { push @OUTPUTS, $ARGV[0]; } - else { push @OUTPUTS, "-"; } - } else { - push @OUTPUTS, "/dev/null"; - } - } -} - -if ($utt2spk_file ne "") { # We have the --utt2spk option... - open($u_fh, '<', $utt2spk_file) || die "$0: Error opening utt2spk file $utt2spk_file: $!\n"; - while(<$u_fh>) { - @A = split; - @A == 2 || die "$0: Bad line $_ in utt2spk file $utt2spk_file\n"; - ($u,$s) = @A; - $utt2spk{$u} = $s; - } - close $u_fh; - open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; - @spkrs = (); - while(<$i_fh>) { - @A = split; - if(@A == 0) { die "$0: Empty or space-only line in scp file $inscp\n"; } - $u = $A[0]; - $s = $utt2spk{$u}; - defined $s || die "$0: No utterance $u in utt2spk file $utt2spk_file\n"; - if(!defined $spk_count{$s}) { - push @spkrs, $s; - $spk_count{$s} = 0; - $spk_data{$s} = []; # ref to new empty array. - } - $spk_count{$s}++; - push @{$spk_data{$s}}, $_; - } - # Now split as equally as possible .. - # First allocate spks to files by allocating an approximately - # equal number of speakers. - $numspks = @spkrs; # number of speakers. - $numscps = @OUTPUTS; # number of output files. - if ($numspks < $numscps) { - die "$0: Refusing to split data because number of speakers $numspks " . - "is less than the number of output .scp files $numscps\n"; - } - for($scpidx = 0; $scpidx < $numscps; $scpidx++) { - $scparray[$scpidx] = []; # [] is array reference. - } - for ($spkidx = 0; $spkidx < $numspks; $spkidx++) { - $scpidx = int(($spkidx*$numscps) / $numspks); - $spk = $spkrs[$spkidx]; - push @{$scparray[$scpidx]}, $spk; - $scpcount[$scpidx] += $spk_count{$spk}; - } - - # Now will try to reassign beginning + ending speakers - # to different scp's and see if it gets more balanced. - # Suppose objf we're minimizing is sum_i (num utts in scp[i] - average)^2. - # We can show that if considering changing just 2 scp's, we minimize - # this by minimizing the squared difference in sizes. This is - # equivalent to minimizing the absolute difference in sizes. This - # shows this method is bound to converge. - - $changed = 1; - while($changed) { - $changed = 0; - for($scpidx = 0; $scpidx < $numscps; $scpidx++) { - # First try to reassign ending spk of this scp. - if($scpidx < $numscps-1) { - $sz = @{$scparray[$scpidx]}; - if($sz > 0) { - $spk = $scparray[$scpidx]->[$sz-1]; - $count = $spk_count{$spk}; - $nutt1 = $scpcount[$scpidx]; - $nutt2 = $scpcount[$scpidx+1]; - if( abs( ($nutt2+$count) - ($nutt1-$count)) - < abs($nutt2 - $nutt1)) { # Would decrease - # size-diff by reassigning spk... - $scpcount[$scpidx+1] += $count; - $scpcount[$scpidx] -= $count; - pop @{$scparray[$scpidx]}; - unshift @{$scparray[$scpidx+1]}, $spk; - $changed = 1; - } - } - } - if($scpidx > 0 && @{$scparray[$scpidx]} > 0) { - $spk = $scparray[$scpidx]->[0]; - $count = $spk_count{$spk}; - $nutt1 = $scpcount[$scpidx-1]; - $nutt2 = $scpcount[$scpidx]; - if( abs( ($nutt2-$count) - ($nutt1+$count)) - < abs($nutt2 - $nutt1)) { # Would decrease - # size-diff by reassigning spk... - $scpcount[$scpidx-1] += $count; - $scpcount[$scpidx] -= $count; - shift @{$scparray[$scpidx]}; - push @{$scparray[$scpidx-1]}, $spk; - $changed = 1; - } - } - } - } - # Now print out the files... - for($scpidx = 0; $scpidx < $numscps; $scpidx++) { - $scpfile = $OUTPUTS[$scpidx]; - ($scpfile ne '-' ? open($f_fh, '>', $scpfile) - : open($f_fh, '>&', \*STDOUT)) || - die "$0: Could not open scp file $scpfile for writing: $!\n"; - $count = 0; - if(@{$scparray[$scpidx]} == 0) { - print STDERR "$0: eError: split_scp.pl producing empty .scp file " . - "$scpfile (too many splits and too few speakers?)\n"; - $error = 1; - } else { - foreach $spk ( @{$scparray[$scpidx]} ) { - print $f_fh @{$spk_data{$spk}}; - $count += $spk_count{$spk}; - } - $count == $scpcount[$scpidx] || die "Count mismatch [code error]"; - } - close($f_fh); - } -} else { - # This block is the "normal" case where there is no --utt2spk - # option and we just break into equal size chunks. - - open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; - - $numscps = @OUTPUTS; # size of array. - @F = (); - while(<$i_fh>) { - push @F, $_; - } - $numlines = @F; - if($numlines == 0) { - print STDERR "$0: error: empty input scp file $inscp\n"; - $error = 1; - } - $linesperscp = int( $numlines / $numscps); # the "whole part".. - $linesperscp >= 1 || die "$0: You are splitting into too many pieces! [reduce \$nj ($numscps) to be smaller than the number of lines ($numlines) in $inscp]\n"; - $remainder = $numlines - ($linesperscp * $numscps); - ($remainder >= 0 && $remainder < $numlines) || die "bad remainder $remainder"; - # [just doing int() rounds down]. - $n = 0; - for($scpidx = 0; $scpidx < @OUTPUTS; $scpidx++) { - $scpfile = $OUTPUTS[$scpidx]; - ($scpfile ne '-' ? open($o_fh, '>', $scpfile) - : open($o_fh, '>&', \*STDOUT)) || - die "$0: Could not open scp file $scpfile for writing: $!\n"; - for($k = 0; $k < $linesperscp + ($scpidx < $remainder ? 1 : 0); $k++) { - print $o_fh $F[$n++]; - } - close($o_fh) || die "$0: Eror closing scp file $scpfile: $!\n"; - } - $n == $numlines || die "$n != $numlines [code error]"; -} - -exit ($error); diff --git a/egs/aishell/transformer/utils/subset_data_dir_tr_cv.sh b/egs/aishell/transformer/utils/subset_data_dir_tr_cv.sh deleted file mode 100755 index e16cebdf1..000000000 --- a/egs/aishell/transformer/utils/subset_data_dir_tr_cv.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash - -dev_num_utt=1000 - -echo "$0 $@" -. utils/parse_options.sh || exit 1; - -train_data=$1 -out_dir=$2 - -[ ! -f ${train_data}/wav.scp ] && echo "$0: no such file ${train_data}/wav.scp" && exit 1; -[ ! -f ${train_data}/text ] && echo "$0: no such file ${train_data}/text" && exit 1; - -mkdir -p ${out_dir}/train && mkdir -p ${out_dir}/dev - -cp ${train_data}/wav.scp ${out_dir}/train/wav.scp.bak -cp ${train_data}/text ${out_dir}/train/text.bak - -num_utt=$(wc -l <${out_dir}/train/wav.scp.bak) - -utils/shuffle_list.pl --srand 1 ${out_dir}/train/wav.scp.bak > ${out_dir}/train/wav.scp.shuf -head -n ${dev_num_utt} ${out_dir}/train/wav.scp.shuf > ${out_dir}/dev/wav.scp -tail -n $((${num_utt}-${dev_num_utt})) ${out_dir}/train/wav.scp.shuf > ${out_dir}/train/wav.scp - -utils/shuffle_list.pl --srand 1 ${out_dir}/train/text.bak > ${out_dir}/train/text.shuf -head -n ${dev_num_utt} ${out_dir}/train/text.shuf > ${out_dir}/dev/text -tail -n $((${num_utt}-${dev_num_utt})) ${out_dir}/train/text.shuf > ${out_dir}/train/text - -rm ${out_dir}/train/wav.scp.bak ${out_dir}/train/text.bak -rm ${out_dir}/train/wav.scp.shuf ${out_dir}/train/text.shuf diff --git a/egs/aishell/transformer/utils/text2token.py b/egs/aishell/transformer/utils/text2token.py deleted file mode 100755 index 56c39138f..000000000 --- a/egs/aishell/transformer/utils/text2token.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2017 Johns Hopkins University (Shinji Watanabe) -# Apache 2.0 (http://www.apache.org/licenses/LICENSE-2.0) - - -import argparse -import codecs -import re -import sys - -is_python2 = sys.version_info[0] == 2 - - -def exist_or_not(i, match_pos): - start_pos = None - end_pos = None - for pos in match_pos: - if pos[0] <= i < pos[1]: - start_pos = pos[0] - end_pos = pos[1] - break - - return start_pos, end_pos - - -def get_parser(): - parser = argparse.ArgumentParser( - description="convert raw text to tokenized text", - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - ) - parser.add_argument( - "--nchar", - "-n", - default=1, - type=int, - help="number of characters to split, i.e., \ - aabb -> a a b b with -n 1 and aa bb with -n 2", - ) - parser.add_argument( - "--skip-ncols", "-s", default=0, type=int, help="skip first n columns" - ) - parser.add_argument("--space", default="", type=str, help="space symbol") - parser.add_argument( - "--non-lang-syms", - "-l", - default=None, - type=str, - help="list of non-linguistic symobles, e.g., etc.", - ) - parser.add_argument("text", type=str, default=False, nargs="?", help="input text") - parser.add_argument( - "--trans_type", - "-t", - type=str, - default="char", - choices=["char", "phn"], - help="""Transcript type. char/phn. e.g., for TIMIT FADG0_SI1279 - - If trans_type is char, - read from SI1279.WRD file -> "bricks are an alternative" - Else if trans_type is phn, - read from SI1279.PHN file -> "sil b r ih sil k s aa r er n aa l - sil t er n ih sil t ih v sil" """, - ) - return parser - - -def main(): - parser = get_parser() - args = parser.parse_args() - - rs = [] - if args.non_lang_syms is not None: - with codecs.open(args.non_lang_syms, "r", encoding="utf-8") as f: - nls = [x.rstrip() for x in f.readlines()] - rs = [re.compile(re.escape(x)) for x in nls] - - if args.text: - f = codecs.open(args.text, encoding="utf-8") - else: - f = codecs.getreader("utf-8")(sys.stdin if is_python2 else sys.stdin.buffer) - - sys.stdout = codecs.getwriter("utf-8")( - sys.stdout if is_python2 else sys.stdout.buffer - ) - line = f.readline() - n = args.nchar - while line: - x = line.split() - print(" ".join(x[: args.skip_ncols]), end=" ") - a = " ".join(x[args.skip_ncols :]) - - # get all matched positions - match_pos = [] - for r in rs: - i = 0 - while i >= 0: - m = r.search(a, i) - if m: - match_pos.append([m.start(), m.end()]) - i = m.end() - else: - break - - if args.trans_type == "phn": - a = a.split(" ") - else: - if len(match_pos) > 0: - chars = [] - i = 0 - while i < len(a): - start_pos, end_pos = exist_or_not(i, match_pos) - if start_pos is not None: - chars.append(a[start_pos:end_pos]) - i = end_pos - else: - chars.append(a[i]) - i += 1 - a = chars - - a = [a[j : j + n] for j in range(0, len(a), n)] - - a_flat = [] - for z in a: - a_flat.append("".join(z)) - - a_chars = [z.replace(" ", args.space) for z in a_flat] - if args.trans_type == "phn": - a_chars = [z.replace("sil", args.space) for z in a_chars] - print(" ".join(a_chars)) - line = f.readline() - - -if __name__ == "__main__": - main() diff --git a/egs/aishell/transformer/utils/text_tokenize.py b/egs/aishell/transformer/utils/text_tokenize.py deleted file mode 100755 index 962ea11bc..000000000 --- a/egs/aishell/transformer/utils/text_tokenize.py +++ /dev/null @@ -1,106 +0,0 @@ -import re -import argparse - - -def load_dict(seg_file): - seg_dict = {} - with open(seg_file, 'r') as infile: - for line in infile: - s = line.strip().split() - key = s[0] - value = s[1:] - seg_dict[key] = " ".join(value) - return seg_dict - - -def forward_segment(text, dic): - word_list = [] - i = 0 - while i < len(text): - longest_word = text[i] - for j in range(i + 1, len(text) + 1): - word = text[i:j] - if word in dic: - if len(word) > len(longest_word): - longest_word = word - word_list.append(longest_word) - i += len(longest_word) - return word_list - - -def tokenize(txt, - seg_dict): - out_txt = "" - pattern = re.compile(r"([\u4E00-\u9FA5A-Za-z0-9])") - for word in txt: - if pattern.match(word): - if word in seg_dict: - out_txt += seg_dict[word] + " " - else: - out_txt += "" + " " - else: - continue - return out_txt.strip() - - -def get_parser(): - parser = argparse.ArgumentParser( - description="text tokenize", - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - ) - parser.add_argument( - "--text-file", - "-t", - default=False, - required=True, - type=str, - help="input text", - ) - parser.add_argument( - "--seg-file", - "-s", - default=False, - required=True, - type=str, - help="seg file", - ) - parser.add_argument( - "--txt-index", - "-i", - default=1, - required=True, - type=int, - help="txt index", - ) - parser.add_argument( - "--output-dir", - "-o", - default=False, - required=True, - type=str, - help="output dir", - ) - return parser - - -def main(): - parser = get_parser() - args = parser.parse_args() - - txt_writer = open("{}/text.{}.txt".format(args.output_dir, args.txt_index), 'w') - shape_writer = open("{}/len.{}".format(args.output_dir, args.txt_index), 'w') - seg_dict = load_dict(args.seg_file) - with open(args.text_file, 'r') as infile: - for line in infile: - s = line.strip().split() - text_id = s[0] - text_list = forward_segment("".join(s[1:]).lower(), seg_dict) - text = tokenize(text_list, seg_dict) - lens = len(text.strip().split()) - txt_writer.write(text_id + " " + text + '\n') - shape_writer.write(text_id + " " + str(lens) + '\n') - - -if __name__ == '__main__': - main() - diff --git a/egs/aishell/transformer/utils/text_tokenize.sh b/egs/aishell/transformer/utils/text_tokenize.sh deleted file mode 100755 index 6b74fef80..000000000 --- a/egs/aishell/transformer/utils/text_tokenize.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash - - -# Begin configuration section. -nj=32 -cmd=utils/run.pl - -echo "$0 $@" - -. utils/parse_options.sh || exit 1; - -# tokenize configuration -text_dir=$1 -seg_file=$2 -logdir=$3 -output_dir=$4 - -txt_dir=${output_dir}/txt; mkdir -p ${output_dir}/txt -mkdir -p ${logdir} - -$cmd JOB=1:$nj $logdir/text_tokenize.JOB.log \ - python utils/text_tokenize.py -t ${text_dir}/txt/text.JOB.txt \ - -s ${seg_file} -i JOB -o ${txt_dir} \ - || exit 1; - -# concatenate the text files together. -for n in $(seq $nj); do - cat ${txt_dir}/text.$n.txt || exit 1 -done > ${output_dir}/text || exit 1 - -for n in $(seq $nj); do - cat ${txt_dir}/len.$n || exit 1 -done > ${output_dir}/text_shape || exit 1 - -echo "$0: Succeeded text tokenize" diff --git a/egs/aishell/transformer/utils/textnorm_zh.py b/egs/aishell/transformer/utils/textnorm_zh.py deleted file mode 100755 index 79feb83fd..000000000 --- a/egs/aishell/transformer/utils/textnorm_zh.py +++ /dev/null @@ -1,834 +0,0 @@ -#!/usr/bin/env python3 -# coding=utf-8 - -# Authors: -# 2019.5 Zhiyang Zhou (https://github.com/Joee1995/chn_text_norm.git) -# 2019.9 Jiayu DU -# -# requirements: -# - python 3.X -# notes: python 2.X WILL fail or produce misleading results - -import sys, os, argparse, codecs, string, re - -# ================================================================================ # -# basic constant -# ================================================================================ # -CHINESE_DIGIS = u'零一二三四五六七八九' -BIG_CHINESE_DIGIS_SIMPLIFIED = u'零壹贰叁肆伍陆柒捌玖' -BIG_CHINESE_DIGIS_TRADITIONAL = u'零壹貳參肆伍陸柒捌玖' -SMALLER_BIG_CHINESE_UNITS_SIMPLIFIED = u'十百千万' -SMALLER_BIG_CHINESE_UNITS_TRADITIONAL = u'拾佰仟萬' -LARGER_CHINESE_NUMERING_UNITS_SIMPLIFIED = u'亿兆京垓秭穰沟涧正载' -LARGER_CHINESE_NUMERING_UNITS_TRADITIONAL = u'億兆京垓秭穰溝澗正載' -SMALLER_CHINESE_NUMERING_UNITS_SIMPLIFIED = u'十百千万' -SMALLER_CHINESE_NUMERING_UNITS_TRADITIONAL = u'拾佰仟萬' - -ZERO_ALT = u'〇' -ONE_ALT = u'幺' -TWO_ALTS = [u'两', u'兩'] - -POSITIVE = [u'正', u'正'] -NEGATIVE = [u'负', u'負'] -POINT = [u'点', u'點'] -# PLUS = [u'加', u'加'] -# SIL = [u'杠', u'槓'] - -FILLER_CHARS = ['呃', '啊'] -ER_WHITELIST = '(儿女|儿子|儿孙|女儿|儿媳|妻儿|' \ - '胎儿|婴儿|新生儿|婴幼儿|幼儿|少儿|小儿|儿歌|儿童|儿科|托儿所|孤儿|' \ - '儿戏|儿化|台儿庄|鹿儿岛|正儿八经|吊儿郎当|生儿育女|托儿带女|养儿防老|痴儿呆女|' \ - '佳儿佳妇|儿怜兽扰|儿无常父|儿不嫌母丑|儿行千里母担忧|儿大不由爷|苏乞儿)' - -# 中文数字系统类型 -NUMBERING_TYPES = ['low', 'mid', 'high'] - -CURRENCY_NAMES = '(人民币|美元|日元|英镑|欧元|马克|法郎|加拿大元|澳元|港币|先令|芬兰马克|爱尔兰镑|' \ - '里拉|荷兰盾|埃斯库多|比塞塔|印尼盾|林吉特|新西兰元|比索|卢布|新加坡元|韩元|泰铢)' -CURRENCY_UNITS = '((亿|千万|百万|万|千|百)|(亿|千万|百万|万|千|百|)元|(亿|千万|百万|万|千|百|)块|角|毛|分)' -COM_QUANTIFIERS = '(匹|张|座|回|场|尾|条|个|首|阙|阵|网|炮|顶|丘|棵|只|支|袭|辆|挑|担|颗|壳|窠|曲|墙|群|腔|' \ - '砣|座|客|贯|扎|捆|刀|令|打|手|罗|坡|山|岭|江|溪|钟|队|单|双|对|出|口|头|脚|板|跳|枝|件|贴|' \ - '针|线|管|名|位|身|堂|课|本|页|家|户|层|丝|毫|厘|分|钱|两|斤|担|铢|石|钧|锱|忽|(千|毫|微)克|' \ - '毫|厘|分|寸|尺|丈|里|寻|常|铺|程|(千|分|厘|毫|微)米|撮|勺|合|升|斗|石|盘|碗|碟|叠|桶|笼|盆|' \ - '盒|杯|钟|斛|锅|簋|篮|盘|桶|罐|瓶|壶|卮|盏|箩|箱|煲|啖|袋|钵|年|月|日|季|刻|时|周|天|秒|分|旬|' \ - '纪|岁|世|更|夜|春|夏|秋|冬|代|伏|辈|丸|泡|粒|颗|幢|堆|条|根|支|道|面|片|张|颗|块)' - -# punctuation information are based on Zhon project (https://github.com/tsroten/zhon.git) -CHINESE_PUNC_STOP = '!?。。' -CHINESE_PUNC_NON_STOP = '"#$%&'()*+,-/:;<=>@[\]^_`{|}~⦅⦆「」、、〃》「」『』【】〔〕〖〗〘〙〚〛〜〝〞〟〰〾〿–—‘’‛“”„‟…‧﹏' -CHINESE_PUNC_LIST = CHINESE_PUNC_STOP + CHINESE_PUNC_NON_STOP - -# ================================================================================ # -# basic class -# ================================================================================ # -class ChineseChar(object): - """ - 中文字符 - 每个字符对应简体和繁体, - e.g. 简体 = '负', 繁体 = '負' - 转换时可转换为简体或繁体 - """ - - def __init__(self, simplified, traditional): - self.simplified = simplified - self.traditional = traditional - #self.__repr__ = self.__str__ - - def __str__(self): - return self.simplified or self.traditional or None - - def __repr__(self): - return self.__str__() - - -class ChineseNumberUnit(ChineseChar): - """ - 中文数字/数位字符 - 每个字符除繁简体外还有一个额外的大写字符 - e.g. '陆' 和 '陸' - """ - - def __init__(self, power, simplified, traditional, big_s, big_t): - super(ChineseNumberUnit, self).__init__(simplified, traditional) - self.power = power - self.big_s = big_s - self.big_t = big_t - - def __str__(self): - return '10^{}'.format(self.power) - - @classmethod - def create(cls, index, value, numbering_type=NUMBERING_TYPES[1], small_unit=False): - - if small_unit: - return ChineseNumberUnit(power=index + 1, - simplified=value[0], traditional=value[1], big_s=value[1], big_t=value[1]) - elif numbering_type == NUMBERING_TYPES[0]: - return ChineseNumberUnit(power=index + 8, - simplified=value[0], traditional=value[1], big_s=value[0], big_t=value[1]) - elif numbering_type == NUMBERING_TYPES[1]: - return ChineseNumberUnit(power=(index + 2) * 4, - simplified=value[0], traditional=value[1], big_s=value[0], big_t=value[1]) - elif numbering_type == NUMBERING_TYPES[2]: - return ChineseNumberUnit(power=pow(2, index + 3), - simplified=value[0], traditional=value[1], big_s=value[0], big_t=value[1]) - else: - raise ValueError( - 'Counting type should be in {0} ({1} provided).'.format(NUMBERING_TYPES, numbering_type)) - - -class ChineseNumberDigit(ChineseChar): - """ - 中文数字字符 - """ - - def __init__(self, value, simplified, traditional, big_s, big_t, alt_s=None, alt_t=None): - super(ChineseNumberDigit, self).__init__(simplified, traditional) - self.value = value - self.big_s = big_s - self.big_t = big_t - self.alt_s = alt_s - self.alt_t = alt_t - - def __str__(self): - return str(self.value) - - @classmethod - def create(cls, i, v): - return ChineseNumberDigit(i, v[0], v[1], v[2], v[3]) - - -class ChineseMath(ChineseChar): - """ - 中文数位字符 - """ - - def __init__(self, simplified, traditional, symbol, expression=None): - super(ChineseMath, self).__init__(simplified, traditional) - self.symbol = symbol - self.expression = expression - self.big_s = simplified - self.big_t = traditional - - -CC, CNU, CND, CM = ChineseChar, ChineseNumberUnit, ChineseNumberDigit, ChineseMath - - -class NumberSystem(object): - """ - 中文数字系统 - """ - pass - - -class MathSymbol(object): - """ - 用于中文数字系统的数学符号 (繁/简体), e.g. - positive = ['正', '正'] - negative = ['负', '負'] - point = ['点', '點'] - """ - - def __init__(self, positive, negative, point): - self.positive = positive - self.negative = negative - self.point = point - - def __iter__(self): - for v in self.__dict__.values(): - yield v - - -# class OtherSymbol(object): -# """ -# 其他符号 -# """ -# -# def __init__(self, sil): -# self.sil = sil -# -# def __iter__(self): -# for v in self.__dict__.values(): -# yield v - - -# ================================================================================ # -# basic utils -# ================================================================================ # -def create_system(numbering_type=NUMBERING_TYPES[1]): - """ - 根据数字系统类型返回创建相应的数字系统,默认为 mid - NUMBERING_TYPES = ['low', 'mid', 'high']: 中文数字系统类型 - low: '兆' = '亿' * '十' = $10^{9}$, '京' = '兆' * '十', etc. - mid: '兆' = '亿' * '万' = $10^{12}$, '京' = '兆' * '万', etc. - high: '兆' = '亿' * '亿' = $10^{16}$, '京' = '兆' * '兆', etc. - 返回对应的数字系统 - """ - - # chinese number units of '亿' and larger - all_larger_units = zip( - LARGER_CHINESE_NUMERING_UNITS_SIMPLIFIED, LARGER_CHINESE_NUMERING_UNITS_TRADITIONAL) - larger_units = [CNU.create(i, v, numbering_type, False) - for i, v in enumerate(all_larger_units)] - # chinese number units of '十, 百, 千, 万' - all_smaller_units = zip( - SMALLER_CHINESE_NUMERING_UNITS_SIMPLIFIED, SMALLER_CHINESE_NUMERING_UNITS_TRADITIONAL) - smaller_units = [CNU.create(i, v, small_unit=True) - for i, v in enumerate(all_smaller_units)] - # digis - chinese_digis = zip(CHINESE_DIGIS, CHINESE_DIGIS, - BIG_CHINESE_DIGIS_SIMPLIFIED, BIG_CHINESE_DIGIS_TRADITIONAL) - digits = [CND.create(i, v) for i, v in enumerate(chinese_digis)] - digits[0].alt_s, digits[0].alt_t = ZERO_ALT, ZERO_ALT - digits[1].alt_s, digits[1].alt_t = ONE_ALT, ONE_ALT - digits[2].alt_s, digits[2].alt_t = TWO_ALTS[0], TWO_ALTS[1] - - # symbols - positive_cn = CM(POSITIVE[0], POSITIVE[1], '+', lambda x: x) - negative_cn = CM(NEGATIVE[0], NEGATIVE[1], '-', lambda x: -x) - point_cn = CM(POINT[0], POINT[1], '.', lambda x, - y: float(str(x) + '.' + str(y))) - # sil_cn = CM(SIL[0], SIL[1], '-', lambda x, y: float(str(x) + '-' + str(y))) - system = NumberSystem() - system.units = smaller_units + larger_units - system.digits = digits - system.math = MathSymbol(positive_cn, negative_cn, point_cn) - # system.symbols = OtherSymbol(sil_cn) - return system - - -def chn2num(chinese_string, numbering_type=NUMBERING_TYPES[1]): - - def get_symbol(char, system): - for u in system.units: - if char in [u.traditional, u.simplified, u.big_s, u.big_t]: - return u - for d in system.digits: - if char in [d.traditional, d.simplified, d.big_s, d.big_t, d.alt_s, d.alt_t]: - return d - for m in system.math: - if char in [m.traditional, m.simplified]: - return m - - def string2symbols(chinese_string, system): - int_string, dec_string = chinese_string, '' - for p in [system.math.point.simplified, system.math.point.traditional]: - if p in chinese_string: - int_string, dec_string = chinese_string.split(p) - break - return [get_symbol(c, system) for c in int_string], \ - [get_symbol(c, system) for c in dec_string] - - def correct_symbols(integer_symbols, system): - """ - 一百八 to 一百八十 - 一亿一千三百万 to 一亿 一千万 三百万 - """ - - if integer_symbols and isinstance(integer_symbols[0], CNU): - if integer_symbols[0].power == 1: - integer_symbols = [system.digits[1]] + integer_symbols - - if len(integer_symbols) > 1: - if isinstance(integer_symbols[-1], CND) and isinstance(integer_symbols[-2], CNU): - integer_symbols.append( - CNU(integer_symbols[-2].power - 1, None, None, None, None)) - - result = [] - unit_count = 0 - for s in integer_symbols: - if isinstance(s, CND): - result.append(s) - unit_count = 0 - elif isinstance(s, CNU): - current_unit = CNU(s.power, None, None, None, None) - unit_count += 1 - - if unit_count == 1: - result.append(current_unit) - elif unit_count > 1: - for i in range(len(result)): - if isinstance(result[-i - 1], CNU) and result[-i - 1].power < current_unit.power: - result[-i - 1] = CNU(result[-i - 1].power + - current_unit.power, None, None, None, None) - return result - - def compute_value(integer_symbols): - """ - Compute the value. - When current unit is larger than previous unit, current unit * all previous units will be used as all previous units. - e.g. '两千万' = 2000 * 10000 not 2000 + 10000 - """ - value = [0] - last_power = 0 - for s in integer_symbols: - if isinstance(s, CND): - value[-1] = s.value - elif isinstance(s, CNU): - value[-1] *= pow(10, s.power) - if s.power > last_power: - value[:-1] = list(map(lambda v: v * - pow(10, s.power), value[:-1])) - last_power = s.power - value.append(0) - return sum(value) - - system = create_system(numbering_type) - int_part, dec_part = string2symbols(chinese_string, system) - int_part = correct_symbols(int_part, system) - int_str = str(compute_value(int_part)) - dec_str = ''.join([str(d.value) for d in dec_part]) - if dec_part: - return '{0}.{1}'.format(int_str, dec_str) - else: - return int_str - - -def num2chn(number_string, numbering_type=NUMBERING_TYPES[1], big=False, - traditional=False, alt_zero=False, alt_one=False, alt_two=True, - use_zeros=True, use_units=True): - - def get_value(value_string, use_zeros=True): - - striped_string = value_string.lstrip('0') - - # record nothing if all zeros - if not striped_string: - return [] - - # record one digits - elif len(striped_string) == 1: - if use_zeros and len(value_string) != len(striped_string): - return [system.digits[0], system.digits[int(striped_string)]] - else: - return [system.digits[int(striped_string)]] - - # recursively record multiple digits - else: - result_unit = next(u for u in reversed( - system.units) if u.power < len(striped_string)) - result_string = value_string[:-result_unit.power] - return get_value(result_string) + [result_unit] + get_value(striped_string[-result_unit.power:]) - - system = create_system(numbering_type) - - int_dec = number_string.split('.') - if len(int_dec) == 1: - int_string = int_dec[0] - dec_string = "" - elif len(int_dec) == 2: - int_string = int_dec[0] - dec_string = int_dec[1] - else: - raise ValueError( - "invalid input num string with more than one dot: {}".format(number_string)) - - if use_units and len(int_string) > 1: - result_symbols = get_value(int_string) - else: - result_symbols = [system.digits[int(c)] for c in int_string] - dec_symbols = [system.digits[int(c)] for c in dec_string] - if dec_string: - result_symbols += [system.math.point] + dec_symbols - - if alt_two: - liang = CND(2, system.digits[2].alt_s, system.digits[2].alt_t, - system.digits[2].big_s, system.digits[2].big_t) - for i, v in enumerate(result_symbols): - if isinstance(v, CND) and v.value == 2: - next_symbol = result_symbols[i + - 1] if i < len(result_symbols) - 1 else None - previous_symbol = result_symbols[i - 1] if i > 0 else None - if isinstance(next_symbol, CNU) and isinstance(previous_symbol, (CNU, type(None))): - if next_symbol.power != 1 and ((previous_symbol is None) or (previous_symbol.power != 1)): - result_symbols[i] = liang - - # if big is True, '两' will not be used and `alt_two` has no impact on output - if big: - attr_name = 'big_' - if traditional: - attr_name += 't' - else: - attr_name += 's' - else: - if traditional: - attr_name = 'traditional' - else: - attr_name = 'simplified' - - result = ''.join([getattr(s, attr_name) for s in result_symbols]) - - # if not use_zeros: - # result = result.strip(getattr(system.digits[0], attr_name)) - - if alt_zero: - result = result.replace( - getattr(system.digits[0], attr_name), system.digits[0].alt_s) - - if alt_one: - result = result.replace( - getattr(system.digits[1], attr_name), system.digits[1].alt_s) - - for i, p in enumerate(POINT): - if result.startswith(p): - return CHINESE_DIGIS[0] + result - - # ^10, 11, .., 19 - if len(result) >= 2 and result[1] in [SMALLER_CHINESE_NUMERING_UNITS_SIMPLIFIED[0], - SMALLER_CHINESE_NUMERING_UNITS_TRADITIONAL[0]] and \ - result[0] in [CHINESE_DIGIS[1], BIG_CHINESE_DIGIS_SIMPLIFIED[1], BIG_CHINESE_DIGIS_TRADITIONAL[1]]: - result = result[1:] - - return result - - -# ================================================================================ # -# different types of rewriters -# ================================================================================ # -class Cardinal: - """ - CARDINAL类 - """ - - def __init__(self, cardinal=None, chntext=None): - self.cardinal = cardinal - self.chntext = chntext - - def chntext2cardinal(self): - return chn2num(self.chntext) - - def cardinal2chntext(self): - return num2chn(self.cardinal) - -class Digit: - """ - DIGIT类 - """ - - def __init__(self, digit=None, chntext=None): - self.digit = digit - self.chntext = chntext - - # def chntext2digit(self): - # return chn2num(self.chntext) - - def digit2chntext(self): - return num2chn(self.digit, alt_two=False, use_units=False) - - -class TelePhone: - """ - TELEPHONE类 - """ - - def __init__(self, telephone=None, raw_chntext=None, chntext=None): - self.telephone = telephone - self.raw_chntext = raw_chntext - self.chntext = chntext - - # def chntext2telephone(self): - # sil_parts = self.raw_chntext.split('') - # self.telephone = '-'.join([ - # str(chn2num(p)) for p in sil_parts - # ]) - # return self.telephone - - def telephone2chntext(self, fixed=False): - - if fixed: - sil_parts = self.telephone.split('-') - self.raw_chntext = ''.join([ - num2chn(part, alt_two=False, use_units=False) for part in sil_parts - ]) - self.chntext = self.raw_chntext.replace('', '') - else: - sp_parts = self.telephone.strip('+').split() - self.raw_chntext = ''.join([ - num2chn(part, alt_two=False, use_units=False) for part in sp_parts - ]) - self.chntext = self.raw_chntext.replace('', '') - return self.chntext - - -class Fraction: - """ - FRACTION类 - """ - - def __init__(self, fraction=None, chntext=None): - self.fraction = fraction - self.chntext = chntext - - def chntext2fraction(self): - denominator, numerator = self.chntext.split('分之') - return chn2num(numerator) + '/' + chn2num(denominator) - - def fraction2chntext(self): - numerator, denominator = self.fraction.split('/') - return num2chn(denominator) + '分之' + num2chn(numerator) - - -class Date: - """ - DATE类 - """ - - def __init__(self, date=None, chntext=None): - self.date = date - self.chntext = chntext - - # def chntext2date(self): - # chntext = self.chntext - # try: - # year, other = chntext.strip().split('年', maxsplit=1) - # year = Digit(chntext=year).digit2chntext() + '年' - # except ValueError: - # other = chntext - # year = '' - # if other: - # try: - # month, day = other.strip().split('月', maxsplit=1) - # month = Cardinal(chntext=month).chntext2cardinal() + '月' - # except ValueError: - # day = chntext - # month = '' - # if day: - # day = Cardinal(chntext=day[:-1]).chntext2cardinal() + day[-1] - # else: - # month = '' - # day = '' - # date = year + month + day - # self.date = date - # return self.date - - def date2chntext(self): - date = self.date - try: - year, other = date.strip().split('年', 1) - year = Digit(digit=year).digit2chntext() + '年' - except ValueError: - other = date - year = '' - if other: - try: - month, day = other.strip().split('月', 1) - month = Cardinal(cardinal=month).cardinal2chntext() + '月' - except ValueError: - day = date - month = '' - if day: - day = Cardinal(cardinal=day[:-1]).cardinal2chntext() + day[-1] - else: - month = '' - day = '' - chntext = year + month + day - self.chntext = chntext - return self.chntext - - -class Money: - """ - MONEY类 - """ - - def __init__(self, money=None, chntext=None): - self.money = money - self.chntext = chntext - - # def chntext2money(self): - # return self.money - - def money2chntext(self): - money = self.money - pattern = re.compile(r'(\d+(\.\d+)?)') - matchers = pattern.findall(money) - if matchers: - for matcher in matchers: - money = money.replace(matcher[0], Cardinal(cardinal=matcher[0]).cardinal2chntext()) - self.chntext = money - return self.chntext - - -class Percentage: - """ - PERCENTAGE类 - """ - - def __init__(self, percentage=None, chntext=None): - self.percentage = percentage - self.chntext = chntext - - def chntext2percentage(self): - return chn2num(self.chntext.strip().strip('百分之')) + '%' - - def percentage2chntext(self): - return '百分之' + num2chn(self.percentage.strip().strip('%')) - - -def remove_erhua(text, er_whitelist): - """ - 去除儿化音词中的儿: - 他女儿在那边儿 -> 他女儿在那边 - """ - - er_pattern = re.compile(er_whitelist) - new_str='' - while re.search('儿',text): - a = re.search('儿',text).span() - remove_er_flag = 0 - - if er_pattern.search(text): - b = er_pattern.search(text).span() - if b[0] <= a[0]: - remove_er_flag = 1 - - if remove_er_flag == 0 : - new_str = new_str + text[0:a[0]] - text = text[a[1]:] - else: - new_str = new_str + text[0:b[1]] - text = text[b[1]:] - - text = new_str + text - return text - -# ================================================================================ # -# NSW Normalizer -# ================================================================================ # -class NSWNormalizer: - def __init__(self, raw_text): - self.raw_text = '^' + raw_text + '$' - self.norm_text = '' - - def _particular(self): - text = self.norm_text - pattern = re.compile(r"(([a-zA-Z]+)二([a-zA-Z]+))") - matchers = pattern.findall(text) - if matchers: - # print('particular') - for matcher in matchers: - text = text.replace(matcher[0], matcher[1]+'2'+matcher[2], 1) - self.norm_text = text - return self.norm_text - - def normalize(self): - text = self.raw_text - - # 规范化日期 - pattern = re.compile(r"\D+((([089]\d|(19|20)\d{2})年)?(\d{1,2}月(\d{1,2}[日号])?)?)") - matchers = pattern.findall(text) - if matchers: - #print('date') - for matcher in matchers: - text = text.replace(matcher[0], Date(date=matcher[0]).date2chntext(), 1) - - # 规范化金钱 - pattern = re.compile(r"\D+((\d+(\.\d+)?)[多余几]?" + CURRENCY_UNITS + r"(\d" + CURRENCY_UNITS + r"?)?)") - matchers = pattern.findall(text) - if matchers: - #print('money') - for matcher in matchers: - text = text.replace(matcher[0], Money(money=matcher[0]).money2chntext(), 1) - - # 规范化固话/手机号码 - # 手机 - # http://www.jihaoba.com/news/show/13680 - # 移动:139、138、137、136、135、134、159、158、157、150、151、152、188、187、182、183、184、178、198 - # 联通:130、131、132、156、155、186、185、176 - # 电信:133、153、189、180、181、177 - pattern = re.compile(r"\D((\+?86 ?)?1([38]\d|5[0-35-9]|7[678]|9[89])\d{8})\D") - matchers = pattern.findall(text) - if matchers: - #print('telephone') - for matcher in matchers: - text = text.replace(matcher[0], TelePhone(telephone=matcher[0]).telephone2chntext(), 1) - # 固话 - pattern = re.compile(r"\D((0(10|2[1-3]|[3-9]\d{2})-?)?[1-9]\d{6,7})\D") - matchers = pattern.findall(text) - if matchers: - # print('fixed telephone') - for matcher in matchers: - text = text.replace(matcher[0], TelePhone(telephone=matcher[0]).telephone2chntext(fixed=True), 1) - - # 规范化分数 - pattern = re.compile(r"(\d+/\d+)") - matchers = pattern.findall(text) - if matchers: - #print('fraction') - for matcher in matchers: - text = text.replace(matcher, Fraction(fraction=matcher).fraction2chntext(), 1) - - # 规范化百分数 - text = text.replace('%', '%') - pattern = re.compile(r"(\d+(\.\d+)?%)") - matchers = pattern.findall(text) - if matchers: - #print('percentage') - for matcher in matchers: - text = text.replace(matcher[0], Percentage(percentage=matcher[0]).percentage2chntext(), 1) - - # 规范化纯数+量词 - pattern = re.compile(r"(\d+(\.\d+)?)[多余几]?" + COM_QUANTIFIERS) - matchers = pattern.findall(text) - if matchers: - #print('cardinal+quantifier') - for matcher in matchers: - text = text.replace(matcher[0], Cardinal(cardinal=matcher[0]).cardinal2chntext(), 1) - - # 规范化数字编号 - pattern = re.compile(r"(\d{4,32})") - matchers = pattern.findall(text) - if matchers: - #print('digit') - for matcher in matchers: - text = text.replace(matcher, Digit(digit=matcher).digit2chntext(), 1) - - # 规范化纯数 - pattern = re.compile(r"(\d+(\.\d+)?)") - matchers = pattern.findall(text) - if matchers: - #print('cardinal') - for matcher in matchers: - text = text.replace(matcher[0], Cardinal(cardinal=matcher[0]).cardinal2chntext(), 1) - - self.norm_text = text - self._particular() - - return self.norm_text.lstrip('^').rstrip('$') - - -def nsw_test_case(raw_text): - print('I:' + raw_text) - print('O:' + NSWNormalizer(raw_text).normalize()) - print('') - - -def nsw_test(): - nsw_test_case('固话:0595-23865596或23880880。') - nsw_test_case('固话:0595-23865596或23880880。') - nsw_test_case('手机:+86 19859213959或15659451527。') - nsw_test_case('分数:32477/76391。') - nsw_test_case('百分数:80.03%。') - nsw_test_case('编号:31520181154418。') - nsw_test_case('纯数:2983.07克或12345.60米。') - nsw_test_case('日期:1999年2月20日或09年3月15号。') - nsw_test_case('金钱:12块5,34.5元,20.1万') - nsw_test_case('特殊:O2O或B2C。') - nsw_test_case('3456万吨') - nsw_test_case('2938个') - nsw_test_case('938') - nsw_test_case('今天吃了115个小笼包231个馒头') - nsw_test_case('有62%的概率') - - -if __name__ == '__main__': - #nsw_test() - - p = argparse.ArgumentParser() - p.add_argument('ifile', help='input filename, assume utf-8 encoding') - p.add_argument('ofile', help='output filename') - p.add_argument('--to_upper', action='store_true', help='convert to upper case') - p.add_argument('--to_lower', action='store_true', help='convert to lower case') - p.add_argument('--has_key', action='store_true', help="input text has Kaldi's key as first field.") - p.add_argument('--remove_fillers', type=bool, default=True, help='remove filler chars such as "呃, 啊"') - p.add_argument('--remove_erhua', type=bool, default=True, help='remove erhua chars such as "这儿"') - p.add_argument('--log_interval', type=int, default=10000, help='log interval in number of processed lines') - args = p.parse_args() - - ifile = codecs.open(args.ifile, 'r', 'utf8') - ofile = codecs.open(args.ofile, 'w+', 'utf8') - - n = 0 - for l in ifile: - key = '' - text = '' - if args.has_key: - cols = l.split(maxsplit=1) - key = cols[0] - if len(cols) == 2: - text = cols[1].strip() - else: - text = '' - else: - text = l.strip() - - # cases - if args.to_upper and args.to_lower: - sys.stderr.write('text norm: to_upper OR to_lower?') - exit(1) - if args.to_upper: - text = text.upper() - if args.to_lower: - text = text.lower() - - # Filler chars removal - if args.remove_fillers: - for ch in FILLER_CHARS: - text = text.replace(ch, '') - - if args.remove_erhua: - text = remove_erhua(text, ER_WHITELIST) - - # NSW(Non-Standard-Word) normalization - text = NSWNormalizer(text).normalize() - - # Punctuations removal - old_chars = CHINESE_PUNC_LIST + string.punctuation # includes all CN and EN punctuations - new_chars = ' ' * len(old_chars) - del_chars = '' - text = text.translate(str.maketrans(old_chars, new_chars, del_chars)) - - # - if args.has_key: - ofile.write(key + '\t' + text + '\n') - else: - ofile.write(text + '\n') - - n += 1 - if n % args.log_interval == 0: - sys.stderr.write("text norm: {} lines done.\n".format(n)) - - sys.stderr.write("text norm: {} lines done in total.\n".format(n)) - - ifile.close() - ofile.close() diff --git a/egs/aishell2/conformer/conf/decode_asr_transformer.yaml b/egs/aishell2/conformer/conf/decode_asr_transformer.yaml deleted file mode 100644 index a147fa79d..000000000 --- a/egs/aishell2/conformer/conf/decode_asr_transformer.yaml +++ /dev/null @@ -1,6 +0,0 @@ -beam_size: 10 -penalty: 0.0 -maxlenratio: 0.0 -minlenratio: 0.0 -ctc_weight: 0.5 -lm_weight: 0.7 diff --git a/egs/aishell2/conformer/conf/train_asr_conformer.yaml b/egs/aishell2/conformer/conf/train_asr_conformer.yaml deleted file mode 100644 index 8183378fb..000000000 --- a/egs/aishell2/conformer/conf/train_asr_conformer.yaml +++ /dev/null @@ -1,99 +0,0 @@ -# network architecture -# encoder related -encoder: conformer -encoder_conf: - output_size: 256 # dimension of attention - attention_heads: 4 - linear_units: 2048 # the number of units of position-wise feed forward - num_blocks: 12 # the number of encoder blocks - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - attention_dropout_rate: 0.0 - input_layer: conv2d # encoder architecture type - normalize_before: true - pos_enc_layer_type: rel_pos - selfattention_layer_type: rel_selfattn - activation_type: swish - macaron_style: true - use_cnn_module: true - cnn_module_kernel: 15 - -# decoder related -decoder: transformer -decoder_conf: - attention_heads: 4 - linear_units: 2048 - num_blocks: 6 - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - self_attention_dropout_rate: 0.0 - src_attention_dropout_rate: 0.0 - -# frontend related -frontend: wav_frontend -frontend_conf: - fs: 16000 - window: hamming - n_mels: 80 - frame_length: 25 - frame_shift: 10 - lfr_m: 1 - lfr_n: 1 - -# hybrid CTC/attention -model_conf: - ctc_weight: 0.3 - lsm_weight: 0.1 # label smoothing option - length_normalized_loss: false - -# optimization related -accum_grad: 2 -grad_clip: 5 -patience: none -max_epoch: 150 -val_scheduler_criterion: - - valid - - acc -best_model_criterion: -- - valid - - acc - - max -keep_nbest_models: 10 - -optim: adam -optim_conf: - lr: 0.0005 -scheduler: warmuplr -scheduler_conf: - warmup_steps: 30000 - -specaug: specaug -specaug_conf: - apply_time_warp: true - time_warp_window: 5 - time_warp_mode: bicubic - apply_freq_mask: true - freq_mask_width_range: - - 0 - - 30 - num_freq_mask: 2 - apply_time_mask: true - time_mask_width_range: - - 0 - - 40 - num_time_mask: 2 - -dataset_conf: - data_names: speech,text - data_types: sound,text - shuffle: True - shuffle_conf: - shuffle_size: 2048 - sort_size: 500 - batch_conf: - batch_type: token - batch_size: 25000 - num_workers: 8 - -log_interval: 50 -normalize: None diff --git a/egs/aishell2/conformer/local/prepare_data.sh b/egs/aishell2/conformer/local/prepare_data.sh deleted file mode 100755 index 77791f9c1..000000000 --- a/egs/aishell2/conformer/local/prepare_data.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env bash -# Copyright 2018 AIShell-Foundation(Authors:Jiayu DU, Xingyu NA, Bengu WU, Hao ZHENG) -# 2018 Beijing Shell Shell Tech. Co. Ltd. (Author: Hui BU) -# Apache 2.0 - -# transform raw AISHELL-2 data to kaldi format - -. ./path.sh || exit 1; - -tmp= -dir= - -if [ $# != 3 ]; then - echo "Usage: $0 " - echo " $0 /export/AISHELL-2/iOS/train data/local/train data/train" - exit 1; -fi - -corpus=$1 -tmp=$2 -dir=$3 - -echo "prepare_data.sh: Preparing data in $corpus" - -mkdir -p $tmp -mkdir -p $dir - -# corpus check -if [ ! -d $corpus ] || [ ! -f $corpus/wav.scp ] || [ ! -f $corpus/trans.txt ]; then - echo "Error: $0 requires wav.scp and trans.txt under $corpus directory." - exit 1; -fi - -# validate utt-key list, IC0803W0380 is a bad utterance -awk '{print $1}' $corpus/wav.scp | grep -v 'IC0803W0380' > $tmp/wav_utt.list -awk '{print $1}' $corpus/trans.txt > $tmp/trans_utt.list -utils/filter_scp.pl -f 1 $tmp/wav_utt.list $tmp/trans_utt.list > $tmp/utt.list - -# wav.scp -awk -F'\t' -v path_prefix=$corpus '{printf("%s\t%s/%s\n",$1,path_prefix,$2)}' $corpus/wav.scp > $tmp/tmp_wav.scp -utils/filter_scp.pl -f 1 $tmp/utt.list $tmp/tmp_wav.scp | sort -k 1 | uniq > $tmp/wav.scp - -# text -utils/filter_scp.pl -f 1 $tmp/utt.list $corpus/trans.txt | sort -k 1 | uniq > $tmp/text - -# copy prepared resources from tmp_dir to target dir -mkdir -p $dir -for f in wav.scp text; do - cp $tmp/$f $dir/$f || exit 1; -done - -echo "local/prepare_data.sh succeeded" -exit 0; diff --git a/egs/aishell2/conformer/path.sh b/egs/aishell2/conformer/path.sh deleted file mode 100755 index ea3c0be2f..000000000 --- a/egs/aishell2/conformer/path.sh +++ /dev/null @@ -1,6 +0,0 @@ -export FUNASR_DIR=$PWD/../../.. - -# NOTE(kan-bayashi): Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C -export PYTHONIOENCODING=UTF-8 -export PYTHONPATH=../../../:$PYTHONPATH -export PATH=$FUNASR_DIR/funasr/bin:$PATH diff --git a/egs/aishell2/conformer/run.sh b/egs/aishell2/conformer/run.sh deleted file mode 100755 index 193c4a3d1..000000000 --- a/egs/aishell2/conformer/run.sh +++ /dev/null @@ -1,230 +0,0 @@ -#!/usr/bin/env bash - -. ./path.sh || exit 1; - -# machines configuration -CUDA_VISIBLE_DEVICES="0,1,2,3,4,5,6,7" -gpu_num=8 -count=1 -gpu_inference=true # Whether to perform gpu decoding, set false for cpu decoding -# for gpu decoding, inference_nj=ngpu*njob; for cpu decoding, inference_nj=njob -njob=5 -train_cmd=utils/run.pl -infer_cmd=utils/run.pl - -# general configuration -feats_dir="../DATA" #feature output dictionary -exp_dir="." -lang=zh -token_type=char -type=sound -scp=wav.scp -speed_perturb="0.9 1.0 1.1" -dataset_type=large -stage=0 -stop_stage=5 - -# feature configuration -feats_dim=80 -nj=64 - -# data -tr_dir= -dev_tst_dir= - -# exp tag -tag="exp1" - -. utils/parse_options.sh || exit 1; - -# Set bash to 'debug' mode, it will exit on : -# -e 'error', -u 'undefined variable', -o ... 'error in pipeline', -x 'print commands', -set -e -set -u -set -o pipefail - -train_set=train -valid_set=dev_ios -test_sets="dev_ios test_ios" - -asr_config=conf/train_asr_conformer.yaml -model_dir="baseline_$(basename "${asr_config}" .yaml)_${lang}_${token_type}_${tag}" - -inference_config=conf/decode_asr_transformer.yaml -inference_asr_model=valid.acc.ave_10best.pb - -# you can set gpu num for decoding here -gpuid_list=$CUDA_VISIBLE_DEVICES # set gpus for decoding, the same as training stage by default -ngpu=$(echo $gpuid_list | awk -F "," '{print NF}') - -if ${gpu_inference}; then - inference_nj=$[${ngpu}*${njob}] - _ngpu=1 -else - inference_nj=$njob - _ngpu=0 -fi - -if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then - echo "stage 0: Data preparation" - # For training set - local/prepare_data.sh ${tr_dir} ${feats_dir}/data/local/train ${feats_dir}/data/train || exit 1; - # # For dev and test set - for x in iOS; do - local/prepare_data.sh ${dev_tst_dir}/${x}/dev ${feats_dir}/data/local/dev_${x,,} ${feats_dir}/data/dev_${x,,} || exit 1; - local/prepare_data.sh ${dev_tst_dir}/${x}/test ${feats_dir}/data/local/test_${x,,} ${feats_dir}/data/test_${x,,} || exit 1; - done - # Normalize text to capital letters - for x in train dev_ios test_ios; do - mv ${feats_dir}/data/${x}/text ${feats_dir}/data/${x}/text.org - paste -d " " <(cut -f 1 ${feats_dir}/data/${x}/text.org) <(cut -f 2- ${feats_dir}/data/${x}/text.org \ - | tr 'A-Z' 'a-z' | tr -d " ") \ - > ${feats_dir}/data/${x}/text - utils/text2token.py -n 1 -s 1 ${feats_dir}/data/${x}/text > ${feats_dir}/data/${x}/text.org - mv ${feats_dir}/data/${x}/text.org ${feats_dir}/data/${x}/text - done -fi - -if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then - echo "stage 1: Feature and CMVN Generation" - utils/compute_cmvn.sh --fbankdir ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config_file "$asr_config" --scale 1.0 -fi - -token_list=${feats_dir}/data/${lang}_token_list/$token_type/tokens.txt -echo "dictionary: ${token_list}" -if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then - echo "stage 2: Dictionary Preparation" - mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/ - - echo "make a dictionary" - echo "" > ${token_list} - echo "" >> ${token_list} - echo "" >> ${token_list} - utils/text2token.py -s 1 -n 1 --space "" ${feats_dir}/data/${train_set}/text | cut -f 2- -d" " | tr " " "\n" \ - | sort | uniq | grep -a -v -e '^\s*$' | awk '{print $0}' >> ${token_list} - echo "" >> ${token_list} - fi - -# LM Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then - echo "stage 3: LM Training" -fi - -# ASR Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then - echo "stage 4: ASR Training" - mkdir -p ${exp_dir}/exp/${model_dir} - mkdir -p ${exp_dir}/exp/${model_dir}/log - INIT_FILE=${exp_dir}/exp/${model_dir}/ddp_init - if [ -f $INIT_FILE ];then - rm -f $INIT_FILE - fi - init_method=file://$(readlink -f $INIT_FILE) - echo "$0: init method is $init_method" - for ((i = 0; i < $gpu_num; ++i)); do - { - rank=$i - local_rank=$i - gpu_id=$(echo $CUDA_VISIBLE_DEVICES | cut -d',' -f$[$i+1]) - train.py \ - --task_name asr \ - --gpu_id $gpu_id \ - --use_preprocessor true \ - --token_type $token_type \ - --token_list $token_list \ - --data_dir ${feats_dir}/data \ - --train_set ${train_set} \ - --valid_set ${valid_set} \ - --data_file_names "wav.scp,text" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --speed_perturb ${speed_perturb} \ - --dataset_type $dataset_type \ - --resume true \ - --output_dir ${exp_dir}/exp/${model_dir} \ - --config $asr_config \ - --ngpu $gpu_num \ - --num_worker_count $count \ - --dist_init_method $init_method \ - --dist_world_size $world_size \ - --dist_rank $rank \ - --local_rank $local_rank 1> ${exp_dir}/exp/${model_dir}/log/train.log.$i 2>&1 - } & - done - wait -fi - -# Testing Stage -if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then - echo "stage 5: Inference" - for dset in ${test_sets}; do - asr_exp=${exp_dir}/exp/${model_dir} - inference_tag="$(basename "${inference_config}" .yaml)" - _dir="${asr_exp}/${inference_tag}/${inference_asr_model}/${dset}" - _logdir="${_dir}/logdir" - if [ -d ${_dir} ]; then - echo "${_dir} is already exists. if you want to decode again, please delete this dir first." - exit 0 - fi - mkdir -p "${_logdir}" - _data="${feats_dir}/data/${dset}" - key_file=${_data}/${scp} - num_scp_file="$(<${key_file} wc -l)" - _nj=$([ $inference_nj -le $num_scp_file ] && echo "$inference_nj" || echo "$num_scp_file") - split_scps= - for n in $(seq "${_nj}"); do - split_scps+=" ${_logdir}/keys.${n}.scp" - done - # shellcheck disable=SC2086 - utils/split_scp.pl "${key_file}" ${split_scps} - _opts= - if [ -n "${inference_config}" ]; then - _opts+="--config ${inference_config} " - fi - ${infer_cmd} --gpu "${_ngpu}" --max-jobs-run "${_nj}" JOB=1:"${_nj}" "${_logdir}"/asr_inference.JOB.log \ - python -m funasr.bin.asr_inference_launch \ - --batch_size 1 \ - --ngpu "${_ngpu}" \ - --njob ${njob} \ - --gpuid_list ${gpuid_list} \ - --data_path_and_name_and_type "${_data}/${scp},speech,${type}" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --key_file "${_logdir}"/keys.JOB.scp \ - --asr_train_config "${asr_exp}"/config.yaml \ - --asr_model_file "${asr_exp}"/"${inference_asr_model}" \ - --output_dir "${_logdir}"/output.JOB \ - --mode asr \ - ${_opts} - - for f in token token_int score text; do - if [ -f "${_logdir}/output.1/1best_recog/${f}" ]; then - for i in $(seq "${_nj}"); do - cat "${_logdir}/output.${i}/1best_recog/${f}" - done | sort -k1 >"${_dir}/${f}" - fi - done - python utils/proce_text.py ${_dir}/text ${_dir}/text.proc - python utils/proce_text.py ${_data}/text ${_data}/text.proc - python utils/compute_wer.py ${_data}/text.proc ${_dir}/text.proc ${_dir}/text.cer - tail -n 3 ${_dir}/text.cer > ${_dir}/text.cer.txt - cat ${_dir}/text.cer.txt - done -fi - -# Prepare files for ModelScope fine-tuning and inference -if [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then - echo "stage 6: ModelScope Preparation" - cp ${feats_dir}/data/${train_set}/cmvn/am.mvn ${exp_dir}/exp/${model_dir}/am.mvn - vocab_size=$(cat ${token_list} | wc -l) - python utils/gen_modelscope_configuration.py \ - --am_model_name $inference_asr_model \ - --mode asr \ - --model_name conformer \ - --dataset aishell2 \ - --output_dir $exp_dir/exp/$model_dir \ - --vocab_size $vocab_size \ - --tag $tag -fi - - diff --git a/egs/aishell2/conformer/utils b/egs/aishell2/conformer/utils deleted file mode 120000 index fe070dd3a..000000000 --- a/egs/aishell2/conformer/utils +++ /dev/null @@ -1 +0,0 @@ -../../aishell/transformer/utils \ No newline at end of file diff --git a/egs/aishell2/data2vec_pretrain/conf/train_pretrain_transformer.yaml b/egs/aishell2/data2vec_pretrain/conf/train_pretrain_transformer.yaml deleted file mode 100644 index 767d8bafd..000000000 --- a/egs/aishell2/data2vec_pretrain/conf/train_pretrain_transformer.yaml +++ /dev/null @@ -1,87 +0,0 @@ -# network architecture -# encoder related -encoder: data2vec_encoder -encoder_conf: - extractor_mode: layer_norm - encoder_layerdrop: 0.05 - dropout_input: 0.0 - dropout_features: 0.0 - feature_grad_mult: 1.0 - encoder_embed_dim: 768 - - mask_prob: 0.65 - mask_length: 10 - - loss_beta: 0 - loss_scale: null - - instance_norm_target_layer: true - average_top_k_layers: 8 - - pos_conv_depth: 5 - conv_pos: 95 - - ema_decay: 0.999 - ema_end_decay: 0.9999 - ema_anneal_end_step: 30000 - ema_transformer_only: true - ema_layers_only: true - - require_same_masks: true - mask_dropout: 0 - -# frontend related -frontend: wav_frontend -frontend_conf: - fs: 16000 - window: hamming - n_mels: 80 - frame_length: 25 - frame_shift: 10 - lfr_m: 1 - lfr_n: 1 - -model: data2vec - -# optimization related -accum_grad: 1 -grad_clip: 5 -patience: none -max_epoch: 1800 -val_scheduler_criterion: - - valid - - acc -best_model_criterion: -- - valid - - loss - - min -keep_nbest_models: 50 -unused_parameters: true - -optim: fairseq_adam -optim_conf: - lr: 0.0005 - adam_betas: [0.9,0.98] - adam_eps: 1.0e-06 - weight_decay: 0.01 - -scheduler: tri_stage -scheduler_conf: - phase_ratio: [0.03,0.9,0.07] - -# for dataset -dataset_conf: - batch_mode: clipping - data_names: speech - data_types: sound - shuffle: true - shuffle_conf: - shuffle_size: 12800 - sort_size: 12800 - batch_conf: - batch_type: token - batch_size: 64000 - num_workers: 8 - -log_interval: 50 -normalize: None \ No newline at end of file diff --git a/egs/aishell2/data2vec_pretrain/local/prepare_data.sh b/egs/aishell2/data2vec_pretrain/local/prepare_data.sh deleted file mode 100755 index ce6ee1909..000000000 --- a/egs/aishell2/data2vec_pretrain/local/prepare_data.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env bash -# Copyright 2018 AIShell-Foundation(Authors:Jiayu DU, Xingyu NA, Bengu WU, Hao ZHENG) -# 2018 Beijing Shell Shell Tech. Co. Ltd. (Author: Hui BU) -# Apache 2.0 - -# transform raw AISHELL-2 data to kaldi format - -. ./path.sh || exit 1; - -tmp= -dir= - -if [ $# != 3 ]; then - echo "Usage: $0 " - echo " $0 /export/AISHELL-2/iOS/train data/local/train data/train" - exit 1; -fi - -corpus=$1 -tmp=$2 -dir=$3 - -echo "prepare_data.sh: Preparing data in $corpus" - -mkdir -p $tmp -mkdir -p $dir - -# corpus check -if [ ! -d $corpus ] || [ ! -f $corpus/wav.scp ] || [ ! -f $corpus/trans.txt ]; then - echo "Error: $0 requires wav.scp and trans.txt under $corpus directory." - exit 1; -fi - -# validate utt-key list, IC0803W0380 is a bad utterance -awk '{print $1}' $corpus/wav.scp | grep -v 'IC0803W0380' > $tmp/wav_utt.list -awk '{print $1}' $corpus/trans.txt > $tmp/trans_utt.list -tools/filter_scp.pl -f 1 $tmp/wav_utt.list $tmp/trans_utt.list > $tmp/utt.list - -# wav.scp -awk -F'\t' -v path_prefix=$corpus '{printf("%s\t%s/%s\n",$1,path_prefix,$2)}' $corpus/wav.scp > $tmp/tmp_wav.scp -tools/filter_scp.pl -f 1 $tmp/utt.list $tmp/tmp_wav.scp | sort -k 1 | uniq > $tmp/wav.scp - -# text -tools/filter_scp.pl -f 1 $tmp/utt.list $corpus/trans.txt | sort -k 1 | uniq > $tmp/text - -# copy prepared resources from tmp_dir to target dir -mkdir -p $dir -for f in wav.scp text; do - cp $tmp/$f $dir/$f || exit 1; -done - -echo "local/prepare_data.sh succeeded" -exit 0; diff --git a/egs/aishell2/data2vec_pretrain/path.sh b/egs/aishell2/data2vec_pretrain/path.sh deleted file mode 100755 index ea3c0be2f..000000000 --- a/egs/aishell2/data2vec_pretrain/path.sh +++ /dev/null @@ -1,6 +0,0 @@ -export FUNASR_DIR=$PWD/../../.. - -# NOTE(kan-bayashi): Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C -export PYTHONIOENCODING=UTF-8 -export PYTHONPATH=../../../:$PYTHONPATH -export PATH=$FUNASR_DIR/funasr/bin:$PATH diff --git a/egs/aishell2/data2vec_pretrain/run.sh b/egs/aishell2/data2vec_pretrain/run.sh deleted file mode 100755 index 3df39af43..000000000 --- a/egs/aishell2/data2vec_pretrain/run.sh +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env bash - -. ./path.sh || exit 1; - -# machines configuration -CUDA_VISIBLE_DEVICES="0,1,2,3,4,5,6,7" -gpu_num=8 -count=1 - -train_cmd=utils/run.pl - -# general configuration -feats_dir="../DATA" #feature output dictionary -exp_dir="." -lang=zh -token_type=char -speed_perturb="0.9 1.0 1.1" -dataset_type=large -stage=0 -stop_stage=3 - -# feature configuration -nj=64 - -# data -tr_dir= -dev_tst_dir= - -# exp tag -tag="exp1" - -. utils/parse_options.sh || exit 1; - -# Set bash to 'debug' mode, it will exit on : -# -e 'error', -u 'undefined variable', -o ... 'error in pipeline', -x 'print commands', -set -e -set -u -set -o pipefail - -train_set=train -valid_set=dev_ios - -asr_config=conf/train_pretrain_transformer.yaml -model_dir="baseline_$(basename "${asr_config}" .yaml)_${lang}_${token_type}_${tag}" - -if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then - echo "stage 0: Data preparation" - # For training set - local/prepare_data.sh ${tr_dir} ${feats_dir}/data/local/train ${feats_dir}/data/train || exit 1; - # # For dev and test set - for x in iOS; do - local/prepare_data.sh ${dev_tst_dir}/${x}/dev ${feats_dir}/data/local/dev_${x,,} ${feats_dir}/data/dev_${x,,} || exit 1; - local/prepare_data.sh ${dev_tst_dir}/${x}/test ${feats_dir}/data/local/test_${x,,} ${feats_dir}/data/test_${x,,} || exit 1; - done - # Normalize text to capital letters - for x in train dev_ios test_ios; do - mv ${feats_dir}/data/${x}/text ${feats_dir}/data/${x}/text.org - paste -d " " <(cut -f 1 ${feats_dir}/data/${x}/text.org) <(cut -f 2- ${feats_dir}/data/${x}/text.org \ - | tr 'A-Z' 'a-z' | tr -d " ") \ - > ${feats_dir}/data/${x}/text - utils/text2token.py -n 1 -s 1 ${feats_dir}/data/${x}/text > ${feats_dir}/data/${x}/text.org - mv ${feats_dir}/data/${x}/text.org ${feats_dir}/data/${x}/text - done -fi - -if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then - echo "stage 1: Feature and CMVN Generation" - utils/compute_cmvn.sh --fbankdir ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config_file "$asr_config" --scale 1.0 -fi - -token_list=${feats_dir}/data/${lang}_token_list/char/tokens.txt -echo "dictionary: ${token_list}" -if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then - echo "stage 2: Dictionary Preparation" - mkdir -p ${feats_dir}/data/${lang}_token_list/char/ - - echo "make a dictionary" - echo "" > ${token_list} - echo "" >> ${token_list} - echo "" >> ${token_list} - utils/text2token.py -s 1 -n 1 --space "" ${feats_dir}/data/${train_set}/text | cut -f 2- -d" " | tr " " "\n" \ - | sort | uniq | grep -a -v -e '^\s*$' | awk '{print $0}' >> ${token_list} - echo "" >> ${token_list} - fi - -# Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then - echo "stage 3: Training" - mkdir -p ${exp_dir}/exp/${model_dir} - mkdir -p ${exp_dir}/exp/${model_dir}/log - INIT_FILE=${exp_dir}/exp/${model_dir}/ddp_init - if [ -f $INIT_FILE ];then - rm -f $INIT_FILE - fi - init_method=file://$(readlink -f $INIT_FILE) - echo "$0: init method is $init_method" - for ((i = 0; i < $gpu_num; ++i)); do - { - rank=$i - local_rank=$i - gpu_id=$(echo $CUDA_VISIBLE_DEVICES | cut -d',' -f$[$i+1]) - train.py \ - --task_name pretrain \ - --gpu_id $gpu_id \ - --use_preprocessor true \ - --data_dir ${feats_dir}/data \ - --train_set ${train_set} \ - --valid_set ${valid_set} \ - --data_file_names "wav.scp" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --speed_perturb ${speed_perturb} \ - --dataset_type $dataset_type \ - --resume true \ - --output_dir ${exp_dir}/exp/${model_dir} \ - --config $asr_config \ - --ngpu $gpu_num \ - --num_worker_count $count \ - --multiprocessing_distributed true \ - --dist_init_method $init_method \ - --dist_world_size $world_size \ - --dist_rank $rank \ - --local_rank $local_rank 1> ${exp_dir}/exp/${model_dir}/log/train.log.$i 2>&1 - } & - done - wait -fi \ No newline at end of file diff --git a/egs/aishell2/data2vec_pretrain/utils b/egs/aishell2/data2vec_pretrain/utils deleted file mode 120000 index fe070dd3a..000000000 --- a/egs/aishell2/data2vec_pretrain/utils +++ /dev/null @@ -1 +0,0 @@ -../../aishell/transformer/utils \ No newline at end of file diff --git a/egs/aishell2/paraformer/conf/decode_asr_transformer.yaml b/egs/aishell2/paraformer/conf/decode_asr_transformer.yaml deleted file mode 100644 index a147fa79d..000000000 --- a/egs/aishell2/paraformer/conf/decode_asr_transformer.yaml +++ /dev/null @@ -1,6 +0,0 @@ -beam_size: 10 -penalty: 0.0 -maxlenratio: 0.0 -minlenratio: 0.0 -ctc_weight: 0.5 -lm_weight: 0.7 diff --git a/egs/aishell2/paraformer/conf/decode_asr_transformer_noctc_1best.yaml b/egs/aishell2/paraformer/conf/decode_asr_transformer_noctc_1best.yaml deleted file mode 100644 index a147fa79d..000000000 --- a/egs/aishell2/paraformer/conf/decode_asr_transformer_noctc_1best.yaml +++ /dev/null @@ -1,6 +0,0 @@ -beam_size: 10 -penalty: 0.0 -maxlenratio: 0.0 -minlenratio: 0.0 -ctc_weight: 0.5 -lm_weight: 0.7 diff --git a/egs/aishell2/paraformer/conf/train_asr_paraformer_conformer_20e_1280_320_6d_1280_320.yaml b/egs/aishell2/paraformer/conf/train_asr_paraformer_conformer_20e_1280_320_6d_1280_320.yaml deleted file mode 100644 index 3ecf44e31..000000000 --- a/egs/aishell2/paraformer/conf/train_asr_paraformer_conformer_20e_1280_320_6d_1280_320.yaml +++ /dev/null @@ -1,109 +0,0 @@ -# network architecture -# encoder related -encoder: conformer -encoder_conf: - output_size: 320 # dimension of attention - attention_heads: 4 - linear_units: 1280 # the number of units of position-wise feed forward - num_blocks: 20 # the number of encoder blocks - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - attention_dropout_rate: 0.0 - input_layer: conv2d # encoder architecture type - normalize_before: true - pos_enc_layer_type: rel_pos - selfattention_layer_type: rel_selfattn - activation_type: swish - macaron_style: true - use_cnn_module: true - cnn_module_kernel: 15 - -# decoder related -decoder: paraformer_decoder_san -decoder_conf: - attention_heads: 4 - linear_units: 1280 - num_blocks: 6 - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - self_attention_dropout_rate: 0.0 - src_attention_dropout_rate: 0.0 - -# frontend related -frontend: wav_frontend -frontend_conf: - fs: 16000 - window: hamming - n_mels: 80 - frame_length: 25 - frame_shift: 10 - lfr_m: 1 - lfr_n: 1 - -# hybrid CTC/attention -model: paraformer -model_conf: - ctc_weight: 0.3 - lsm_weight: 0.1 - length_normalized_loss: false - predictor_weight: 1.0 - sampling_ratio: 0.4 - -# optimization related -accum_grad: 2 -grad_clip: 5 -patience: none -max_epoch: 150 -val_scheduler_criterion: - - valid - - acc -best_model_criterion: -- - valid - - acc - - max -keep_nbest_models: 10 - -optim: adam -optim_conf: - lr: 0.0005 -scheduler: warmuplr -scheduler_conf: - warmup_steps: 30000 - -specaug: specaug -specaug_conf: - apply_time_warp: true - time_warp_window: 5 - time_warp_mode: bicubic - apply_freq_mask: true - freq_mask_width_range: - - 0 - - 30 - num_freq_mask: 2 - apply_time_mask: true - time_mask_width_range: - - 0 - - 40 - num_time_mask: 2 - -predictor: cif_predictor -predictor_conf: - idim: 320 - threshold: 1.0 - l_order: 1 - r_order: 1 - -dataset_conf: - data_names: speech,text - data_types: sound,text - shuffle: True - shuffle_conf: - shuffle_size: 2048 - sort_size: 500 - batch_conf: - batch_type: token - batch_size: 25000 - num_workers: 8 - -log_interval: 50 -normalize: None diff --git a/egs/aishell2/paraformer/local/prepare_data.sh b/egs/aishell2/paraformer/local/prepare_data.sh deleted file mode 100755 index 77791f9c1..000000000 --- a/egs/aishell2/paraformer/local/prepare_data.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env bash -# Copyright 2018 AIShell-Foundation(Authors:Jiayu DU, Xingyu NA, Bengu WU, Hao ZHENG) -# 2018 Beijing Shell Shell Tech. Co. Ltd. (Author: Hui BU) -# Apache 2.0 - -# transform raw AISHELL-2 data to kaldi format - -. ./path.sh || exit 1; - -tmp= -dir= - -if [ $# != 3 ]; then - echo "Usage: $0 " - echo " $0 /export/AISHELL-2/iOS/train data/local/train data/train" - exit 1; -fi - -corpus=$1 -tmp=$2 -dir=$3 - -echo "prepare_data.sh: Preparing data in $corpus" - -mkdir -p $tmp -mkdir -p $dir - -# corpus check -if [ ! -d $corpus ] || [ ! -f $corpus/wav.scp ] || [ ! -f $corpus/trans.txt ]; then - echo "Error: $0 requires wav.scp and trans.txt under $corpus directory." - exit 1; -fi - -# validate utt-key list, IC0803W0380 is a bad utterance -awk '{print $1}' $corpus/wav.scp | grep -v 'IC0803W0380' > $tmp/wav_utt.list -awk '{print $1}' $corpus/trans.txt > $tmp/trans_utt.list -utils/filter_scp.pl -f 1 $tmp/wav_utt.list $tmp/trans_utt.list > $tmp/utt.list - -# wav.scp -awk -F'\t' -v path_prefix=$corpus '{printf("%s\t%s/%s\n",$1,path_prefix,$2)}' $corpus/wav.scp > $tmp/tmp_wav.scp -utils/filter_scp.pl -f 1 $tmp/utt.list $tmp/tmp_wav.scp | sort -k 1 | uniq > $tmp/wav.scp - -# text -utils/filter_scp.pl -f 1 $tmp/utt.list $corpus/trans.txt | sort -k 1 | uniq > $tmp/text - -# copy prepared resources from tmp_dir to target dir -mkdir -p $dir -for f in wav.scp text; do - cp $tmp/$f $dir/$f || exit 1; -done - -echo "local/prepare_data.sh succeeded" -exit 0; diff --git a/egs/aishell2/paraformer/path.sh b/egs/aishell2/paraformer/path.sh deleted file mode 100755 index ea3c0be2f..000000000 --- a/egs/aishell2/paraformer/path.sh +++ /dev/null @@ -1,6 +0,0 @@ -export FUNASR_DIR=$PWD/../../.. - -# NOTE(kan-bayashi): Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C -export PYTHONIOENCODING=UTF-8 -export PYTHONPATH=../../../:$PYTHONPATH -export PATH=$FUNASR_DIR/funasr/bin:$PATH diff --git a/egs/aishell2/paraformer/run.sh b/egs/aishell2/paraformer/run.sh deleted file mode 100755 index 4268cf638..000000000 --- a/egs/aishell2/paraformer/run.sh +++ /dev/null @@ -1,229 +0,0 @@ -#!/usr/bin/env bash - -. ./path.sh || exit 1; - -# machines configuration -CUDA_VISIBLE_DEVICES="0,1,2,3,4,5,6,7" -gpu_num=8 -count=1 -gpu_inference=true # Whether to perform gpu decoding, set false for cpu decoding -# for gpu decoding, inference_nj=ngpu*njob; for cpu decoding, inference_nj=njob -njob=1 -train_cmd=utils/run.pl -infer_cmd=utils/run.pl - -# general configuration -feats_dir="../DATA" #feature output dictionary -exp_dir="." -lang=zh -token_type=char -type=sound -scp=wav.scp -speed_perturb="0.9 1.0 1.1" -dataset_type=large -stage=0 -stop_stage=5 - -# feature configuration -feats_dim=80 -nj=64 - -# data -tr_dir= -dev_tst_dir= - -# exp tag -tag="exp1" - -. utils/parse_options.sh || exit 1; - -# Set bash to 'debug' mode, it will exit on : -# -e 'error', -u 'undefined variable', -o ... 'error in pipeline', -x 'print commands', -set -e -set -u -set -o pipefail - -train_set=train -valid_set=dev_ios -test_sets="dev_ios test_ios" - -asr_config=conf/train_asr_paraformer_conformer_20e_1280_320_6d_1280_320.yaml -model_dir="baseline_$(basename "${asr_config}" .yaml)_${lang}_${token_type}_${tag}" - -inference_config=conf/decode_asr_transformer_noctc_1best.yaml -inference_asr_model=valid.acc.ave_10best.pb - -# you can set gpu num for decoding here -gpuid_list=$CUDA_VISIBLE_DEVICES # set gpus for decoding, e.g., gpuid_list=2,3, the same as training stage by default -ngpu=$(echo $gpuid_list | awk -F "," '{print NF}') - -if ${gpu_inference}; then - inference_nj=$[${ngpu}*${njob}] - _ngpu=1 -else - inference_nj=$njob - _ngpu=0 -fi - -if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then - echo "stage 0: Data preparation" - # For training set - local/prepare_data.sh ${tr_dir} ${feats_dir}/data/local/train ${feats_dir}/data/train || exit 1; - # # For dev and test set - for x in iOS; do - local/prepare_data.sh ${dev_tst_dir}/${x}/dev ${feats_dir}/data/local/dev_${x,,} ${feats_dir}/data/dev_${x,,} || exit 1; - local/prepare_data.sh ${dev_tst_dir}/${x}/test ${feats_dir}/data/local/test_${x,,} ${feats_dir}/data/test_${x,,} || exit 1; - done - # Normalize text to capital letters - for x in train dev_ios test_ios; do - mv ${feats_dir}/data/${x}/text ${feats_dir}/data/${x}/text.org - paste -d " " <(cut -f 1 ${feats_dir}/data/${x}/text.org) <(cut -f 2- ${feats_dir}/data/${x}/text.org \ - | tr 'A-Z' 'a-z' | tr -d " ") \ - > ${feats_dir}/data/${x}/text - utils/text2token.py -n 1 -s 1 ${feats_dir}/data/${x}/text > ${feats_dir}/data/${x}/text.org - mv ${feats_dir}/data/${x}/text.org ${feats_dir}/data/${x}/text - done -fi - -if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then - echo "stage 1: Feature and CMVN Generation" - utils/compute_cmvn.sh --fbankdir ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config_file "$asr_config" --scale 1.0 -fi - -token_list=${feats_dir}/data/${lang}_token_list/$token_type/tokens.txt -echo "dictionary: ${token_list}" -if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then - echo "stage 2: Dictionary Preparation" - mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/ - - echo "make a dictionary" - echo "" > ${token_list} - echo "" >> ${token_list} - echo "" >> ${token_list} - utils/text2token.py -s 1 -n 1 --space "" ${feats_dir}/data/${train_set}/text | cut -f 2- -d" " | tr " " "\n" \ - | sort | uniq | grep -a -v -e '^\s*$' | awk '{print $0}' >> ${token_list} - echo "" >> ${token_list} - fi - -# LM Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then - echo "stage 3: LM Training" -fi - -# ASR Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then - echo "stage 4: ASR Training" - mkdir -p ${exp_dir}/exp/${model_dir} - mkdir -p ${exp_dir}/exp/${model_dir}/log - INIT_FILE=${exp_dir}/exp/${model_dir}/ddp_init - if [ -f $INIT_FILE ];then - rm -f $INIT_FILE - fi - init_method=file://$(readlink -f $INIT_FILE) - echo "$0: init method is $init_method" - for ((i = 0; i < $gpu_num; ++i)); do - { - rank=$i - local_rank=$i - gpu_id=$(echo $CUDA_VISIBLE_DEVICES | cut -d',' -f$[$i+1]) - train.py \ - --task_name asr \ - --gpu_id $gpu_id \ - --use_preprocessor true \ - --token_type $token_type \ - --token_list $token_list \ - --data_dir ${feats_dir}/data \ - --train_set ${train_set} \ - --valid_set ${valid_set} \ - --data_file_names "wav.scp,text" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --speed_perturb ${speed_perturb} \ - --dataset_type $dataset_type \ - --resume true \ - --output_dir ${exp_dir}/exp/${model_dir} \ - --config $asr_config \ - --ngpu $gpu_num \ - --num_worker_count $count \ - --dist_init_method $init_method \ - --dist_world_size $world_size \ - --dist_rank $rank \ - --local_rank $local_rank 1> ${exp_dir}/exp/${model_dir}/log/train.log.$i 2>&1 - } & - done - wait -fi - -# Testing Stage -if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then - echo "stage 5: Inference" - for dset in ${test_sets}; do - asr_exp=${exp_dir}/exp/${model_dir} - inference_tag="$(basename "${inference_config}" .yaml)" - _dir="${asr_exp}/${inference_tag}/${inference_asr_model}/${dset}" - _logdir="${_dir}/logdir" - if [ -d ${_dir} ]; then - echo "${_dir} is already exists. if you want to decode again, please delete this dir first." - exit 0 - fi - mkdir -p "${_logdir}" - _data="${feats_dir}/data/${dset}" - key_file=${_data}/${scp} - num_scp_file="$(<${key_file} wc -l)" - _nj=$([ $inference_nj -le $num_scp_file ] && echo "$inference_nj" || echo "$num_scp_file") - split_scps= - for n in $(seq "${_nj}"); do - split_scps+=" ${_logdir}/keys.${n}.scp" - done - # shellcheck disable=SC2086 - utils/split_scp.pl "${key_file}" ${split_scps} - _opts= - if [ -n "${inference_config}" ]; then - _opts+="--config ${inference_config} " - fi - ${infer_cmd} --gpu "${_ngpu}" --max-jobs-run "${_nj}" JOB=1:"${_nj}" "${_logdir}"/asr_inference.JOB.log \ - python -m funasr.bin.asr_inference_launch \ - --batch_size 1 \ - --ngpu "${_ngpu}" \ - --njob ${njob} \ - --gpuid_list ${gpuid_list} \ - --data_path_and_name_and_type "${_data}/${scp},speech,${type}" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --key_file "${_logdir}"/keys.JOB.scp \ - --asr_train_config "${asr_exp}"/config.yaml \ - --asr_model_file "${asr_exp}"/"${inference_asr_model}" \ - --output_dir "${_logdir}"/output.JOB \ - --mode paraformer \ - ${_opts} - - for f in token token_int score text; do - if [ -f "${_logdir}/output.1/1best_recog/${f}" ]; then - for i in $(seq "${_nj}"); do - cat "${_logdir}/output.${i}/1best_recog/${f}" - done | sort -k1 >"${_dir}/${f}" - fi - done - python utils/proce_text.py ${_dir}/text ${_dir}/text.proc - python utils/proce_text.py ${_data}/text ${_data}/text.proc - python utils/compute_wer.py ${_data}/text.proc ${_dir}/text.proc ${_dir}/text.cer - tail -n 3 ${_dir}/text.cer > ${_dir}/text.cer.txt - cat ${_dir}/text.cer.txt - done -fi - -# Prepare files for ModelScope fine-tuning and inference -if [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then - echo "stage 6: ModelScope Preparation" - cp ${feats_dir}/data/${train_set}/cmvn/am.mvn ${exp_dir}/exp/${model_dir}/am.mvn - vocab_size=$(cat ${token_list} | wc -l) - python utils/gen_modelscope_configuration.py \ - --am_model_name $inference_asr_model \ - --mode paraformer \ - --model_name paraformer \ - --dataset aishell2 \ - --output_dir $exp_dir/exp/$model_dir \ - --vocab_size $vocab_size \ - --nat _nat \ - --tag $tag -fi \ No newline at end of file diff --git a/egs/aishell2/paraformer/utils b/egs/aishell2/paraformer/utils deleted file mode 120000 index fe070dd3a..000000000 --- a/egs/aishell2/paraformer/utils +++ /dev/null @@ -1 +0,0 @@ -../../aishell/transformer/utils \ No newline at end of file diff --git a/egs/aishell2/paraformerbert/conf/decode_asr_transformer.yaml b/egs/aishell2/paraformerbert/conf/decode_asr_transformer.yaml deleted file mode 100644 index a147fa79d..000000000 --- a/egs/aishell2/paraformerbert/conf/decode_asr_transformer.yaml +++ /dev/null @@ -1,6 +0,0 @@ -beam_size: 10 -penalty: 0.0 -maxlenratio: 0.0 -minlenratio: 0.0 -ctc_weight: 0.5 -lm_weight: 0.7 diff --git a/egs/aishell2/paraformerbert/conf/train_asr_paraformerbert_conformer_20e_6d_1280_320.yaml b/egs/aishell2/paraformerbert/conf/train_asr_paraformerbert_conformer_20e_6d_1280_320.yaml deleted file mode 100644 index 8968d2d9e..000000000 --- a/egs/aishell2/paraformerbert/conf/train_asr_paraformerbert_conformer_20e_6d_1280_320.yaml +++ /dev/null @@ -1,112 +0,0 @@ -# network architecture -# encoder related -encoder: conformer -encoder_conf: - output_size: 320 # dimension of attention - attention_heads: 4 - linear_units: 1280 # the number of units of position-wise feed forward - num_blocks: 20 # the number of encoder blocks - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - attention_dropout_rate: 0.0 - input_layer: conv2d # encoder architecture type - normalize_before: true - pos_enc_layer_type: rel_pos - selfattention_layer_type: rel_selfattn - activation_type: swish - macaron_style: true - use_cnn_module: true - cnn_module_kernel: 15 - -# decoder related -decoder: paraformer_decoder_san -decoder_conf: - attention_heads: 4 - linear_units: 1280 - num_blocks: 6 - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - self_attention_dropout_rate: 0.0 - src_attention_dropout_rate: 0.0 - -# frontend related -frontend: wav_frontend -frontend_conf: - fs: 16000 - window: hamming - n_mels: 80 - frame_length: 25 - frame_shift: 10 - lfr_m: 1 - lfr_n: 1 - -# hybrid CTC/attention -model: paraformer_bert -model_conf: - ctc_weight: 0.3 - lsm_weight: 0.1 # label smoothing option - length_normalized_loss: false - predictor_weight: 1.0 - sampling_ratio: 0.4 - embeds_id: 3 - embed_dims: 768 - embeds_loss_weight: 2.0 - -# optimization related -accum_grad: 2 -grad_clip: 5 -patience: none -max_epoch: 150 -val_scheduler_criterion: - - valid - - acc -best_model_criterion: -- - valid - - acc - - max -keep_nbest_models: 10 - -optim: adam -optim_conf: - lr: 0.0005 -scheduler: warmuplr -scheduler_conf: - warmup_steps: 30000 - -specaug: specaug -specaug_conf: - apply_time_warp: true - time_warp_window: 5 - time_warp_mode: bicubic - apply_freq_mask: true - freq_mask_width_range: - - 0 - - 30 - num_freq_mask: 2 - apply_time_mask: true - time_mask_width_range: - - 0 - - 40 - num_time_mask: 2 - -predictor: cif_predictor -predictor_conf: - idim: 320 - threshold: 1.0 - l_order: 1 - r_order: 1 - -dataset_conf: - data_names: speech,text,embed - data_types: sound,text,kaldi_ark - shuffle: True - shuffle_conf: - shuffle_size: 2048 - sort_size: 500 - batch_conf: - batch_type: token - batch_size: 25000 - num_workers: 8 - -log_interval: 50 -normalize: None \ No newline at end of file diff --git a/egs/aishell2/paraformerbert/local/extract_embeds.sh b/egs/aishell2/paraformerbert/local/extract_embeds.sh deleted file mode 100755 index d7dd4f20b..000000000 --- a/egs/aishell2/paraformerbert/local/extract_embeds.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env bash - -stage=1 -stop_stage=3 - -bert_model_name="bert-base-chinese" -raw_dataset_path="../DATA" -nj=64 -model_path=${bert_model_name} - -. utils/parse_options.sh || exit 1; - -for data_set in train dev_ios;do - scp=$raw_dataset_path/data/${data_set}/text - local_scp_dir_raw=${raw_dataset_path}/data/embeds/${data_set} - local_scp_dir=$local_scp_dir_raw/split$nj - local_records_dir=$local_scp_dir_raw/ark - - mkdir -p $local_records_dir - mkdir -p $local_scp_dir - - split_scps="" - for JOB in $(seq ${nj}); do - split_scps="$split_scps $local_scp_dir/data.$JOB.text" - done - - utils/split_scp.pl $scp ${split_scps} - - - for num in {0..7};do - tmp=`expr $num \* 4` - - if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then - for idx in {1..4}; do - JOB=`expr $tmp + $idx` - echo "proces jobid=$JOB" - { - beg=0 - gpu=`expr $beg + $idx` - echo ${local_scp_dir}/log.${JOB} - python utils/extract_embeds.py $local_scp_dir/data.$JOB.text ${local_records_dir}/embeds.${JOB}.ark ${local_records_dir}/embeds.${JOB}.scp ${local_records_dir}/embeds.${JOB}.shape ${gpu} ${model_path} &> ${local_scp_dir}/log.${JOB} - } & - done - wait - fi - done - - if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then - for JOB in $(seq ${nj}); do - cat ${local_records_dir}/embeds.${JOB}.scp || exit 1; - done > ${local_scp_dir_raw}/embeds.scp - - for JOB in $(seq ${nj}); do - cat ${local_records_dir}/embeds.${JOB}.shape || exit 1; - done > ${local_scp_dir_raw}/embeds.shape - fi - - cp ${local_scp_dir_raw}/embeds.scp ${raw_dataset_path}/data/${data_set}/embeds.scp -done - -echo "embeds is in: ${local_scp_dir_raw}" -echo "success" \ No newline at end of file diff --git a/egs/aishell2/paraformerbert/local/prepare_data.sh b/egs/aishell2/paraformerbert/local/prepare_data.sh deleted file mode 100755 index 77791f9c1..000000000 --- a/egs/aishell2/paraformerbert/local/prepare_data.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env bash -# Copyright 2018 AIShell-Foundation(Authors:Jiayu DU, Xingyu NA, Bengu WU, Hao ZHENG) -# 2018 Beijing Shell Shell Tech. Co. Ltd. (Author: Hui BU) -# Apache 2.0 - -# transform raw AISHELL-2 data to kaldi format - -. ./path.sh || exit 1; - -tmp= -dir= - -if [ $# != 3 ]; then - echo "Usage: $0 " - echo " $0 /export/AISHELL-2/iOS/train data/local/train data/train" - exit 1; -fi - -corpus=$1 -tmp=$2 -dir=$3 - -echo "prepare_data.sh: Preparing data in $corpus" - -mkdir -p $tmp -mkdir -p $dir - -# corpus check -if [ ! -d $corpus ] || [ ! -f $corpus/wav.scp ] || [ ! -f $corpus/trans.txt ]; then - echo "Error: $0 requires wav.scp and trans.txt under $corpus directory." - exit 1; -fi - -# validate utt-key list, IC0803W0380 is a bad utterance -awk '{print $1}' $corpus/wav.scp | grep -v 'IC0803W0380' > $tmp/wav_utt.list -awk '{print $1}' $corpus/trans.txt > $tmp/trans_utt.list -utils/filter_scp.pl -f 1 $tmp/wav_utt.list $tmp/trans_utt.list > $tmp/utt.list - -# wav.scp -awk -F'\t' -v path_prefix=$corpus '{printf("%s\t%s/%s\n",$1,path_prefix,$2)}' $corpus/wav.scp > $tmp/tmp_wav.scp -utils/filter_scp.pl -f 1 $tmp/utt.list $tmp/tmp_wav.scp | sort -k 1 | uniq > $tmp/wav.scp - -# text -utils/filter_scp.pl -f 1 $tmp/utt.list $corpus/trans.txt | sort -k 1 | uniq > $tmp/text - -# copy prepared resources from tmp_dir to target dir -mkdir -p $dir -for f in wav.scp text; do - cp $tmp/$f $dir/$f || exit 1; -done - -echo "local/prepare_data.sh succeeded" -exit 0; diff --git a/egs/aishell2/paraformerbert/path.sh b/egs/aishell2/paraformerbert/path.sh deleted file mode 100755 index ea3c0be2f..000000000 --- a/egs/aishell2/paraformerbert/path.sh +++ /dev/null @@ -1,6 +0,0 @@ -export FUNASR_DIR=$PWD/../../.. - -# NOTE(kan-bayashi): Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C -export PYTHONIOENCODING=UTF-8 -export PYTHONPATH=../../../:$PYTHONPATH -export PATH=$FUNASR_DIR/funasr/bin:$PATH diff --git a/egs/aishell2/paraformerbert/run.sh b/egs/aishell2/paraformerbert/run.sh deleted file mode 100755 index 548c4db5e..000000000 --- a/egs/aishell2/paraformerbert/run.sh +++ /dev/null @@ -1,239 +0,0 @@ -#!/usr/bin/env bash - -. ./path.sh || exit 1; - -# machines configuration -CUDA_VISIBLE_DEVICES="0,1,2,3,4,5,6,7" -gpu_num=8 -count=1 -gpu_inference=true # Whether to perform gpu decoding, set false for cpu decoding -# for gpu decoding, inference_nj=ngpu*njob; for cpu decoding, inference_nj=njob -njob=1 -train_cmd=utils/run.pl -infer_cmd=utils/run.pl - -# general configuration -feats_dir="../DATA" #feature output dictionary -exp_dir="." -lang=zh -token_type=char -type=sound -scp=wav.scp -speed_perturb="0.9 1.0 1.1" -dataset_type=large -stage=0 -stop_stage=5 - -skip_extract_embed=false -bert_model_name="bert-base-chinese" - -# feature configuration -feats_dim=80 -nj=64 - -# data -tr_dir= -dev_tst_dir= - -# exp tag -tag="exp1" - -. utils/parse_options.sh || exit 1; - -# Set bash to 'debug' mode, it will exit on : -# -e 'error', -u 'undefined variable', -o ... 'error in pipeline', -x 'print commands', -set -e -set -u -set -o pipefail - -train_set=train -valid_set=dev_ios -test_sets="dev_ios test_ios" - -asr_config=conf/train_asr_paraformerbert_conformer_20e_6d_1280_320.yaml -model_dir="baseline_$(basename "${asr_config}" .yaml)_${lang}_${token_type}_${tag}" - -inference_config=conf/decode_asr_transformer_noctc_1best.yaml -inference_asr_model=valid.acc.ave_10best.pb - -# you can set gpu num for decoding here -gpuid_list=$CUDA_VISIBLE_DEVICES # set gpus for decoding, e.g., gpuid_list=2,3, the same as training stage by default -ngpu=$(echo $gpuid_list | awk -F "," '{print NF}') - -if ${gpu_inference}; then - inference_nj=$[${ngpu}*${njob}] - _ngpu=1 -else - inference_nj=$njob - _ngpu=0 -fi - -if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then - echo "stage 0: Data preparation" - # For training set - local/prepare_data.sh ${tr_dir} ${feats_dir}/data/local/train ${feats_dir}/data/train || exit 1; - # # For dev and test set - for x in iOS; do - local/prepare_data.sh ${dev_tst_dir}/${x}/dev ${feats_dir}/data/local/dev_${x,,} ${feats_dir}/data/dev_${x,,} || exit 1; - local/prepare_data.sh ${dev_tst_dir}/${x}/test ${feats_dir}/data/local/test_${x,,} ${feats_dir}/data/test_${x,,} || exit 1; - done - # Normalize text to capital letters - for x in train dev_ios test_ios; do - mv ${feats_dir}/data/${x}/text ${feats_dir}/data/${x}/text.org - paste -d " " <(cut -f 1 ${feats_dir}/data/${x}/text.org) <(cut -f 2- ${feats_dir}/data/${x}/text.org \ - | tr 'A-Z' 'a-z' | tr -d " ") \ - > ${feats_dir}/data/${x}/text - utils/text2token.py -n 1 -s 1 ${feats_dir}/data/${x}/text > ${feats_dir}/data/${x}/text.org - mv ${feats_dir}/data/${x}/text.org ${feats_dir}/data/${x}/text - done -fi - -if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then - echo "stage 1: Feature and CMVN Generation" - utils/compute_cmvn.sh --fbankdir ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config_file "$asr_config" --scale 1.0 -fi - -token_list=${feats_dir}/data/${lang}_token_list/$token_type/tokens.txt -echo "dictionary: ${token_list}" -if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then - echo "stage 2: Dictionary Preparation" - mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/ - - echo "make a dictionary" - echo "" > ${token_list} - echo "" >> ${token_list} - echo "" >> ${token_list} - utils/text2token.py -s 1 -n 1 --space "" ${feats_dir}/data/${train_set}/text | cut -f 2- -d" " | tr " " "\n" \ - | sort | uniq | grep -a -v -e '^\s*$' | awk '{print $0}' >> ${token_list} - echo "" >> ${token_list} - fi - -# LM Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then - echo "stage 3: LM Training" -fi - -# ASR Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then - echo "stage 4: ASR Training" - if ! "${skip_extract_embed}"; then - echo "extract embeddings..." - local/extract_embeds.sh \ - --bert_model_name ${bert_model_name} \ - --raw_dataset_path ${feats_dir} \ - --nj $nj - fi - mkdir -p ${exp_dir}/exp/${model_dir} - mkdir -p ${exp_dir}/exp/${model_dir}/log - INIT_FILE=${exp_dir}/exp/${model_dir}/ddp_init - if [ -f $INIT_FILE ];then - rm -f $INIT_FILE - fi - init_method=file://$(readlink -f $INIT_FILE) - echo "$0: init method is $init_method" - for ((i = 0; i < $gpu_num; ++i)); do - { - rank=$i - local_rank=$i - gpu_id=$(echo $CUDA_VISIBLE_DEVICES | cut -d',' -f$[$i+1]) - train.py \ - --task_name asr \ - --gpu_id $gpu_id \ - --use_preprocessor true \ - --token_type $token_type \ - --token_list $token_list \ - --data_dir ${feats_dir}/data \ - --train_set ${train_set} \ - --valid_set ${valid_set} \ - --data_file_names "wav.scp,text,embeds.scp" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --speed_perturb ${speed_perturb} \ - --dataset_type $dataset_type \ - --resume true \ - --output_dir ${exp_dir}/exp/${model_dir} \ - --config $asr_config \ - --ngpu $gpu_num \ - --num_worker_count $count \ - --dist_init_method $init_method \ - --dist_world_size $world_size \ - --dist_rank $rank \ - --local_rank $local_rank 1> ${exp_dir}/exp/${model_dir}/log/train.log.$i 2>&1 - } & - done - wait -fi - -# Testing Stage -if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then - echo "stage 5: Inference" - for dset in ${test_sets}; do - asr_exp=${exp_dir}/exp/${model_dir} - inference_tag="$(basename "${inference_config}" .yaml)" - _dir="${asr_exp}/${inference_tag}/${inference_asr_model}/${dset}" - _logdir="${_dir}/logdir" - if [ -d ${_dir} ]; then - echo "${_dir} is already exists. if you want to decode again, please delete this dir first." - exit 0 - fi - mkdir -p "${_logdir}" - _data="${feats_dir}/data/${dset}" - key_file=${_data}/${scp} - num_scp_file="$(<${key_file} wc -l)" - _nj=$([ $inference_nj -le $num_scp_file ] && echo "$inference_nj" || echo "$num_scp_file") - split_scps= - for n in $(seq "${_nj}"); do - split_scps+=" ${_logdir}/keys.${n}.scp" - done - # shellcheck disable=SC2086 - utils/split_scp.pl "${key_file}" ${split_scps} - _opts= - if [ -n "${inference_config}" ]; then - _opts+="--config ${inference_config} " - fi - ${infer_cmd} --gpu "${_ngpu}" --max-jobs-run "${_nj}" JOB=1:"${_nj}" "${_logdir}"/asr_inference.JOB.log \ - python -m funasr.bin.asr_inference_launch \ - --batch_size 1 \ - --ngpu "${_ngpu}" \ - --njob ${njob} \ - --gpuid_list ${gpuid_list} \ - --data_path_and_name_and_type "${_data}/${scp},speech,${type}" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --key_file "${_logdir}"/keys.JOB.scp \ - --asr_train_config "${asr_exp}"/config.yaml \ - --asr_model_file "${asr_exp}"/"${inference_asr_model}" \ - --output_dir "${_logdir}"/output.JOB \ - --mode paraformer \ - ${_opts} - - for f in token token_int score text; do - if [ -f "${_logdir}/output.1/1best_recog/${f}" ]; then - for i in $(seq "${_nj}"); do - cat "${_logdir}/output.${i}/1best_recog/${f}" - done | sort -k1 >"${_dir}/${f}" - fi - done - python utils/proce_text.py ${_dir}/text ${_dir}/text.proc - python utils/proce_text.py ${_data}/text ${_data}/text.proc - python utils/compute_wer.py ${_data}/text.proc ${_dir}/text.proc ${_dir}/text.cer - tail -n 3 ${_dir}/text.cer > ${_dir}/text.cer.txt - cat ${_dir}/text.cer.txt - done -fi - -# Prepare files for ModelScope fine-tuning and inference -if [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then - echo "stage 6: ModelScope Preparation" - cp ${feats_dir}/data/${train_set}/cmvn/am.mvn ${exp_dir}/exp/${model_dir}/am.mvn - vocab_size=$(cat ${token_list} | wc -l) - python utils/gen_modelscope_configuration.py \ - --am_model_name $inference_asr_model \ - --mode paraformer \ - --model_name paraformer_bert \ - --dataset aishell2 \ - --output_dir $exp_dir/exp/$model_dir \ - --vocab_size $vocab_size \ - --nat _nat \ - --tag $tag -fi \ No newline at end of file diff --git a/egs/aishell2/paraformerbert/utils b/egs/aishell2/paraformerbert/utils deleted file mode 120000 index fe070dd3a..000000000 --- a/egs/aishell2/paraformerbert/utils +++ /dev/null @@ -1 +0,0 @@ -../../aishell/transformer/utils \ No newline at end of file diff --git a/egs/aishell2/transformer/conf/decode_asr_transformer.yaml b/egs/aishell2/transformer/conf/decode_asr_transformer.yaml deleted file mode 100644 index a147fa79d..000000000 --- a/egs/aishell2/transformer/conf/decode_asr_transformer.yaml +++ /dev/null @@ -1,6 +0,0 @@ -beam_size: 10 -penalty: 0.0 -maxlenratio: 0.0 -minlenratio: 0.0 -ctc_weight: 0.5 -lm_weight: 0.7 diff --git a/egs/aishell2/transformer/conf/train_asr_transformer.yaml b/egs/aishell2/transformer/conf/train_asr_transformer.yaml deleted file mode 100644 index 1b76e2a51..000000000 --- a/egs/aishell2/transformer/conf/train_asr_transformer.yaml +++ /dev/null @@ -1,93 +0,0 @@ -# network architecture -# encoder related -encoder: transformer -encoder_conf: - output_size: 256 # dimension of attention - attention_heads: 4 - linear_units: 2048 # the number of units of position-wise feed forward - num_blocks: 12 # the number of encoder blocks - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - attention_dropout_rate: 0.0 - input_layer: conv2d # encoder architecture type - normalize_before: true - -# decoder related -decoder: transformer -decoder_conf: - attention_heads: 4 - linear_units: 2048 - num_blocks: 6 - dropout_rate: 0.1 - positional_dropout_rate: 0.1 - self_attention_dropout_rate: 0.0 - src_attention_dropout_rate: 0.0 - -# frontend related -frontend: wav_frontend -frontend_conf: - fs: 16000 - window: hamming - n_mels: 80 - frame_length: 25 - frame_shift: 10 - lfr_m: 1 - lfr_n: 1 - -# hybrid CTC/attention -model_conf: - ctc_weight: 0.3 - lsm_weight: 0.1 # label smoothing option - length_normalized_loss: false - -# optimization related -accum_grad: 2 -grad_clip: 5 -patience: none -max_epoch: 150 -val_scheduler_criterion: - - valid - - acc -best_model_criterion: -- - valid - - acc - - max -keep_nbest_models: 10 - -optim: adam -optim_conf: - lr: 0.002 -scheduler: warmuplr # pytorch v1.1.0+ required -scheduler_conf: - warmup_steps: 25000 - -specaug: specaug -specaug_conf: - apply_time_warp: true - time_warp_window: 5 - time_warp_mode: bicubic - apply_freq_mask: true - freq_mask_width_range: - - 0 - - 30 - num_freq_mask: 2 - apply_time_mask: true - time_mask_width_range: - - 0 - - 40 - num_time_mask: 2 - -dataset_conf: - data_names: speech,text - data_types: sound,text - shuffle: True - shuffle_conf: - shuffle_size: 2048 - sort_size: 500 - batch_conf: - batch_type: token - batch_size: 25000 - num_workers: 8 - -log_interval: 50 -normalize: None \ No newline at end of file diff --git a/egs/aishell2/transformer/local/prepare_data.sh b/egs/aishell2/transformer/local/prepare_data.sh deleted file mode 100755 index 77791f9c1..000000000 --- a/egs/aishell2/transformer/local/prepare_data.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env bash -# Copyright 2018 AIShell-Foundation(Authors:Jiayu DU, Xingyu NA, Bengu WU, Hao ZHENG) -# 2018 Beijing Shell Shell Tech. Co. Ltd. (Author: Hui BU) -# Apache 2.0 - -# transform raw AISHELL-2 data to kaldi format - -. ./path.sh || exit 1; - -tmp= -dir= - -if [ $# != 3 ]; then - echo "Usage: $0 " - echo " $0 /export/AISHELL-2/iOS/train data/local/train data/train" - exit 1; -fi - -corpus=$1 -tmp=$2 -dir=$3 - -echo "prepare_data.sh: Preparing data in $corpus" - -mkdir -p $tmp -mkdir -p $dir - -# corpus check -if [ ! -d $corpus ] || [ ! -f $corpus/wav.scp ] || [ ! -f $corpus/trans.txt ]; then - echo "Error: $0 requires wav.scp and trans.txt under $corpus directory." - exit 1; -fi - -# validate utt-key list, IC0803W0380 is a bad utterance -awk '{print $1}' $corpus/wav.scp | grep -v 'IC0803W0380' > $tmp/wav_utt.list -awk '{print $1}' $corpus/trans.txt > $tmp/trans_utt.list -utils/filter_scp.pl -f 1 $tmp/wav_utt.list $tmp/trans_utt.list > $tmp/utt.list - -# wav.scp -awk -F'\t' -v path_prefix=$corpus '{printf("%s\t%s/%s\n",$1,path_prefix,$2)}' $corpus/wav.scp > $tmp/tmp_wav.scp -utils/filter_scp.pl -f 1 $tmp/utt.list $tmp/tmp_wav.scp | sort -k 1 | uniq > $tmp/wav.scp - -# text -utils/filter_scp.pl -f 1 $tmp/utt.list $corpus/trans.txt | sort -k 1 | uniq > $tmp/text - -# copy prepared resources from tmp_dir to target dir -mkdir -p $dir -for f in wav.scp text; do - cp $tmp/$f $dir/$f || exit 1; -done - -echo "local/prepare_data.sh succeeded" -exit 0; diff --git a/egs/aishell2/transformer/path.sh b/egs/aishell2/transformer/path.sh deleted file mode 100755 index ea3c0be2f..000000000 --- a/egs/aishell2/transformer/path.sh +++ /dev/null @@ -1,6 +0,0 @@ -export FUNASR_DIR=$PWD/../../.. - -# NOTE(kan-bayashi): Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C -export PYTHONIOENCODING=UTF-8 -export PYTHONPATH=../../../:$PYTHONPATH -export PATH=$FUNASR_DIR/funasr/bin:$PATH diff --git a/egs/aishell2/transformer/run.sh b/egs/aishell2/transformer/run.sh deleted file mode 100755 index 22c3342f5..000000000 --- a/egs/aishell2/transformer/run.sh +++ /dev/null @@ -1,229 +0,0 @@ -#!/usr/bin/env bash - -. ./path.sh || exit 1; - -# machines configuration -CUDA_VISIBLE_DEVICES="0,1,2,3,4,5,6,7" -gpu_num=8 -count=1 -gpu_inference=true # Whether to perform gpu decoding, set false for cpu decoding -# for gpu decoding, inference_nj=ngpu*njob; for cpu decoding, inference_nj=njob -njob=5 -train_cmd=utils/run.pl -infer_cmd=utils/run.pl - -# general configuration -feats_dir="../DATA" #feature output dictionary -exp_dir="." -lang=zh -token_type=char -type=sound -scp=wav.scp -speed_perturb="0.9 1.0 1.1" -dataset_type=large -stage=0 -stop_stage=5 - -# feature configuration -feats_dim=80 -nj=64 - -# data -tr_dir= -dev_tst_dir= - -# exp tag -tag="exp1" - -. utils/parse_options.sh || exit 1; - -# Set bash to 'debug' mode, it will exit on : -# -e 'error', -u 'undefined variable', -o ... 'error in pipeline', -x 'print commands', -set -e -set -u -set -o pipefail - -train_set=train -valid_set=dev_ios -test_sets="dev_ios test_ios" - -asr_config=conf/train_asr_transformer.yaml -model_dir="baseline_$(basename "${asr_config}" .yaml)_${lang}_${token_type}_${tag}" - -inference_config=conf/decode_asr_transformer.yaml -inference_asr_model=valid.acc.ave_10best.pb - -# you can set gpu num for decoding here -gpuid_list=$CUDA_VISIBLE_DEVICES # set gpus for decoding, the same as training stage by default -ngpu=$(echo $gpuid_list | awk -F "," '{print NF}') - -if ${gpu_inference}; then - inference_nj=$[${ngpu}*${njob}] - _ngpu=1 -else - inference_nj=$njob - _ngpu=0 -fi - -if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then - echo "stage 0: Data preparation" - # For training set - local/prepare_data.sh ${tr_dir} ${feats_dir}/data/local/train ${feats_dir}/data/train || exit 1; - # # For dev and test set - for x in iOS; do - local/prepare_data.sh ${dev_tst_dir}/${x}/dev ${feats_dir}/data/local/dev_${x,,} ${feats_dir}/data/dev_${x,,} || exit 1; - local/prepare_data.sh ${dev_tst_dir}/${x}/test ${feats_dir}/data/local/test_${x,,} ${feats_dir}/data/test_${x,,} || exit 1; - done - # Normalize text to capital letters - for x in train dev_ios test_ios; do - mv ${feats_dir}/data/${x}/text ${feats_dir}/data/${x}/text.org - paste -d " " <(cut -f 1 ${feats_dir}/data/${x}/text.org) <(cut -f 2- ${feats_dir}/data/${x}/text.org \ - | tr 'A-Z' 'a-z' | tr -d " ") \ - > ${feats_dir}/data/${x}/text - utils/text2token.py -n 1 -s 1 ${feats_dir}/data/${x}/text > ${feats_dir}/data/${x}/text.org - mv ${feats_dir}/data/${x}/text.org ${feats_dir}/data/${x}/text - done -fi - -if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then - echo "stage 1: Feature and CMVN Generation" - utils/compute_cmvn.sh --fbankdir ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config_file "$asr_config" --scale 1.0 -fi - -token_list=${feats_dir}/data/${lang}_token_list/$token_type/tokens.txt -echo "dictionary: ${token_list}" -if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then - echo "stage 2: Dictionary Preparation" - mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/ - - echo "make a dictionary" - echo "" > ${token_list} - echo "" >> ${token_list} - echo "" >> ${token_list} - utils/text2token.py -s 1 -n 1 --space "" ${feats_dir}/data/${train_set}/text | cut -f 2- -d" " | tr " " "\n" \ - | sort | uniq | grep -a -v -e '^\s*$' | awk '{print $0}' >> ${token_list} - echo "" >> ${token_list} - fi - -# LM Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then - echo "stage 3: LM Training" -fi - -# ASR Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then - echo "stage 4: ASR Training" - mkdir -p ${exp_dir}/exp/${model_dir} - mkdir -p ${exp_dir}/exp/${model_dir}/log - INIT_FILE=${exp_dir}/exp/${model_dir}/ddp_init - if [ -f $INIT_FILE ];then - rm -f $INIT_FILE - fi - init_method=file://$(readlink -f $INIT_FILE) - echo "$0: init method is $init_method" - for ((i = 0; i < $gpu_num; ++i)); do - { - rank=$i - local_rank=$i - gpu_id=$(echo $CUDA_VISIBLE_DEVICES | cut -d',' -f$[$i+1]) - train.py \ - --task_name asr \ - --gpu_id $gpu_id \ - --use_preprocessor true \ - --token_type $token_type \ - --token_list $token_list \ - --data_dir ${feats_dir}/data \ - --train_set ${train_set} \ - --valid_set ${valid_set} \ - --data_file_names "wav.scp,text" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --speed_perturb ${speed_perturb} \ - --dataset_type $dataset_type \ - --resume true \ - --output_dir ${exp_dir}/exp/${model_dir} \ - --config $asr_config \ - --ngpu $gpu_num \ - --num_worker_count $count \ - --dist_init_method $init_method \ - --dist_world_size $world_size \ - --dist_rank $rank \ - --local_rank $local_rank 1> ${exp_dir}/exp/${model_dir}/log/train.log.$i 2>&1 - } & - done - wait -fi - -# Testing Stage -if [ ${stage} -le 5 ] && [ ${stop_stage} -ge 5 ]; then - echo "stage 5 Inference" - for dset in ${test_sets}; do - asr_exp=${exp_dir}/exp/${model_dir} - inference_tag="$(basename "${inference_config}" .yaml)" - _dir="${asr_exp}/${inference_tag}/${inference_asr_model}/${dset}" - _logdir="${_dir}/logdir" - if [ -d ${_dir} ]; then - echo "${_dir} is already exists. if you want to decode again, please delete this dir first." - exit 0 - fi - mkdir -p "${_logdir}" - _data="${feats_dir}/data/${dset}" - key_file=${_data}/${scp} - num_scp_file="$(<${key_file} wc -l)" - _nj=$([ $inference_nj -le $num_scp_file ] && echo "$inference_nj" || echo "$num_scp_file") - split_scps= - for n in $(seq "${_nj}"); do - split_scps+=" ${_logdir}/keys.${n}.scp" - done - # shellcheck disable=SC2086 - utils/split_scp.pl "${key_file}" ${split_scps} - _opts= - if [ -n "${inference_config}" ]; then - _opts+="--config ${inference_config} " - fi - ${infer_cmd} --gpu "${_ngpu}" --max-jobs-run "${_nj}" JOB=1:"${_nj}" "${_logdir}"/asr_inference.JOB.log \ - python -m funasr.bin.asr_inference_launch \ - --batch_size 1 \ - --ngpu "${_ngpu}" \ - --njob ${njob} \ - --gpuid_list ${gpuid_list} \ - --data_path_and_name_and_type "${_data}/${scp},speech,${type}" \ - --cmvn_file ${feats_dir}/data/${train_set}/cmvn/am.mvn \ - --key_file "${_logdir}"/keys.JOB.scp \ - --asr_train_config "${asr_exp}"/config.yaml \ - --asr_model_file "${asr_exp}"/"${inference_asr_model}" \ - --output_dir "${_logdir}"/output.JOB \ - --mode asr \ - ${_opts} - - for f in token token_int score text; do - if [ -f "${_logdir}/output.1/1best_recog/${f}" ]; then - for i in $(seq "${_nj}"); do - cat "${_logdir}/output.${i}/1best_recog/${f}" - done | sort -k1 >"${_dir}/${f}" - fi - done - python utils/proce_text.py ${_dir}/text ${_dir}/text.proc - python utils/proce_text.py ${_data}/text ${_data}/text.proc - python utils/compute_wer.py ${_data}/text.proc ${_dir}/text.proc ${_dir}/text.cer - tail -n 3 ${_dir}/text.cer > ${_dir}/text.cer.txt - cat ${_dir}/text.cer.txt - done -fi - -# Prepare files for ModelScope fine-tuning and inference -if [ ${stage} -le 6 ] && [ ${stop_stage} -ge 6 ]; then - echo "stage 6: ModelScope Preparation" - cp ${feats_dir}/data/${train_set}/cmvn/am.mvn ${exp_dir}/exp/${model_dir}/am.mvn - vocab_size=$(cat ${token_list} | wc -l) - python utils/gen_modelscope_configuration.py \ - --am_model_name $inference_asr_model \ - --mode asr \ - --model_name transformer \ - --dataset aishell2 \ - --output_dir $exp_dir/exp/$model_dir \ - --vocab_size $vocab_size \ - --tag $tag -fi - diff --git a/egs/aishell2/transformer/utils b/egs/aishell2/transformer/utils deleted file mode 120000 index fe070dd3a..000000000 --- a/egs/aishell2/transformer/utils +++ /dev/null @@ -1 +0,0 @@ -../../aishell/transformer/utils \ No newline at end of file diff --git a/egs/aishell2/transformerLM/conf/train_lm_transformer.yaml b/egs/aishell2/transformerLM/conf/train_lm_transformer.yaml deleted file mode 100644 index 4155a79ae..000000000 --- a/egs/aishell2/transformerLM/conf/train_lm_transformer.yaml +++ /dev/null @@ -1,31 +0,0 @@ -lm: transformer -lm_conf: - pos_enc: null - embed_unit: 128 - att_unit: 512 - head: 8 - unit: 2048 - layer: 16 - dropout_rate: 0.1 - -# optimization related -grad_clip: 5.0 -batch_type: numel -batch_bins: 6000000 -accum_grad: 1 -max_epoch: 15 # 15epoch is enough - -optim: adam -optim_conf: - lr: 0.001 -scheduler: warmuplr -scheduler_conf: - warmup_steps: 25000 - -best_model_criterion: -- - valid - - loss - - min -keep_nbest_models: 10 # 10 is good. - -log_interval: 50 diff --git a/egs/aishell2/transformerLM/path.sh b/egs/aishell2/transformerLM/path.sh deleted file mode 100755 index ea3c0be2f..000000000 --- a/egs/aishell2/transformerLM/path.sh +++ /dev/null @@ -1,6 +0,0 @@ -export FUNASR_DIR=$PWD/../../.. - -# NOTE(kan-bayashi): Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C -export PYTHONIOENCODING=UTF-8 -export PYTHONPATH=../../../:$PYTHONPATH -export PATH=$FUNASR_DIR/funasr/bin:$PATH diff --git a/egs/aishell2/transformerLM/run.sh b/egs/aishell2/transformerLM/run.sh deleted file mode 100755 index b04c64396..000000000 --- a/egs/aishell2/transformerLM/run.sh +++ /dev/null @@ -1,228 +0,0 @@ -#!/usr/bin/env bash - -. ./path.sh || exit 1; - -# machines configuration -CUDA_VISIBLE_DEVICES="0,1" -gpu_num=2 -count=1 -train_cmd=utils/run.pl -infer_cmd=utils/run.pl - -# general configuration -lang=zh -nlsyms_txt=none # Non-linguistic symbol list if existing. -cleaner=none # Text cleaner. -g2p=none # g2p method (needed if token_type=phn). -lm_fold_length=150 # fold_length for LM training. -word_vocab_size=10000 # Size of word vocabulary. -token_type=char -lm_token_list= - -nj=10 -## path to AISHELL2 trans -lm_train_text= -lm_dev_text= -lm_test_text= - -train_data_path_and_name_and_type=${lm_train_text},text,text -train_shape_file= -valid_data_path_and_name_and_type=${lm_dev_text},text,text -valid_shape_file= -lm_config=conf/train_lm_transformer.yaml -exp_dir=./data -tag=exp1 -model_dir="baseline_$(basename "${lm_config}" .yaml)_${lang}_${token_type}_${tag}" -lm_exp=${exp_dir}/exp/${model_dir} -inference_lm=valid.loss.ave.pb # Language model path for decoding. - -stage=0 -stop_stage=3 - -. utils/parse_options.sh || exit 1; - -# Set bash to 'debug' mode, it will exit on : -# -e 'error', -u 'undefined variable', -o ... 'error in pipeline', -x 'print commands', -set -e -set -u -set -o pipefail - -min() { - local a b - a=$1 - for b in "$@"; do - if [ "${b}" -le "${a}" ]; then - a="${b}" - fi - done - echo "${a}" -} - -# you can set gpu num for decoding here -gpuid_list=$CUDA_VISIBLE_DEVICES # set gpus for decoding, e.g., gpuid_list=2,3, the same as training stage by default -ngpu=$(echo $gpuid_list | awk -F "," '{print NF}') - -mkdir -p ${exp_dir}/exp/${model_dir} -token_list=${exp_dir}/exp/${model_dir}/vocab.txt -blank="" # CTC blank symbole -sos="" # sos symbole -eos="" # eos symbole -oov="" # Out of vocabulary symbol. -if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then - if [ "${token_type}" = char ] || [ "${token_type}" = word ]; then - echo "Stage 0: Generate character level token_list from ${lm_train_text}" - - # The first symbol in token_list must be "": - # 0 is reserved for CTC-blank for ASR and also used as ignore-index in the other task - python -m funasr.bin.tokenize_text \ - --token_type "${token_type}" \ - --input "${lm_train_text}" \ - --output "${token_list}" \ - --non_linguistic_symbols "${nlsyms_txt}" \ - --field 2- \ - --cleaner "${cleaner}" \ - --g2p "${g2p}" \ - --write_vocabulary true \ - --add_symbol "${blank}:0" \ - --add_symbol "${sos}:1" \ - --add_symbol "${eos}:2" \ - --add_symbol "${oov}:-1" - - else - echo "Error: not supported --token_type '${token_type}'" - exit 2 - fi - - lm_token_list="${token_list}" - -fi - - -if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then - echo "stage 1: Data preparation" - - # 1. Split the key file - _logdir="${exp_dir}/exp/${model_dir}/log" - mkdir -p "${_logdir}" - # Get the minimum number among ${nj} and the number lines of input files - _nj=$(min "${nj}" "$(<${lm_train_text} wc -l)" "$(<${lm_dev_text} wc -l)") - - key_file="${lm_train_text}" - split_scps="" - for n in $(seq ${_nj}); do - split_scps+=" ${_logdir}/train.${n}.scp" - done - # shellcheck disable=SC2086 - utils/split_scp.pl "${key_file}" ${split_scps} - - key_file="${lm_dev_text}" - split_scps="" - for n in $(seq ${_nj}); do - split_scps+=" ${_logdir}/dev.${n}.scp" - done - # shellcheck disable=SC2086 - utils/split_scp.pl "${key_file}" ${split_scps} - - # 2. Submit jobs - ## python ../../funasr/bin/lm_train.py \ - ${train_cmd} JOB=1:"${_nj}" "${_logdir}"/stats.JOB.log \ - python -m funasr.bin.lm_train \ - --collect_stats true \ - --use_preprocessor true \ - --token_type "${token_type}" \ - --token_list "${lm_token_list}" \ - --non_linguistic_symbols "${nlsyms_txt}" \ - --cleaner "${cleaner}" \ - --g2p "${g2p}" \ - --train_data_path_and_name_and_type "${lm_train_text},text,text" \ - --valid_data_path_and_name_and_type "${lm_dev_text},text,text" \ - --train_shape_file "${_logdir}/train.JOB.scp" \ - --valid_shape_file "${_logdir}/dev.JOB.scp" \ - --output_dir "${_logdir}/stats.JOB" \ - --config ${lm_config} || { cat "${_logdir}"/stats.*.log; exit 1; } - - # 3. Aggregate shape files - _opts= - for i in $(seq "${_nj}"); do - _opts+="--input_dir ${_logdir}/stats.${i} " - done - lm_stats_dir=${exp_dir}/exp/${model_dir} - # shellcheck disable=SC2086 - python -m funasr.bin.aggregate_stats_dirs ${_opts} --output_dir "${lm_stats_dir}" - - # Append the num-tokens at the last dimensions. This is used for batch-bins count - <"${lm_stats_dir}/train/text_shape" \ - awk -v N="$(<${lm_token_list} wc -l)" '{ print $0 "," N }' \ - >"${lm_stats_dir}/train/text_shape.${token_type}" - - <"${lm_stats_dir}/valid/text_shape" \ - awk -v N="$(<${lm_token_list} wc -l)" '{ print $0 "," N }' \ - >"${lm_stats_dir}/valid/text_shape.${token_type}" - - train_shape_file=${lm_stats_dir}/train/text_shape.${token_type} - valid_shape_file=${lm_stats_dir}/valid/text_shape.${token_type} - -fi - -# Training Stage -world_size=$gpu_num # run on one machine -if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then - echo "stage 2: Training" - mkdir -p ${lm_exp} - mkdir -p ${lm_exp}/log - INIT_FILE=${lm_exp}/ddp_init - if [ -f $INIT_FILE ];then - rm -f $INIT_FILE - fi - init_method=file://$(readlink -f $INIT_FILE) - echo "$0: init method is $init_method" - for ((i = 0; i < $gpu_num; ++i)); do - { - rank=$i - local_rank=$i - gpu_id=$(echo $CUDA_VISIBLE_DEVICES | cut -d',' -f$[$i+1]) - python ../../../funasr/bin/lm_train.py \ - --gpu_id ${gpu_id} \ - --use_preprocessor true \ - --token_type "${token_type}" \ - --token_list "${lm_token_list}" \ - --non_linguistic_symbols "${nlsyms_txt}" \ - --cleaner "${cleaner}" \ - --train_data_path_and_name_and_type "${train_data_path_and_name_and_type}" \ - --train_shape_file "${train_shape_file}" \ - --valid_data_path_and_name_and_type "${valid_data_path_and_name_and_type}" \ - --valid_shape_file "${valid_shape_file}" \ - --fold_length "${lm_fold_length}" \ - --resume true \ - --output_dir "${lm_exp}" \ - --config ${lm_config} \ - --ngpu ${gpu_num} \ - --num_worker_count ${count} \ - --multiprocessing_distributed true \ - --dist_init_method ${init_method} \ - --dist_world_size ${world_size} \ - --dist_rank ${rank} \ - --local_rank ${local_rank} 1> ${exp_dir}/exp/${model_dir}/log/train.log.$i 2>&1 - } & - done - wait -fi - -# Testing Stage -gpu_num=1 -if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then - echo "Stage 3: Calc perplexity: ${lm_test_text}" - - python ../../../funasr/bin/lm_inference_launch.py \ - --output_dir "${lm_exp}/perplexity_test/output.1" \ - --ngpu "${gpu_num}" \ - --batch_size 1 \ - --train_config "${lm_exp}"/config.yaml \ - --model_file "${lm_exp}/${inference_lm}" \ - --data_path_and_name_and_type "${lm_test_text},text,text" \ - --num_workers 1 \ - --gpuid_list 0 \ - --mode "transformer" \ - --split_with_space false -fi - diff --git a/egs/aishell2/transformerLM/utils b/egs/aishell2/transformerLM/utils deleted file mode 120000 index fe070dd3a..000000000 --- a/egs/aishell2/transformerLM/utils +++ /dev/null @@ -1 +0,0 @@ -../../aishell/transformer/utils \ No newline at end of file diff --git a/egs/alimeeting/diarization/sond/README.md b/egs/alimeeting/diarization/sond/README.md deleted file mode 100644 index b36210c6d..000000000 --- a/egs/alimeeting/diarization/sond/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Get Started -To use this example, please execute the first stage of run.sh first to obtain the prepared data and pre-trained models: -```shell -sh run.sh --stage 0 --stop_stage 0 -``` -Then, you can execute unit_test.py to check the correctness of code: -```shell -python unit_test.py -# you will get the results: -[{'key': 'R8002_M8002_MS802-S0000_0000000_0001600', 'value': 'spk1 [(0.0, 8.88), (10.72, 11.92), (12.64, 15.2)]\nspk2 [(8.8, 9.76)]\nspk3 [(9.6, 10.96), (15.12, 15.68)]\nspk4 [(11.12, 12.72)]'}] -[{'key': 'R8002_M8002_MS802-S0000_0000000_0001600', 'value': 'spk1 [(0.0, 8.88), (10.72, 11.92), (12.64, 15.2)]\nspk2 [(8.8, 9.76)]\nspk3 [(9.6, 10.96), (15.12, 15.68)]\nspk4 [(11.12, 12.72)]'}] -[{'key': 'R8002_M8002_MS802-S0000_0000000_0001600', 'value': 'spk1 [(0.0, 8.88), (10.72, 11.92), (12.64, 15.2)]\nspk2 [(8.8, 9.76)]\nspk3 [(9.6, 10.88), (15.12, 15.68)]\nspk4 [(11.12, 12.72)]'}] -[{'key': 'test0', 'value': 'spk1 [(0.0, 8.88), (10.64, 15.2)]\nspk2 [(8.88, 9.84)]\nspk3 [(9.6, 11.04), (15.12, 15.68)]\nspk4 [(11.2, 11.76)]'}] -``` -You can also execute run.sh to reproduce the diarization performance reported in [1] -```shell -sh run.sh --stage 1 --stop_stage 2 -``` - -# Results -After executing "run.sh", you will get a DER about 4.21%, which is reported in [1], Table 6, line "SOND Oracle Profile". - -# Reference -[1] Speaker Overlap-aware Neural Diarization for Multi-party Meeting Analysis, Zhihao Du, Shiliang Zhang, -Siqi Zheng, Zhijie Yan. EMNLP 2022. \ No newline at end of file diff --git a/egs/alimeeting/diarization/sond/config.yaml b/egs/alimeeting/diarization/sond/config.yaml deleted file mode 100644 index 072c171c3..000000000 --- a/egs/alimeeting/diarization/sond/config.yaml +++ /dev/null @@ -1,2740 +0,0 @@ -config: finetune.yaml -print_config: false -log_level: INFO -dry_run: false -iterator_type: sequence -output_dir: exp/sond -ngpu: 1 -seed: 0 -num_workers: 16 -num_att_plot: 0 -dist_backend: nccl -dist_init_method: env:// -dist_world_size: null -dist_rank: null -local_rank: 0 -dist_master_addr: null -dist_master_port: null -dist_launcher: null -multiprocessing_distributed: true -distributed: false -unused_parameters: true -sharded_ddp: false -ddp_backend: pytorch_ddp -cudnn_enabled: true -cudnn_benchmark: false -cudnn_deterministic: true -collect_stats: false -write_collected_feats: false -max_epoch: 50 -patience: null -val_scheduler_criterion: -- valid -- acc -early_stopping_criterion: -- valid -- loss -- min -best_model_criterion: -- - valid - - acc - - max -keep_nbest_models: 10 -nbest_averaging_interval: 0 -grad_clip: 5 -grad_clip_type: 2.0 -grad_noise: false -accum_grad: 1 -no_forward_run: false -resume: true -train_dtype: float32 -use_amp: false -log_interval: 50 -use_matplotlib: false -use_tensorboard: true -use_wandb: false -wandb_project: null -wandb_id: null -wandb_entity: null -wandb_name: null -wandb_model_log_interval: -1 -use_pai: true -detect_anomaly: false -pretrain_path: null -init_param: [] -ignore_init_mismatch: false -freeze_param: [] -num_iters_per_epoch: null -batch_size: 20 -valid_batch_size: null -batch_bins: 10000 -valid_batch_bins: null -train_shape_file: -- /data/volume1/youyan/aishell/ark/train/speech_shape.1 -- /data/volume1/youyan/aishell/ark/train/text_shape.1 -valid_shape_file: -- /data/volume1/youyan/aishell/ark/dev/speech_shape.1 -- /data/volume1/youyan/aishell/ark/dev/text_shape.1 -batch_type: length -valid_batch_type: null -fold_length: -- 512 -- 150 -sort_in_batch: descending -sort_batch: descending -multiple_iterator: false -chunk_length: 500 -chunk_shift_ratio: 0.5 -num_cache_chunks: 1024 -train_data_path_and_name_and_type: -- - /data/volume1/youyan/aishell/ark/train/data.scp - - speech - - kaldi_ark -- - /data/volume1/youyan/aishell/ark/train/data.text.1 - - text - - text -valid_data_path_and_name_and_type: -- - /data/volume1/youyan/aishell/ark/dev/data.scp - - speech - - kaldi_ark -- - /data/volume1/youyan/aishell/ark/dev/data.text.1 - - text - - text -allow_variable_data_keys: false -max_cache_size: 0.0 -max_cache_fd: 32 -valid_max_cache_size: null -optim: adam -optim_conf: - lr: 0.0005 -scheduler: warmuplr -scheduler_conf: - warmup_steps: 30000 -token_list: -- '0' -- '1' -- '2' -- '3' -- '4' -- '5' -- '6' -- '7' -- '8' -- '9' -- '10' -- '11' -- '12' -- '13' -- '14' -- '15' -- '16' -- '17' -- '18' -- '19' -- '20' -- '21' -- '22' -- '23' -- '24' -- '25' -- '26' -- '27' -- '28' -- '29' -- '30' -- '32' -- '33' -- '34' -- '35' -- '36' -- '37' -- '38' -- '39' -- '40' -- '41' -- '42' -- '43' -- '44' -- '45' -- '46' -- '48' -- '49' -- '50' -- '51' -- '52' -- '53' -- '54' -- '56' -- '57' -- '58' -- '60' -- '64' -- '65' -- '66' -- '67' -- '68' -- '69' -- '70' -- '71' -- '72' -- '73' -- '74' -- '75' -- '76' -- '77' -- '78' -- '80' -- '81' -- '82' -- '83' -- '84' -- '85' -- '86' -- '88' -- '89' -- '90' -- '92' -- '96' -- '97' -- '98' -- '99' -- '100' -- '101' -- '102' -- '104' -- '105' -- '106' -- '108' -- '112' -- '113' -- '114' -- '116' -- '120' -- '128' -- '129' -- '130' -- '131' -- '132' -- '133' -- '134' -- '135' -- '136' -- '137' -- '138' -- '139' -- '140' -- '141' -- '142' -- '144' -- '145' -- '146' -- '147' -- '148' -- '149' -- '150' -- '152' -- '153' -- '154' -- '156' -- '160' -- '161' -- '162' -- '163' -- '164' -- '165' -- '166' -- '168' -- '169' -- '170' -- '172' -- '176' -- '177' -- '178' -- '180' -- '184' -- '192' -- '193' -- '194' -- '195' -- '196' -- '197' -- '198' -- '200' -- '201' -- '202' -- '204' -- '208' -- '209' -- '210' -- '212' -- '216' -- '224' -- '225' -- '226' -- '228' -- '232' -- '240' -- '256' -- '257' -- '258' -- '259' -- '260' -- '261' -- '262' -- '263' -- '264' -- '265' -- '266' -- '267' -- '268' -- '269' -- '270' -- '272' -- '273' -- '274' -- '275' -- '276' -- '277' -- '278' -- '280' -- '281' -- '282' -- '284' -- '288' -- '289' -- '290' -- '291' -- '292' -- '293' -- '294' -- '296' -- '297' -- '298' -- '300' -- '304' -- '305' -- '306' -- '308' -- '312' -- '320' -- '321' -- '322' -- '323' -- '324' -- '325' -- '326' -- '328' -- '329' -- '330' -- '332' -- '336' -- '337' -- '338' -- '340' -- '344' -- '352' -- '353' -- '354' -- '356' -- '360' -- '368' -- '384' -- '385' -- '386' -- '387' -- '388' -- '389' -- '390' -- '392' -- '393' -- '394' -- '396' -- '400' -- '401' -- '402' -- '404' -- '408' -- '416' -- '417' -- '418' -- '420' -- '424' -- '432' -- '448' -- '449' -- '450' -- '452' -- '456' -- '464' -- '480' -- '512' -- '513' -- '514' -- '515' -- '516' -- '517' -- '518' -- '519' -- '520' -- '521' -- '522' -- '523' -- '524' -- '525' -- '526' -- '528' -- '529' -- '530' -- '531' -- '532' -- '533' -- '534' -- '536' -- '537' -- '538' -- '540' -- '544' -- '545' -- '546' -- '547' -- '548' -- '549' -- '550' -- '552' -- '553' -- '554' -- '556' -- '560' -- '561' -- '562' -- '564' -- '568' -- '576' -- '577' -- '578' -- '579' -- '580' -- '581' -- '582' -- '584' -- '585' -- '586' -- '588' -- '592' -- '593' -- '594' -- '596' -- '600' -- '608' -- '609' -- '610' -- '612' -- '616' -- '624' -- '640' -- '641' -- '642' -- '643' -- '644' -- '645' -- '646' -- '648' -- '649' -- '650' -- '652' -- '656' -- '657' -- '658' -- '660' -- '664' -- '672' -- '673' -- '674' -- '676' -- '680' -- '688' -- '704' -- '705' -- '706' -- '708' -- '712' -- '720' -- '736' -- '768' -- '769' -- '770' -- '771' -- '772' -- '773' -- '774' -- '776' -- '777' -- '778' -- '780' -- '784' -- '785' -- '786' -- '788' -- '792' -- '800' -- '801' -- '802' -- '804' -- '808' -- '816' -- '832' -- '833' -- '834' -- '836' -- '840' -- '848' -- '864' -- '896' -- '897' -- '898' -- '900' -- '904' -- '912' -- '928' -- '960' -- '1024' -- '1025' -- '1026' -- '1027' -- '1028' -- '1029' -- '1030' -- '1031' -- '1032' -- '1033' -- '1034' -- '1035' -- '1036' -- '1037' -- '1038' -- '1040' -- '1041' -- '1042' -- '1043' -- '1044' -- '1045' -- '1046' -- '1048' -- '1049' -- '1050' -- '1052' -- '1056' -- '1057' -- '1058' -- '1059' -- '1060' -- '1061' -- '1062' -- '1064' -- '1065' -- '1066' -- '1068' -- '1072' -- '1073' -- '1074' -- '1076' -- '1080' -- '1088' -- '1089' -- '1090' -- '1091' -- '1092' -- '1093' -- '1094' -- '1096' -- '1097' -- '1098' -- '1100' -- '1104' -- '1105' -- '1106' -- '1108' -- '1112' -- '1120' -- '1121' -- '1122' -- '1124' -- '1128' -- '1136' -- '1152' -- '1153' -- '1154' -- '1155' -- '1156' -- '1157' -- '1158' -- '1160' -- '1161' -- '1162' -- '1164' -- '1168' -- '1169' -- '1170' -- '1172' -- '1176' -- '1184' -- '1185' -- '1186' -- '1188' -- '1192' -- '1200' -- '1216' -- '1217' -- '1218' -- '1220' -- '1224' -- '1232' -- '1248' -- '1280' -- '1281' -- '1282' -- '1283' -- '1284' -- '1285' -- '1286' -- '1288' -- '1289' -- '1290' -- '1292' -- '1296' -- '1297' -- '1298' -- '1300' -- '1304' -- '1312' -- '1313' -- '1314' -- '1316' -- '1320' -- '1328' -- '1344' -- '1345' -- '1346' -- '1348' -- '1352' -- '1360' -- '1376' -- '1408' -- '1409' -- '1410' -- '1412' -- '1416' -- '1424' -- '1440' -- '1472' -- '1536' -- '1537' -- '1538' -- '1539' -- '1540' -- '1541' -- '1542' -- '1544' -- '1545' -- '1546' -- '1548' -- '1552' -- '1553' -- '1554' -- '1556' -- '1560' -- '1568' -- '1569' -- '1570' -- '1572' -- '1576' -- '1584' -- '1600' -- '1601' -- '1602' -- '1604' -- '1608' -- '1616' -- '1632' -- '1664' -- '1665' -- '1666' -- '1668' -- '1672' -- '1680' -- '1696' -- '1728' -- '1792' -- '1793' -- '1794' -- '1796' -- '1800' -- '1808' -- '1824' -- '1856' -- '1920' -- '2048' -- '2049' -- '2050' -- '2051' -- '2052' -- '2053' -- '2054' -- '2055' -- '2056' -- '2057' -- '2058' -- '2059' -- '2060' -- '2061' -- '2062' -- '2064' -- '2065' -- '2066' -- '2067' -- '2068' -- '2069' -- '2070' -- '2072' -- '2073' -- '2074' -- '2076' -- '2080' -- '2081' -- '2082' -- '2083' -- '2084' -- '2085' -- '2086' -- '2088' -- '2089' -- '2090' -- '2092' -- '2096' -- '2097' -- '2098' -- '2100' -- '2104' -- '2112' -- '2113' -- '2114' -- '2115' -- '2116' -- '2117' -- '2118' -- '2120' -- '2121' -- '2122' -- '2124' -- '2128' -- '2129' -- '2130' -- '2132' -- '2136' -- '2144' -- '2145' -- '2146' -- '2148' -- '2152' -- '2160' -- '2176' -- '2177' -- '2178' -- '2179' -- '2180' -- '2181' -- '2182' -- '2184' -- '2185' -- '2186' -- '2188' -- '2192' -- '2193' -- '2194' -- '2196' -- '2200' -- '2208' -- '2209' -- '2210' -- '2212' -- '2216' -- '2224' -- '2240' -- '2241' -- '2242' -- '2244' -- '2248' -- '2256' -- '2272' -- '2304' -- '2305' -- '2306' -- '2307' -- '2308' -- '2309' -- '2310' -- '2312' -- '2313' -- '2314' -- '2316' -- '2320' -- '2321' -- '2322' -- '2324' -- '2328' -- '2336' -- '2337' -- '2338' -- '2340' -- '2344' -- '2352' -- '2368' -- '2369' -- '2370' -- '2372' -- '2376' -- '2384' -- '2400' -- '2432' -- '2433' -- '2434' -- '2436' -- '2440' -- '2448' -- '2464' -- '2496' -- '2560' -- '2561' -- '2562' -- '2563' -- '2564' -- '2565' -- '2566' -- '2568' -- '2569' -- '2570' -- '2572' -- '2576' -- '2577' -- '2578' -- '2580' -- '2584' -- '2592' -- '2593' -- '2594' -- '2596' -- '2600' -- '2608' -- '2624' -- '2625' -- '2626' -- '2628' -- '2632' -- '2640' -- '2656' -- '2688' -- '2689' -- '2690' -- '2692' -- '2696' -- '2704' -- '2720' -- '2752' -- '2816' -- '2817' -- '2818' -- '2820' -- '2824' -- '2832' -- '2848' -- '2880' -- '2944' -- '3072' -- '3073' -- '3074' -- '3075' -- '3076' -- '3077' -- '3078' -- '3080' -- '3081' -- '3082' -- '3084' -- '3088' -- '3089' -- '3090' -- '3092' -- '3096' -- '3104' -- '3105' -- '3106' -- '3108' -- '3112' -- '3120' -- '3136' -- '3137' -- '3138' -- '3140' -- '3144' -- '3152' -- '3168' -- '3200' -- '3201' -- '3202' -- '3204' -- '3208' -- '3216' -- '3232' -- '3264' -- '3328' -- '3329' -- '3330' -- '3332' -- '3336' -- '3344' -- '3360' -- '3392' -- '3456' -- '3584' -- '3585' -- '3586' -- '3588' -- '3592' -- '3600' -- '3616' -- '3648' -- '3712' -- '3840' -- '4096' -- '4097' -- '4098' -- '4099' -- '4100' -- '4101' -- '4102' -- '4103' -- '4104' -- '4105' -- '4106' -- '4107' -- '4108' -- '4109' -- '4110' -- '4112' -- '4113' -- '4114' -- '4115' -- '4116' -- '4117' -- '4118' -- '4120' -- '4121' -- '4122' -- '4124' -- '4128' -- '4129' -- '4130' -- '4131' -- '4132' -- '4133' -- '4134' -- '4136' -- '4137' -- '4138' -- '4140' -- '4144' -- '4145' -- '4146' -- '4148' -- '4152' -- '4160' -- '4161' -- '4162' -- '4163' -- '4164' -- '4165' -- '4166' -- '4168' -- '4169' -- '4170' -- '4172' -- '4176' -- '4177' -- '4178' -- '4180' -- '4184' -- '4192' -- '4193' -- '4194' -- '4196' -- '4200' -- '4208' -- '4224' -- '4225' -- '4226' -- '4227' -- '4228' -- '4229' -- '4230' -- '4232' -- '4233' -- '4234' -- '4236' -- '4240' -- '4241' -- '4242' -- '4244' -- '4248' -- '4256' -- '4257' -- '4258' -- '4260' -- '4264' -- '4272' -- '4288' -- '4289' -- '4290' -- '4292' -- '4296' -- '4304' -- '4320' -- '4352' -- '4353' -- '4354' -- '4355' -- '4356' -- '4357' -- '4358' -- '4360' -- '4361' -- '4362' -- '4364' -- '4368' -- '4369' -- '4370' -- '4372' -- '4376' -- '4384' -- '4385' -- '4386' -- '4388' -- '4392' -- '4400' -- '4416' -- '4417' -- '4418' -- '4420' -- '4424' -- '4432' -- '4448' -- '4480' -- '4481' -- '4482' -- '4484' -- '4488' -- '4496' -- '4512' -- '4544' -- '4608' -- '4609' -- '4610' -- '4611' -- '4612' -- '4613' -- '4614' -- '4616' -- '4617' -- '4618' -- '4620' -- '4624' -- '4625' -- '4626' -- '4628' -- '4632' -- '4640' -- '4641' -- '4642' -- '4644' -- '4648' -- '4656' -- '4672' -- '4673' -- '4674' -- '4676' -- '4680' -- '4688' -- '4704' -- '4736' -- '4737' -- '4738' -- '4740' -- '4744' -- '4752' -- '4768' -- '4800' -- '4864' -- '4865' -- '4866' -- '4868' -- '4872' -- '4880' -- '4896' -- '4928' -- '4992' -- '5120' -- '5121' -- '5122' -- '5123' -- '5124' -- '5125' -- '5126' -- '5128' -- '5129' -- '5130' -- '5132' -- '5136' -- '5137' -- '5138' -- '5140' -- '5144' -- '5152' -- '5153' -- '5154' -- '5156' -- '5160' -- '5168' -- '5184' -- '5185' -- '5186' -- '5188' -- '5192' -- '5200' -- '5216' -- '5248' -- '5249' -- '5250' -- '5252' -- '5256' -- '5264' -- '5280' -- '5312' -- '5376' -- '5377' -- '5378' -- '5380' -- '5384' -- '5392' -- '5408' -- '5440' -- '5504' -- '5632' -- '5633' -- '5634' -- '5636' -- '5640' -- '5648' -- '5664' -- '5696' -- '5760' -- '5888' -- '6144' -- '6145' -- '6146' -- '6147' -- '6148' -- '6149' -- '6150' -- '6152' -- '6153' -- '6154' -- '6156' -- '6160' -- '6161' -- '6162' -- '6164' -- '6168' -- '6176' -- '6177' -- '6178' -- '6180' -- '6184' -- '6192' -- '6208' -- '6209' -- '6210' -- '6212' -- '6216' -- '6224' -- '6240' -- '6272' -- '6273' -- '6274' -- '6276' -- '6280' -- '6288' -- '6304' -- '6336' -- '6400' -- '6401' -- '6402' -- '6404' -- '6408' -- '6416' -- '6432' -- '6464' -- '6528' -- '6656' -- '6657' -- '6658' -- '6660' -- '6664' -- '6672' -- '6688' -- '6720' -- '6784' -- '6912' -- '7168' -- '7169' -- '7170' -- '7172' -- '7176' -- '7184' -- '7200' -- '7232' -- '7296' -- '7424' -- '7680' -- '8192' -- '8193' -- '8194' -- '8195' -- '8196' -- '8197' -- '8198' -- '8199' -- '8200' -- '8201' -- '8202' -- '8203' -- '8204' -- '8205' -- '8206' -- '8208' -- '8209' -- '8210' -- '8211' -- '8212' -- '8213' -- '8214' -- '8216' -- '8217' -- '8218' -- '8220' -- '8224' -- '8225' -- '8226' -- '8227' -- '8228' -- '8229' -- '8230' -- '8232' -- '8233' -- '8234' -- '8236' -- '8240' -- '8241' -- '8242' -- '8244' -- '8248' -- '8256' -- '8257' -- '8258' -- '8259' -- '8260' -- '8261' -- '8262' -- '8264' -- '8265' -- '8266' -- '8268' -- '8272' -- '8273' -- '8274' -- '8276' -- '8280' -- '8288' -- '8289' -- '8290' -- '8292' -- '8296' -- '8304' -- '8320' -- '8321' -- '8322' -- '8323' -- '8324' -- '8325' -- '8326' -- '8328' -- '8329' -- '8330' -- '8332' -- '8336' -- '8337' -- '8338' -- '8340' -- '8344' -- '8352' -- '8353' -- '8354' -- '8356' -- '8360' -- '8368' -- '8384' -- '8385' -- '8386' -- '8388' -- '8392' -- '8400' -- '8416' -- '8448' -- '8449' -- '8450' -- '8451' -- '8452' -- '8453' -- '8454' -- '8456' -- '8457' -- '8458' -- '8460' -- '8464' -- '8465' -- '8466' -- '8468' -- '8472' -- '8480' -- '8481' -- '8482' -- '8484' -- '8488' -- '8496' -- '8512' -- '8513' -- '8514' -- '8516' -- '8520' -- '8528' -- '8544' -- '8576' -- '8577' -- '8578' -- '8580' -- '8584' -- '8592' -- '8608' -- '8640' -- '8704' -- '8705' -- '8706' -- '8707' -- '8708' -- '8709' -- '8710' -- '8712' -- '8713' -- '8714' -- '8716' -- '8720' -- '8721' -- '8722' -- '8724' -- '8728' -- '8736' -- '8737' -- '8738' -- '8740' -- '8744' -- '8752' -- '8768' -- '8769' -- '8770' -- '8772' -- '8776' -- '8784' -- '8800' -- '8832' -- '8833' -- '8834' -- '8836' -- '8840' -- '8848' -- '8864' -- '8896' -- '8960' -- '8961' -- '8962' -- '8964' -- '8968' -- '8976' -- '8992' -- '9024' -- '9088' -- '9216' -- '9217' -- '9218' -- '9219' -- '9220' -- '9221' -- '9222' -- '9224' -- '9225' -- '9226' -- '9228' -- '9232' -- '9233' -- '9234' -- '9236' -- '9240' -- '9248' -- '9249' -- '9250' -- '9252' -- '9256' -- '9264' -- '9280' -- '9281' -- '9282' -- '9284' -- '9288' -- '9296' -- '9312' -- '9344' -- '9345' -- '9346' -- '9348' -- '9352' -- '9360' -- '9376' -- '9408' -- '9472' -- '9473' -- '9474' -- '9476' -- '9480' -- '9488' -- '9504' -- '9536' -- '9600' -- '9728' -- '9729' -- '9730' -- '9732' -- '9736' -- '9744' -- '9760' -- '9792' -- '9856' -- '9984' -- '10240' -- '10241' -- '10242' -- '10243' -- '10244' -- '10245' -- '10246' -- '10248' -- '10249' -- '10250' -- '10252' -- '10256' -- '10257' -- '10258' -- '10260' -- '10264' -- '10272' -- '10273' -- '10274' -- '10276' -- '10280' -- '10288' -- '10304' -- '10305' -- '10306' -- '10308' -- '10312' -- '10320' -- '10336' -- '10368' -- '10369' -- '10370' -- '10372' -- '10376' -- '10384' -- '10400' -- '10432' -- '10496' -- '10497' -- '10498' -- '10500' -- '10504' -- '10512' -- '10528' -- '10560' -- '10624' -- '10752' -- '10753' -- '10754' -- '10756' -- '10760' -- '10768' -- '10784' -- '10816' -- '10880' -- '11008' -- '11264' -- '11265' -- '11266' -- '11268' -- '11272' -- '11280' -- '11296' -- '11328' -- '11392' -- '11520' -- '11776' -- '12288' -- '12289' -- '12290' -- '12291' -- '12292' -- '12293' -- '12294' -- '12296' -- '12297' -- '12298' -- '12300' -- '12304' -- '12305' -- '12306' -- '12308' -- '12312' -- '12320' -- '12321' -- '12322' -- '12324' -- '12328' -- '12336' -- '12352' -- '12353' -- '12354' -- '12356' -- '12360' -- '12368' -- '12384' -- '12416' -- '12417' -- '12418' -- '12420' -- '12424' -- '12432' -- '12448' -- '12480' -- '12544' -- '12545' -- '12546' -- '12548' -- '12552' -- '12560' -- '12576' -- '12608' -- '12672' -- '12800' -- '12801' -- '12802' -- '12804' -- '12808' -- '12816' -- '12832' -- '12864' -- '12928' -- '13056' -- '13312' -- '13313' -- '13314' -- '13316' -- '13320' -- '13328' -- '13344' -- '13376' -- '13440' -- '13568' -- '13824' -- '14336' -- '14337' -- '14338' -- '14340' -- '14344' -- '14352' -- '14368' -- '14400' -- '14464' -- '14592' -- '14848' -- '15360' -- '16384' -- '16385' -- '16386' -- '16387' -- '16388' -- '16389' -- '16390' -- '16391' -- '16392' -- '16393' -- '16394' -- '16395' -- '16396' -- '16397' -- '16398' -- '16400' -- '16401' -- '16402' -- '16403' -- '16404' -- '16405' -- '16406' -- '16408' -- '16409' -- '16410' -- '16412' -- '16416' -- '16417' -- '16418' -- '16419' -- '16420' -- '16421' -- '16422' -- '16424' -- '16425' -- '16426' -- '16428' -- '16432' -- '16433' -- '16434' -- '16436' -- '16440' -- '16448' -- '16449' -- '16450' -- '16451' -- '16452' -- '16453' -- '16454' -- '16456' -- '16457' -- '16458' -- '16460' -- '16464' -- '16465' -- '16466' -- '16468' -- '16472' -- '16480' -- '16481' -- '16482' -- '16484' -- '16488' -- '16496' -- '16512' -- '16513' -- '16514' -- '16515' -- '16516' -- '16517' -- '16518' -- '16520' -- '16521' -- '16522' -- '16524' -- '16528' -- '16529' -- '16530' -- '16532' -- '16536' -- '16544' -- '16545' -- '16546' -- '16548' -- '16552' -- '16560' -- '16576' -- '16577' -- '16578' -- '16580' -- '16584' -- '16592' -- '16608' -- '16640' -- '16641' -- '16642' -- '16643' -- '16644' -- '16645' -- '16646' -- '16648' -- '16649' -- '16650' -- '16652' -- '16656' -- '16657' -- '16658' -- '16660' -- '16664' -- '16672' -- '16673' -- '16674' -- '16676' -- '16680' -- '16688' -- '16704' -- '16705' -- '16706' -- '16708' -- '16712' -- '16720' -- '16736' -- '16768' -- '16769' -- '16770' -- '16772' -- '16776' -- '16784' -- '16800' -- '16832' -- '16896' -- '16897' -- '16898' -- '16899' -- '16900' -- '16901' -- '16902' -- '16904' -- '16905' -- '16906' -- '16908' -- '16912' -- '16913' -- '16914' -- '16916' -- '16920' -- '16928' -- '16929' -- '16930' -- '16932' -- '16936' -- '16944' -- '16960' -- '16961' -- '16962' -- '16964' -- '16968' -- '16976' -- '16992' -- '17024' -- '17025' -- '17026' -- '17028' -- '17032' -- '17040' -- '17056' -- '17088' -- '17152' -- '17153' -- '17154' -- '17156' -- '17160' -- '17168' -- '17184' -- '17216' -- '17280' -- '17408' -- '17409' -- '17410' -- '17411' -- '17412' -- '17413' -- '17414' -- '17416' -- '17417' -- '17418' -- '17420' -- '17424' -- '17425' -- '17426' -- '17428' -- '17432' -- '17440' -- '17441' -- '17442' -- '17444' -- '17448' -- '17456' -- '17472' -- '17473' -- '17474' -- '17476' -- '17480' -- '17488' -- '17504' -- '17536' -- '17537' -- '17538' -- '17540' -- '17544' -- '17552' -- '17568' -- '17600' -- '17664' -- '17665' -- '17666' -- '17668' -- '17672' -- '17680' -- '17696' -- '17728' -- '17792' -- '17920' -- '17921' -- '17922' -- '17924' -- '17928' -- '17936' -- '17952' -- '17984' -- '18048' -- '18176' -- '18432' -- '18433' -- '18434' -- '18435' -- '18436' -- '18437' -- '18438' -- '18440' -- '18441' -- '18442' -- '18444' -- '18448' -- '18449' -- '18450' -- '18452' -- '18456' -- '18464' -- '18465' -- '18466' -- '18468' -- '18472' -- '18480' -- '18496' -- '18497' -- '18498' -- '18500' -- '18504' -- '18512' -- '18528' -- '18560' -- '18561' -- '18562' -- '18564' -- '18568' -- '18576' -- '18592' -- '18624' -- '18688' -- '18689' -- '18690' -- '18692' -- '18696' -- '18704' -- '18720' -- '18752' -- '18816' -- '18944' -- '18945' -- '18946' -- '18948' -- '18952' -- '18960' -- '18976' -- '19008' -- '19072' -- '19200' -- '19456' -- '19457' -- '19458' -- '19460' -- '19464' -- '19472' -- '19488' -- '19520' -- '19584' -- '19712' -- '19968' -- '20480' -- '20481' -- '20482' -- '20483' -- '20484' -- '20485' -- '20486' -- '20488' -- '20489' -- '20490' -- '20492' -- '20496' -- '20497' -- '20498' -- '20500' -- '20504' -- '20512' -- '20513' -- '20514' -- '20516' -- '20520' -- '20528' -- '20544' -- '20545' -- '20546' -- '20548' -- '20552' -- '20560' -- '20576' -- '20608' -- '20609' -- '20610' -- '20612' -- '20616' -- '20624' -- '20640' -- '20672' -- '20736' -- '20737' -- '20738' -- '20740' -- '20744' -- '20752' -- '20768' -- '20800' -- '20864' -- '20992' -- '20993' -- '20994' -- '20996' -- '21000' -- '21008' -- '21024' -- '21056' -- '21120' -- '21248' -- '21504' -- '21505' -- '21506' -- '21508' -- '21512' -- '21520' -- '21536' -- '21568' -- '21632' -- '21760' -- '22016' -- '22528' -- '22529' -- '22530' -- '22532' -- '22536' -- '22544' -- '22560' -- '22592' -- '22656' -- '22784' -- '23040' -- '23552' -- '24576' -- '24577' -- '24578' -- '24579' -- '24580' -- '24581' -- '24582' -- '24584' -- '24585' -- '24586' -- '24588' -- '24592' -- '24593' -- '24594' -- '24596' -- '24600' -- '24608' -- '24609' -- '24610' -- '24612' -- '24616' -- '24624' -- '24640' -- '24641' -- '24642' -- '24644' -- '24648' -- '24656' -- '24672' -- '24704' -- '24705' -- '24706' -- '24708' -- '24712' -- '24720' -- '24736' -- '24768' -- '24832' -- '24833' -- '24834' -- '24836' -- '24840' -- '24848' -- '24864' -- '24896' -- '24960' -- '25088' -- '25089' -- '25090' -- '25092' -- '25096' -- '25104' -- '25120' -- '25152' -- '25216' -- '25344' -- '25600' -- '25601' -- '25602' -- '25604' -- '25608' -- '25616' -- '25632' -- '25664' -- '25728' -- '25856' -- '26112' -- '26624' -- '26625' -- '26626' -- '26628' -- '26632' -- '26640' -- '26656' -- '26688' -- '26752' -- '26880' -- '27136' -- '27648' -- '28672' -- '28673' -- '28674' -- '28676' -- '28680' -- '28688' -- '28704' -- '28736' -- '28800' -- '28928' -- '29184' -- '29696' -- '30720' -- '32768' -- '32769' -- '32770' -- '32771' -- '32772' -- '32773' -- '32774' -- '32775' -- '32776' -- '32777' -- '32778' -- '32779' -- '32780' -- '32781' -- '32782' -- '32784' -- '32785' -- '32786' -- '32787' -- '32788' -- '32789' -- '32790' -- '32792' -- '32793' -- '32794' -- '32796' -- '32800' -- '32801' -- '32802' -- '32803' -- '32804' -- '32805' -- '32806' -- '32808' -- '32809' -- '32810' -- '32812' -- '32816' -- '32817' -- '32818' -- '32820' -- '32824' -- '32832' -- '32833' -- '32834' -- '32835' -- '32836' -- '32837' -- '32838' -- '32840' -- '32841' -- '32842' -- '32844' -- '32848' -- '32849' -- '32850' -- '32852' -- '32856' -- '32864' -- '32865' -- '32866' -- '32868' -- '32872' -- '32880' -- '32896' -- '32897' -- '32898' -- '32899' -- '32900' -- '32901' -- '32902' -- '32904' -- '32905' -- '32906' -- '32908' -- '32912' -- '32913' -- '32914' -- '32916' -- '32920' -- '32928' -- '32929' -- '32930' -- '32932' -- '32936' -- '32944' -- '32960' -- '32961' -- '32962' -- '32964' -- '32968' -- '32976' -- '32992' -- '33024' -- '33025' -- '33026' -- '33027' -- '33028' -- '33029' -- '33030' -- '33032' -- '33033' -- '33034' -- '33036' -- '33040' -- '33041' -- '33042' -- '33044' -- '33048' -- '33056' -- '33057' -- '33058' -- '33060' -- '33064' -- '33072' -- '33088' -- '33089' -- '33090' -- '33092' -- '33096' -- '33104' -- '33120' -- '33152' -- '33153' -- '33154' -- '33156' -- '33160' -- '33168' -- '33184' -- '33216' -- '33280' -- '33281' -- '33282' -- '33283' -- '33284' -- '33285' -- '33286' -- '33288' -- '33289' -- '33290' -- '33292' -- '33296' -- '33297' -- '33298' -- '33300' -- '33304' -- '33312' -- '33313' -- '33314' -- '33316' -- '33320' -- '33328' -- '33344' -- '33345' -- '33346' -- '33348' -- '33352' -- '33360' -- '33376' -- '33408' -- '33409' -- '33410' -- '33412' -- '33416' -- '33424' -- '33440' -- '33472' -- '33536' -- '33537' -- '33538' -- '33540' -- '33544' -- '33552' -- '33568' -- '33600' -- '33664' -- '33792' -- '33793' -- '33794' -- '33795' -- '33796' -- '33797' -- '33798' -- '33800' -- '33801' -- '33802' -- '33804' -- '33808' -- '33809' -- '33810' -- '33812' -- '33816' -- '33824' -- '33825' -- '33826' -- '33828' -- '33832' -- '33840' -- '33856' -- '33857' -- '33858' -- '33860' -- '33864' -- '33872' -- '33888' -- '33920' -- '33921' -- '33922' -- '33924' -- '33928' -- '33936' -- '33952' -- '33984' -- '34048' -- '34049' -- '34050' -- '34052' -- '34056' -- '34064' -- '34080' -- '34112' -- '34176' -- '34304' -- '34305' -- '34306' -- '34308' -- '34312' -- '34320' -- '34336' -- '34368' -- '34432' -- '34560' -- '34816' -- '34817' -- '34818' -- '34819' -- '34820' -- '34821' -- '34822' -- '34824' -- '34825' -- '34826' -- '34828' -- '34832' -- '34833' -- '34834' -- '34836' -- '34840' -- '34848' -- '34849' -- '34850' -- '34852' -- '34856' -- '34864' -- '34880' -- '34881' -- '34882' -- '34884' -- '34888' -- '34896' -- '34912' -- '34944' -- '34945' -- '34946' -- '34948' -- '34952' -- '34960' -- '34976' -- '35008' -- '35072' -- '35073' -- '35074' -- '35076' -- '35080' -- '35088' -- '35104' -- '35136' -- '35200' -- '35328' -- '35329' -- '35330' -- '35332' -- '35336' -- '35344' -- '35360' -- '35392' -- '35456' -- '35584' -- '35840' -- '35841' -- '35842' -- '35844' -- '35848' -- '35856' -- '35872' -- '35904' -- '35968' -- '36096' -- '36352' -- '36864' -- '36865' -- '36866' -- '36867' -- '36868' -- '36869' -- '36870' -- '36872' -- '36873' -- '36874' -- '36876' -- '36880' -- '36881' -- '36882' -- '36884' -- '36888' -- '36896' -- '36897' -- '36898' -- '36900' -- '36904' -- '36912' -- '36928' -- '36929' -- '36930' -- '36932' -- '36936' -- '36944' -- '36960' -- '36992' -- '36993' -- '36994' -- '36996' -- '37000' -- '37008' -- '37024' -- '37056' -- '37120' -- '37121' -- '37122' -- '37124' -- '37128' -- '37136' -- '37152' -- '37184' -- '37248' -- '37376' -- '37377' -- '37378' -- '37380' -- '37384' -- '37392' -- '37408' -- '37440' -- '37504' -- '37632' -- '37888' -- '37889' -- '37890' -- '37892' -- '37896' -- '37904' -- '37920' -- '37952' -- '38016' -- '38144' -- '38400' -- '38912' -- '38913' -- '38914' -- '38916' -- '38920' -- '38928' -- '38944' -- '38976' -- '39040' -- '39168' -- '39424' -- '39936' -- '40960' -- '40961' -- '40962' -- '40963' -- '40964' -- '40965' -- '40966' -- '40968' -- '40969' -- '40970' -- '40972' -- '40976' -- '40977' -- '40978' -- '40980' -- '40984' -- '40992' -- '40993' -- '40994' -- '40996' -- '41000' -- '41008' -- '41024' -- '41025' -- '41026' -- '41028' -- '41032' -- '41040' -- '41056' -- '41088' -- '41089' -- '41090' -- '41092' -- '41096' -- '41104' -- '41120' -- '41152' -- '41216' -- '41217' -- '41218' -- '41220' -- '41224' -- '41232' -- '41248' -- '41280' -- '41344' -- '41472' -- '41473' -- '41474' -- '41476' -- '41480' -- '41488' -- '41504' -- '41536' -- '41600' -- '41728' -- '41984' -- '41985' -- '41986' -- '41988' -- '41992' -- '42000' -- '42016' -- '42048' -- '42112' -- '42240' -- '42496' -- '43008' -- '43009' -- '43010' -- '43012' -- '43016' -- '43024' -- '43040' -- '43072' -- '43136' -- '43264' -- '43520' -- '44032' -- '45056' -- '45057' -- '45058' -- '45060' -- '45064' -- '45072' -- '45088' -- '45120' -- '45184' -- '45312' -- '45568' -- '46080' -- '47104' -- '49152' -- '49153' -- '49154' -- '49155' -- '49156' -- '49157' -- '49158' -- '49160' -- '49161' -- '49162' -- '49164' -- '49168' -- '49169' -- '49170' -- '49172' -- '49176' -- '49184' -- '49185' -- '49186' -- '49188' -- '49192' -- '49200' -- '49216' -- '49217' -- '49218' -- '49220' -- '49224' -- '49232' -- '49248' -- '49280' -- '49281' -- '49282' -- '49284' -- '49288' -- '49296' -- '49312' -- '49344' -- '49408' -- '49409' -- '49410' -- '49412' -- '49416' -- '49424' -- '49440' -- '49472' -- '49536' -- '49664' -- '49665' -- '49666' -- '49668' -- '49672' -- '49680' -- '49696' -- '49728' -- '49792' -- '49920' -- '50176' -- '50177' -- '50178' -- '50180' -- '50184' -- '50192' -- '50208' -- '50240' -- '50304' -- '50432' -- '50688' -- '51200' -- '51201' -- '51202' -- '51204' -- '51208' -- '51216' -- '51232' -- '51264' -- '51328' -- '51456' -- '51712' -- '52224' -- '53248' -- '53249' -- '53250' -- '53252' -- '53256' -- '53264' -- '53280' -- '53312' -- '53376' -- '53504' -- '53760' -- '54272' -- '55296' -- '57344' -- '57345' -- '57346' -- '57348' -- '57352' -- '57360' -- '57376' -- '57408' -- '57472' -- '57600' -- '57856' -- '58368' -- '59392' -- '61440' -init: null -input_size: null -cmvn_file: null -ctc_conf: - dropout_rate: 0.0 - ctc_type: builtin - reduce: true - ignore_nan_grad: true -joint_net_conf: null -use_preprocessor: true -token_type: char -bpemodel: null -non_linguistic_symbols: null -cleaner: null -g2p: null -speech_volume_normalize: null -rir_scp: null -rir_apply_prob: 1.0 -noise_scp: null -noise_apply_prob: 1.0 -noise_db_range: '13_15' -specaug: null -specaug_conf: {} -normalize: null -normalize_conf: {} -label_aggregator: null -label_aggregator_conf: {} -model: sond -model_conf: - # ctc_weight: 0.0 - lsm_weight: 0.1 - length_normalized_loss: true - max_spk_num: 16 - # predictor_weight: 1.0 - # predictor_bias: 1 - # sampling_ratio: 0.75 -# speech encoder -encoder: resnet34 -encoder_conf: - # pass by model, equal to feature dim - # input_size: 80 - pooling_type: "window_shift" - pool_size: 20 - stride: 1 - tf2torch_tensor_name_prefix_torch: encoder - tf2torch_tensor_name_prefix_tf: EAND/speech_encoder -speaker_encoder: conv -speaker_encoder_conf: - input_units: 256 - num_layers: 3 - num_units: 256 - kernel_size: 1 - dropout_rate: 0.0 - position_encoder: null - out_units: 256 - out_norm: false - auxiliary_states: false - tf2torch_tensor_name_prefix_torch: speaker_encoder - tf2torch_tensor_name_prefix_tf: EAND/speaker_encoder -ci_scorer: dot -ci_scorer_conf: {} -cd_scorer: san -cd_scorer_conf: - input_size: 512 - output_size: 512 - out_units: 1 - attention_heads: 4 - linear_units: 1024 - num_blocks: 4 - dropout_rate: 0.0 - positional_dropout_rate: 0.0 - attention_dropout_rate: 0.0 - # use string "null" to remove input layer - input_layer: "null" - pos_enc_class: null - normalize_before: true - tf2torch_tensor_name_prefix_torch: cd_scorer - tf2torch_tensor_name_prefix_tf: EAND/compute_distance_layer -# post net -decoder: fsmn -decoder_conf: - in_units: 32 - out_units: 2517 - filter_size: 31 - fsmn_num_layers: 6 - dnn_num_layers: 1 - num_memory_units: 512 - ffn_inner_dim: 512 - dropout_rate: 0.0 - tf2torch_tensor_name_prefix_torch: decoder - tf2torch_tensor_name_prefix_tf: EAND/post_net -frontend: wav_frontend -frontend_conf: - fs: 16000 - window: povey - n_mels: 80 - frame_length: 25 - frame_shift: 10 - filter_length_min: -1 - filter_length_max: -1 - lfr_m: 1 - lfr_n: 1 - dither: 0.0 - snip_edges: false -num_worker_count: 1 -required: -- output_dir -- token_list -oss_bucket: 'null' -version: 0.1.4 diff --git a/egs/alimeeting/diarization/sond/config_fbank.yaml b/egs/alimeeting/diarization/sond/config_fbank.yaml deleted file mode 100644 index cb4b8a921..000000000 --- a/egs/alimeeting/diarization/sond/config_fbank.yaml +++ /dev/null @@ -1,2728 +0,0 @@ -config: finetune.yaml -print_config: false -log_level: INFO -dry_run: false -iterator_type: sequence -output_dir: exp/sond -ngpu: 1 -seed: 0 -num_workers: 16 -num_att_plot: 0 -dist_backend: nccl -dist_init_method: env:// -dist_world_size: null -dist_rank: null -local_rank: 0 -dist_master_addr: null -dist_master_port: null -dist_launcher: null -multiprocessing_distributed: true -distributed: false -unused_parameters: true -sharded_ddp: false -ddp_backend: pytorch_ddp -cudnn_enabled: true -cudnn_benchmark: false -cudnn_deterministic: true -collect_stats: false -write_collected_feats: false -max_epoch: 50 -patience: null -val_scheduler_criterion: -- valid -- acc -early_stopping_criterion: -- valid -- loss -- min -best_model_criterion: -- - valid - - acc - - max -keep_nbest_models: 10 -nbest_averaging_interval: 0 -grad_clip: 5 -grad_clip_type: 2.0 -grad_noise: false -accum_grad: 1 -no_forward_run: false -resume: true -train_dtype: float32 -use_amp: false -log_interval: 50 -use_matplotlib: false -use_tensorboard: true -use_wandb: false -wandb_project: null -wandb_id: null -wandb_entity: null -wandb_name: null -wandb_model_log_interval: -1 -use_pai: true -detect_anomaly: false -pretrain_path: null -init_param: [] -ignore_init_mismatch: false -freeze_param: [] -num_iters_per_epoch: null -batch_size: 20 -valid_batch_size: null -batch_bins: 10000 -valid_batch_bins: null -train_shape_file: -- /data/volume1/youyan/aishell/ark/train/speech_shape.1 -- /data/volume1/youyan/aishell/ark/train/text_shape.1 -valid_shape_file: -- /data/volume1/youyan/aishell/ark/dev/speech_shape.1 -- /data/volume1/youyan/aishell/ark/dev/text_shape.1 -batch_type: length -valid_batch_type: null -fold_length: -- 512 -- 150 -sort_in_batch: descending -sort_batch: descending -multiple_iterator: false -chunk_length: 500 -chunk_shift_ratio: 0.5 -num_cache_chunks: 1024 -train_data_path_and_name_and_type: -- - /data/volume1/youyan/aishell/ark/train/data.scp - - speech - - kaldi_ark -- - /data/volume1/youyan/aishell/ark/train/data.text.1 - - text - - text -valid_data_path_and_name_and_type: -- - /data/volume1/youyan/aishell/ark/dev/data.scp - - speech - - kaldi_ark -- - /data/volume1/youyan/aishell/ark/dev/data.text.1 - - text - - text -allow_variable_data_keys: false -max_cache_size: 0.0 -max_cache_fd: 32 -valid_max_cache_size: null -optim: adam -optim_conf: - lr: 0.0005 -scheduler: warmuplr -scheduler_conf: - warmup_steps: 30000 -token_list: -- '0' -- '1' -- '2' -- '3' -- '4' -- '5' -- '6' -- '7' -- '8' -- '9' -- '10' -- '11' -- '12' -- '13' -- '14' -- '15' -- '16' -- '17' -- '18' -- '19' -- '20' -- '21' -- '22' -- '23' -- '24' -- '25' -- '26' -- '27' -- '28' -- '29' -- '30' -- '32' -- '33' -- '34' -- '35' -- '36' -- '37' -- '38' -- '39' -- '40' -- '41' -- '42' -- '43' -- '44' -- '45' -- '46' -- '48' -- '49' -- '50' -- '51' -- '52' -- '53' -- '54' -- '56' -- '57' -- '58' -- '60' -- '64' -- '65' -- '66' -- '67' -- '68' -- '69' -- '70' -- '71' -- '72' -- '73' -- '74' -- '75' -- '76' -- '77' -- '78' -- '80' -- '81' -- '82' -- '83' -- '84' -- '85' -- '86' -- '88' -- '89' -- '90' -- '92' -- '96' -- '97' -- '98' -- '99' -- '100' -- '101' -- '102' -- '104' -- '105' -- '106' -- '108' -- '112' -- '113' -- '114' -- '116' -- '120' -- '128' -- '129' -- '130' -- '131' -- '132' -- '133' -- '134' -- '135' -- '136' -- '137' -- '138' -- '139' -- '140' -- '141' -- '142' -- '144' -- '145' -- '146' -- '147' -- '148' -- '149' -- '150' -- '152' -- '153' -- '154' -- '156' -- '160' -- '161' -- '162' -- '163' -- '164' -- '165' -- '166' -- '168' -- '169' -- '170' -- '172' -- '176' -- '177' -- '178' -- '180' -- '184' -- '192' -- '193' -- '194' -- '195' -- '196' -- '197' -- '198' -- '200' -- '201' -- '202' -- '204' -- '208' -- '209' -- '210' -- '212' -- '216' -- '224' -- '225' -- '226' -- '228' -- '232' -- '240' -- '256' -- '257' -- '258' -- '259' -- '260' -- '261' -- '262' -- '263' -- '264' -- '265' -- '266' -- '267' -- '268' -- '269' -- '270' -- '272' -- '273' -- '274' -- '275' -- '276' -- '277' -- '278' -- '280' -- '281' -- '282' -- '284' -- '288' -- '289' -- '290' -- '291' -- '292' -- '293' -- '294' -- '296' -- '297' -- '298' -- '300' -- '304' -- '305' -- '306' -- '308' -- '312' -- '320' -- '321' -- '322' -- '323' -- '324' -- '325' -- '326' -- '328' -- '329' -- '330' -- '332' -- '336' -- '337' -- '338' -- '340' -- '344' -- '352' -- '353' -- '354' -- '356' -- '360' -- '368' -- '384' -- '385' -- '386' -- '387' -- '388' -- '389' -- '390' -- '392' -- '393' -- '394' -- '396' -- '400' -- '401' -- '402' -- '404' -- '408' -- '416' -- '417' -- '418' -- '420' -- '424' -- '432' -- '448' -- '449' -- '450' -- '452' -- '456' -- '464' -- '480' -- '512' -- '513' -- '514' -- '515' -- '516' -- '517' -- '518' -- '519' -- '520' -- '521' -- '522' -- '523' -- '524' -- '525' -- '526' -- '528' -- '529' -- '530' -- '531' -- '532' -- '533' -- '534' -- '536' -- '537' -- '538' -- '540' -- '544' -- '545' -- '546' -- '547' -- '548' -- '549' -- '550' -- '552' -- '553' -- '554' -- '556' -- '560' -- '561' -- '562' -- '564' -- '568' -- '576' -- '577' -- '578' -- '579' -- '580' -- '581' -- '582' -- '584' -- '585' -- '586' -- '588' -- '592' -- '593' -- '594' -- '596' -- '600' -- '608' -- '609' -- '610' -- '612' -- '616' -- '624' -- '640' -- '641' -- '642' -- '643' -- '644' -- '645' -- '646' -- '648' -- '649' -- '650' -- '652' -- '656' -- '657' -- '658' -- '660' -- '664' -- '672' -- '673' -- '674' -- '676' -- '680' -- '688' -- '704' -- '705' -- '706' -- '708' -- '712' -- '720' -- '736' -- '768' -- '769' -- '770' -- '771' -- '772' -- '773' -- '774' -- '776' -- '777' -- '778' -- '780' -- '784' -- '785' -- '786' -- '788' -- '792' -- '800' -- '801' -- '802' -- '804' -- '808' -- '816' -- '832' -- '833' -- '834' -- '836' -- '840' -- '848' -- '864' -- '896' -- '897' -- '898' -- '900' -- '904' -- '912' -- '928' -- '960' -- '1024' -- '1025' -- '1026' -- '1027' -- '1028' -- '1029' -- '1030' -- '1031' -- '1032' -- '1033' -- '1034' -- '1035' -- '1036' -- '1037' -- '1038' -- '1040' -- '1041' -- '1042' -- '1043' -- '1044' -- '1045' -- '1046' -- '1048' -- '1049' -- '1050' -- '1052' -- '1056' -- '1057' -- '1058' -- '1059' -- '1060' -- '1061' -- '1062' -- '1064' -- '1065' -- '1066' -- '1068' -- '1072' -- '1073' -- '1074' -- '1076' -- '1080' -- '1088' -- '1089' -- '1090' -- '1091' -- '1092' -- '1093' -- '1094' -- '1096' -- '1097' -- '1098' -- '1100' -- '1104' -- '1105' -- '1106' -- '1108' -- '1112' -- '1120' -- '1121' -- '1122' -- '1124' -- '1128' -- '1136' -- '1152' -- '1153' -- '1154' -- '1155' -- '1156' -- '1157' -- '1158' -- '1160' -- '1161' -- '1162' -- '1164' -- '1168' -- '1169' -- '1170' -- '1172' -- '1176' -- '1184' -- '1185' -- '1186' -- '1188' -- '1192' -- '1200' -- '1216' -- '1217' -- '1218' -- '1220' -- '1224' -- '1232' -- '1248' -- '1280' -- '1281' -- '1282' -- '1283' -- '1284' -- '1285' -- '1286' -- '1288' -- '1289' -- '1290' -- '1292' -- '1296' -- '1297' -- '1298' -- '1300' -- '1304' -- '1312' -- '1313' -- '1314' -- '1316' -- '1320' -- '1328' -- '1344' -- '1345' -- '1346' -- '1348' -- '1352' -- '1360' -- '1376' -- '1408' -- '1409' -- '1410' -- '1412' -- '1416' -- '1424' -- '1440' -- '1472' -- '1536' -- '1537' -- '1538' -- '1539' -- '1540' -- '1541' -- '1542' -- '1544' -- '1545' -- '1546' -- '1548' -- '1552' -- '1553' -- '1554' -- '1556' -- '1560' -- '1568' -- '1569' -- '1570' -- '1572' -- '1576' -- '1584' -- '1600' -- '1601' -- '1602' -- '1604' -- '1608' -- '1616' -- '1632' -- '1664' -- '1665' -- '1666' -- '1668' -- '1672' -- '1680' -- '1696' -- '1728' -- '1792' -- '1793' -- '1794' -- '1796' -- '1800' -- '1808' -- '1824' -- '1856' -- '1920' -- '2048' -- '2049' -- '2050' -- '2051' -- '2052' -- '2053' -- '2054' -- '2055' -- '2056' -- '2057' -- '2058' -- '2059' -- '2060' -- '2061' -- '2062' -- '2064' -- '2065' -- '2066' -- '2067' -- '2068' -- '2069' -- '2070' -- '2072' -- '2073' -- '2074' -- '2076' -- '2080' -- '2081' -- '2082' -- '2083' -- '2084' -- '2085' -- '2086' -- '2088' -- '2089' -- '2090' -- '2092' -- '2096' -- '2097' -- '2098' -- '2100' -- '2104' -- '2112' -- '2113' -- '2114' -- '2115' -- '2116' -- '2117' -- '2118' -- '2120' -- '2121' -- '2122' -- '2124' -- '2128' -- '2129' -- '2130' -- '2132' -- '2136' -- '2144' -- '2145' -- '2146' -- '2148' -- '2152' -- '2160' -- '2176' -- '2177' -- '2178' -- '2179' -- '2180' -- '2181' -- '2182' -- '2184' -- '2185' -- '2186' -- '2188' -- '2192' -- '2193' -- '2194' -- '2196' -- '2200' -- '2208' -- '2209' -- '2210' -- '2212' -- '2216' -- '2224' -- '2240' -- '2241' -- '2242' -- '2244' -- '2248' -- '2256' -- '2272' -- '2304' -- '2305' -- '2306' -- '2307' -- '2308' -- '2309' -- '2310' -- '2312' -- '2313' -- '2314' -- '2316' -- '2320' -- '2321' -- '2322' -- '2324' -- '2328' -- '2336' -- '2337' -- '2338' -- '2340' -- '2344' -- '2352' -- '2368' -- '2369' -- '2370' -- '2372' -- '2376' -- '2384' -- '2400' -- '2432' -- '2433' -- '2434' -- '2436' -- '2440' -- '2448' -- '2464' -- '2496' -- '2560' -- '2561' -- '2562' -- '2563' -- '2564' -- '2565' -- '2566' -- '2568' -- '2569' -- '2570' -- '2572' -- '2576' -- '2577' -- '2578' -- '2580' -- '2584' -- '2592' -- '2593' -- '2594' -- '2596' -- '2600' -- '2608' -- '2624' -- '2625' -- '2626' -- '2628' -- '2632' -- '2640' -- '2656' -- '2688' -- '2689' -- '2690' -- '2692' -- '2696' -- '2704' -- '2720' -- '2752' -- '2816' -- '2817' -- '2818' -- '2820' -- '2824' -- '2832' -- '2848' -- '2880' -- '2944' -- '3072' -- '3073' -- '3074' -- '3075' -- '3076' -- '3077' -- '3078' -- '3080' -- '3081' -- '3082' -- '3084' -- '3088' -- '3089' -- '3090' -- '3092' -- '3096' -- '3104' -- '3105' -- '3106' -- '3108' -- '3112' -- '3120' -- '3136' -- '3137' -- '3138' -- '3140' -- '3144' -- '3152' -- '3168' -- '3200' -- '3201' -- '3202' -- '3204' -- '3208' -- '3216' -- '3232' -- '3264' -- '3328' -- '3329' -- '3330' -- '3332' -- '3336' -- '3344' -- '3360' -- '3392' -- '3456' -- '3584' -- '3585' -- '3586' -- '3588' -- '3592' -- '3600' -- '3616' -- '3648' -- '3712' -- '3840' -- '4096' -- '4097' -- '4098' -- '4099' -- '4100' -- '4101' -- '4102' -- '4103' -- '4104' -- '4105' -- '4106' -- '4107' -- '4108' -- '4109' -- '4110' -- '4112' -- '4113' -- '4114' -- '4115' -- '4116' -- '4117' -- '4118' -- '4120' -- '4121' -- '4122' -- '4124' -- '4128' -- '4129' -- '4130' -- '4131' -- '4132' -- '4133' -- '4134' -- '4136' -- '4137' -- '4138' -- '4140' -- '4144' -- '4145' -- '4146' -- '4148' -- '4152' -- '4160' -- '4161' -- '4162' -- '4163' -- '4164' -- '4165' -- '4166' -- '4168' -- '4169' -- '4170' -- '4172' -- '4176' -- '4177' -- '4178' -- '4180' -- '4184' -- '4192' -- '4193' -- '4194' -- '4196' -- '4200' -- '4208' -- '4224' -- '4225' -- '4226' -- '4227' -- '4228' -- '4229' -- '4230' -- '4232' -- '4233' -- '4234' -- '4236' -- '4240' -- '4241' -- '4242' -- '4244' -- '4248' -- '4256' -- '4257' -- '4258' -- '4260' -- '4264' -- '4272' -- '4288' -- '4289' -- '4290' -- '4292' -- '4296' -- '4304' -- '4320' -- '4352' -- '4353' -- '4354' -- '4355' -- '4356' -- '4357' -- '4358' -- '4360' -- '4361' -- '4362' -- '4364' -- '4368' -- '4369' -- '4370' -- '4372' -- '4376' -- '4384' -- '4385' -- '4386' -- '4388' -- '4392' -- '4400' -- '4416' -- '4417' -- '4418' -- '4420' -- '4424' -- '4432' -- '4448' -- '4480' -- '4481' -- '4482' -- '4484' -- '4488' -- '4496' -- '4512' -- '4544' -- '4608' -- '4609' -- '4610' -- '4611' -- '4612' -- '4613' -- '4614' -- '4616' -- '4617' -- '4618' -- '4620' -- '4624' -- '4625' -- '4626' -- '4628' -- '4632' -- '4640' -- '4641' -- '4642' -- '4644' -- '4648' -- '4656' -- '4672' -- '4673' -- '4674' -- '4676' -- '4680' -- '4688' -- '4704' -- '4736' -- '4737' -- '4738' -- '4740' -- '4744' -- '4752' -- '4768' -- '4800' -- '4864' -- '4865' -- '4866' -- '4868' -- '4872' -- '4880' -- '4896' -- '4928' -- '4992' -- '5120' -- '5121' -- '5122' -- '5123' -- '5124' -- '5125' -- '5126' -- '5128' -- '5129' -- '5130' -- '5132' -- '5136' -- '5137' -- '5138' -- '5140' -- '5144' -- '5152' -- '5153' -- '5154' -- '5156' -- '5160' -- '5168' -- '5184' -- '5185' -- '5186' -- '5188' -- '5192' -- '5200' -- '5216' -- '5248' -- '5249' -- '5250' -- '5252' -- '5256' -- '5264' -- '5280' -- '5312' -- '5376' -- '5377' -- '5378' -- '5380' -- '5384' -- '5392' -- '5408' -- '5440' -- '5504' -- '5632' -- '5633' -- '5634' -- '5636' -- '5640' -- '5648' -- '5664' -- '5696' -- '5760' -- '5888' -- '6144' -- '6145' -- '6146' -- '6147' -- '6148' -- '6149' -- '6150' -- '6152' -- '6153' -- '6154' -- '6156' -- '6160' -- '6161' -- '6162' -- '6164' -- '6168' -- '6176' -- '6177' -- '6178' -- '6180' -- '6184' -- '6192' -- '6208' -- '6209' -- '6210' -- '6212' -- '6216' -- '6224' -- '6240' -- '6272' -- '6273' -- '6274' -- '6276' -- '6280' -- '6288' -- '6304' -- '6336' -- '6400' -- '6401' -- '6402' -- '6404' -- '6408' -- '6416' -- '6432' -- '6464' -- '6528' -- '6656' -- '6657' -- '6658' -- '6660' -- '6664' -- '6672' -- '6688' -- '6720' -- '6784' -- '6912' -- '7168' -- '7169' -- '7170' -- '7172' -- '7176' -- '7184' -- '7200' -- '7232' -- '7296' -- '7424' -- '7680' -- '8192' -- '8193' -- '8194' -- '8195' -- '8196' -- '8197' -- '8198' -- '8199' -- '8200' -- '8201' -- '8202' -- '8203' -- '8204' -- '8205' -- '8206' -- '8208' -- '8209' -- '8210' -- '8211' -- '8212' -- '8213' -- '8214' -- '8216' -- '8217' -- '8218' -- '8220' -- '8224' -- '8225' -- '8226' -- '8227' -- '8228' -- '8229' -- '8230' -- '8232' -- '8233' -- '8234' -- '8236' -- '8240' -- '8241' -- '8242' -- '8244' -- '8248' -- '8256' -- '8257' -- '8258' -- '8259' -- '8260' -- '8261' -- '8262' -- '8264' -- '8265' -- '8266' -- '8268' -- '8272' -- '8273' -- '8274' -- '8276' -- '8280' -- '8288' -- '8289' -- '8290' -- '8292' -- '8296' -- '8304' -- '8320' -- '8321' -- '8322' -- '8323' -- '8324' -- '8325' -- '8326' -- '8328' -- '8329' -- '8330' -- '8332' -- '8336' -- '8337' -- '8338' -- '8340' -- '8344' -- '8352' -- '8353' -- '8354' -- '8356' -- '8360' -- '8368' -- '8384' -- '8385' -- '8386' -- '8388' -- '8392' -- '8400' -- '8416' -- '8448' -- '8449' -- '8450' -- '8451' -- '8452' -- '8453' -- '8454' -- '8456' -- '8457' -- '8458' -- '8460' -- '8464' -- '8465' -- '8466' -- '8468' -- '8472' -- '8480' -- '8481' -- '8482' -- '8484' -- '8488' -- '8496' -- '8512' -- '8513' -- '8514' -- '8516' -- '8520' -- '8528' -- '8544' -- '8576' -- '8577' -- '8578' -- '8580' -- '8584' -- '8592' -- '8608' -- '8640' -- '8704' -- '8705' -- '8706' -- '8707' -- '8708' -- '8709' -- '8710' -- '8712' -- '8713' -- '8714' -- '8716' -- '8720' -- '8721' -- '8722' -- '8724' -- '8728' -- '8736' -- '8737' -- '8738' -- '8740' -- '8744' -- '8752' -- '8768' -- '8769' -- '8770' -- '8772' -- '8776' -- '8784' -- '8800' -- '8832' -- '8833' -- '8834' -- '8836' -- '8840' -- '8848' -- '8864' -- '8896' -- '8960' -- '8961' -- '8962' -- '8964' -- '8968' -- '8976' -- '8992' -- '9024' -- '9088' -- '9216' -- '9217' -- '9218' -- '9219' -- '9220' -- '9221' -- '9222' -- '9224' -- '9225' -- '9226' -- '9228' -- '9232' -- '9233' -- '9234' -- '9236' -- '9240' -- '9248' -- '9249' -- '9250' -- '9252' -- '9256' -- '9264' -- '9280' -- '9281' -- '9282' -- '9284' -- '9288' -- '9296' -- '9312' -- '9344' -- '9345' -- '9346' -- '9348' -- '9352' -- '9360' -- '9376' -- '9408' -- '9472' -- '9473' -- '9474' -- '9476' -- '9480' -- '9488' -- '9504' -- '9536' -- '9600' -- '9728' -- '9729' -- '9730' -- '9732' -- '9736' -- '9744' -- '9760' -- '9792' -- '9856' -- '9984' -- '10240' -- '10241' -- '10242' -- '10243' -- '10244' -- '10245' -- '10246' -- '10248' -- '10249' -- '10250' -- '10252' -- '10256' -- '10257' -- '10258' -- '10260' -- '10264' -- '10272' -- '10273' -- '10274' -- '10276' -- '10280' -- '10288' -- '10304' -- '10305' -- '10306' -- '10308' -- '10312' -- '10320' -- '10336' -- '10368' -- '10369' -- '10370' -- '10372' -- '10376' -- '10384' -- '10400' -- '10432' -- '10496' -- '10497' -- '10498' -- '10500' -- '10504' -- '10512' -- '10528' -- '10560' -- '10624' -- '10752' -- '10753' -- '10754' -- '10756' -- '10760' -- '10768' -- '10784' -- '10816' -- '10880' -- '11008' -- '11264' -- '11265' -- '11266' -- '11268' -- '11272' -- '11280' -- '11296' -- '11328' -- '11392' -- '11520' -- '11776' -- '12288' -- '12289' -- '12290' -- '12291' -- '12292' -- '12293' -- '12294' -- '12296' -- '12297' -- '12298' -- '12300' -- '12304' -- '12305' -- '12306' -- '12308' -- '12312' -- '12320' -- '12321' -- '12322' -- '12324' -- '12328' -- '12336' -- '12352' -- '12353' -- '12354' -- '12356' -- '12360' -- '12368' -- '12384' -- '12416' -- '12417' -- '12418' -- '12420' -- '12424' -- '12432' -- '12448' -- '12480' -- '12544' -- '12545' -- '12546' -- '12548' -- '12552' -- '12560' -- '12576' -- '12608' -- '12672' -- '12800' -- '12801' -- '12802' -- '12804' -- '12808' -- '12816' -- '12832' -- '12864' -- '12928' -- '13056' -- '13312' -- '13313' -- '13314' -- '13316' -- '13320' -- '13328' -- '13344' -- '13376' -- '13440' -- '13568' -- '13824' -- '14336' -- '14337' -- '14338' -- '14340' -- '14344' -- '14352' -- '14368' -- '14400' -- '14464' -- '14592' -- '14848' -- '15360' -- '16384' -- '16385' -- '16386' -- '16387' -- '16388' -- '16389' -- '16390' -- '16391' -- '16392' -- '16393' -- '16394' -- '16395' -- '16396' -- '16397' -- '16398' -- '16400' -- '16401' -- '16402' -- '16403' -- '16404' -- '16405' -- '16406' -- '16408' -- '16409' -- '16410' -- '16412' -- '16416' -- '16417' -- '16418' -- '16419' -- '16420' -- '16421' -- '16422' -- '16424' -- '16425' -- '16426' -- '16428' -- '16432' -- '16433' -- '16434' -- '16436' -- '16440' -- '16448' -- '16449' -- '16450' -- '16451' -- '16452' -- '16453' -- '16454' -- '16456' -- '16457' -- '16458' -- '16460' -- '16464' -- '16465' -- '16466' -- '16468' -- '16472' -- '16480' -- '16481' -- '16482' -- '16484' -- '16488' -- '16496' -- '16512' -- '16513' -- '16514' -- '16515' -- '16516' -- '16517' -- '16518' -- '16520' -- '16521' -- '16522' -- '16524' -- '16528' -- '16529' -- '16530' -- '16532' -- '16536' -- '16544' -- '16545' -- '16546' -- '16548' -- '16552' -- '16560' -- '16576' -- '16577' -- '16578' -- '16580' -- '16584' -- '16592' -- '16608' -- '16640' -- '16641' -- '16642' -- '16643' -- '16644' -- '16645' -- '16646' -- '16648' -- '16649' -- '16650' -- '16652' -- '16656' -- '16657' -- '16658' -- '16660' -- '16664' -- '16672' -- '16673' -- '16674' -- '16676' -- '16680' -- '16688' -- '16704' -- '16705' -- '16706' -- '16708' -- '16712' -- '16720' -- '16736' -- '16768' -- '16769' -- '16770' -- '16772' -- '16776' -- '16784' -- '16800' -- '16832' -- '16896' -- '16897' -- '16898' -- '16899' -- '16900' -- '16901' -- '16902' -- '16904' -- '16905' -- '16906' -- '16908' -- '16912' -- '16913' -- '16914' -- '16916' -- '16920' -- '16928' -- '16929' -- '16930' -- '16932' -- '16936' -- '16944' -- '16960' -- '16961' -- '16962' -- '16964' -- '16968' -- '16976' -- '16992' -- '17024' -- '17025' -- '17026' -- '17028' -- '17032' -- '17040' -- '17056' -- '17088' -- '17152' -- '17153' -- '17154' -- '17156' -- '17160' -- '17168' -- '17184' -- '17216' -- '17280' -- '17408' -- '17409' -- '17410' -- '17411' -- '17412' -- '17413' -- '17414' -- '17416' -- '17417' -- '17418' -- '17420' -- '17424' -- '17425' -- '17426' -- '17428' -- '17432' -- '17440' -- '17441' -- '17442' -- '17444' -- '17448' -- '17456' -- '17472' -- '17473' -- '17474' -- '17476' -- '17480' -- '17488' -- '17504' -- '17536' -- '17537' -- '17538' -- '17540' -- '17544' -- '17552' -- '17568' -- '17600' -- '17664' -- '17665' -- '17666' -- '17668' -- '17672' -- '17680' -- '17696' -- '17728' -- '17792' -- '17920' -- '17921' -- '17922' -- '17924' -- '17928' -- '17936' -- '17952' -- '17984' -- '18048' -- '18176' -- '18432' -- '18433' -- '18434' -- '18435' -- '18436' -- '18437' -- '18438' -- '18440' -- '18441' -- '18442' -- '18444' -- '18448' -- '18449' -- '18450' -- '18452' -- '18456' -- '18464' -- '18465' -- '18466' -- '18468' -- '18472' -- '18480' -- '18496' -- '18497' -- '18498' -- '18500' -- '18504' -- '18512' -- '18528' -- '18560' -- '18561' -- '18562' -- '18564' -- '18568' -- '18576' -- '18592' -- '18624' -- '18688' -- '18689' -- '18690' -- '18692' -- '18696' -- '18704' -- '18720' -- '18752' -- '18816' -- '18944' -- '18945' -- '18946' -- '18948' -- '18952' -- '18960' -- '18976' -- '19008' -- '19072' -- '19200' -- '19456' -- '19457' -- '19458' -- '19460' -- '19464' -- '19472' -- '19488' -- '19520' -- '19584' -- '19712' -- '19968' -- '20480' -- '20481' -- '20482' -- '20483' -- '20484' -- '20485' -- '20486' -- '20488' -- '20489' -- '20490' -- '20492' -- '20496' -- '20497' -- '20498' -- '20500' -- '20504' -- '20512' -- '20513' -- '20514' -- '20516' -- '20520' -- '20528' -- '20544' -- '20545' -- '20546' -- '20548' -- '20552' -- '20560' -- '20576' -- '20608' -- '20609' -- '20610' -- '20612' -- '20616' -- '20624' -- '20640' -- '20672' -- '20736' -- '20737' -- '20738' -- '20740' -- '20744' -- '20752' -- '20768' -- '20800' -- '20864' -- '20992' -- '20993' -- '20994' -- '20996' -- '21000' -- '21008' -- '21024' -- '21056' -- '21120' -- '21248' -- '21504' -- '21505' -- '21506' -- '21508' -- '21512' -- '21520' -- '21536' -- '21568' -- '21632' -- '21760' -- '22016' -- '22528' -- '22529' -- '22530' -- '22532' -- '22536' -- '22544' -- '22560' -- '22592' -- '22656' -- '22784' -- '23040' -- '23552' -- '24576' -- '24577' -- '24578' -- '24579' -- '24580' -- '24581' -- '24582' -- '24584' -- '24585' -- '24586' -- '24588' -- '24592' -- '24593' -- '24594' -- '24596' -- '24600' -- '24608' -- '24609' -- '24610' -- '24612' -- '24616' -- '24624' -- '24640' -- '24641' -- '24642' -- '24644' -- '24648' -- '24656' -- '24672' -- '24704' -- '24705' -- '24706' -- '24708' -- '24712' -- '24720' -- '24736' -- '24768' -- '24832' -- '24833' -- '24834' -- '24836' -- '24840' -- '24848' -- '24864' -- '24896' -- '24960' -- '25088' -- '25089' -- '25090' -- '25092' -- '25096' -- '25104' -- '25120' -- '25152' -- '25216' -- '25344' -- '25600' -- '25601' -- '25602' -- '25604' -- '25608' -- '25616' -- '25632' -- '25664' -- '25728' -- '25856' -- '26112' -- '26624' -- '26625' -- '26626' -- '26628' -- '26632' -- '26640' -- '26656' -- '26688' -- '26752' -- '26880' -- '27136' -- '27648' -- '28672' -- '28673' -- '28674' -- '28676' -- '28680' -- '28688' -- '28704' -- '28736' -- '28800' -- '28928' -- '29184' -- '29696' -- '30720' -- '32768' -- '32769' -- '32770' -- '32771' -- '32772' -- '32773' -- '32774' -- '32775' -- '32776' -- '32777' -- '32778' -- '32779' -- '32780' -- '32781' -- '32782' -- '32784' -- '32785' -- '32786' -- '32787' -- '32788' -- '32789' -- '32790' -- '32792' -- '32793' -- '32794' -- '32796' -- '32800' -- '32801' -- '32802' -- '32803' -- '32804' -- '32805' -- '32806' -- '32808' -- '32809' -- '32810' -- '32812' -- '32816' -- '32817' -- '32818' -- '32820' -- '32824' -- '32832' -- '32833' -- '32834' -- '32835' -- '32836' -- '32837' -- '32838' -- '32840' -- '32841' -- '32842' -- '32844' -- '32848' -- '32849' -- '32850' -- '32852' -- '32856' -- '32864' -- '32865' -- '32866' -- '32868' -- '32872' -- '32880' -- '32896' -- '32897' -- '32898' -- '32899' -- '32900' -- '32901' -- '32902' -- '32904' -- '32905' -- '32906' -- '32908' -- '32912' -- '32913' -- '32914' -- '32916' -- '32920' -- '32928' -- '32929' -- '32930' -- '32932' -- '32936' -- '32944' -- '32960' -- '32961' -- '32962' -- '32964' -- '32968' -- '32976' -- '32992' -- '33024' -- '33025' -- '33026' -- '33027' -- '33028' -- '33029' -- '33030' -- '33032' -- '33033' -- '33034' -- '33036' -- '33040' -- '33041' -- '33042' -- '33044' -- '33048' -- '33056' -- '33057' -- '33058' -- '33060' -- '33064' -- '33072' -- '33088' -- '33089' -- '33090' -- '33092' -- '33096' -- '33104' -- '33120' -- '33152' -- '33153' -- '33154' -- '33156' -- '33160' -- '33168' -- '33184' -- '33216' -- '33280' -- '33281' -- '33282' -- '33283' -- '33284' -- '33285' -- '33286' -- '33288' -- '33289' -- '33290' -- '33292' -- '33296' -- '33297' -- '33298' -- '33300' -- '33304' -- '33312' -- '33313' -- '33314' -- '33316' -- '33320' -- '33328' -- '33344' -- '33345' -- '33346' -- '33348' -- '33352' -- '33360' -- '33376' -- '33408' -- '33409' -- '33410' -- '33412' -- '33416' -- '33424' -- '33440' -- '33472' -- '33536' -- '33537' -- '33538' -- '33540' -- '33544' -- '33552' -- '33568' -- '33600' -- '33664' -- '33792' -- '33793' -- '33794' -- '33795' -- '33796' -- '33797' -- '33798' -- '33800' -- '33801' -- '33802' -- '33804' -- '33808' -- '33809' -- '33810' -- '33812' -- '33816' -- '33824' -- '33825' -- '33826' -- '33828' -- '33832' -- '33840' -- '33856' -- '33857' -- '33858' -- '33860' -- '33864' -- '33872' -- '33888' -- '33920' -- '33921' -- '33922' -- '33924' -- '33928' -- '33936' -- '33952' -- '33984' -- '34048' -- '34049' -- '34050' -- '34052' -- '34056' -- '34064' -- '34080' -- '34112' -- '34176' -- '34304' -- '34305' -- '34306' -- '34308' -- '34312' -- '34320' -- '34336' -- '34368' -- '34432' -- '34560' -- '34816' -- '34817' -- '34818' -- '34819' -- '34820' -- '34821' -- '34822' -- '34824' -- '34825' -- '34826' -- '34828' -- '34832' -- '34833' -- '34834' -- '34836' -- '34840' -- '34848' -- '34849' -- '34850' -- '34852' -- '34856' -- '34864' -- '34880' -- '34881' -- '34882' -- '34884' -- '34888' -- '34896' -- '34912' -- '34944' -- '34945' -- '34946' -- '34948' -- '34952' -- '34960' -- '34976' -- '35008' -- '35072' -- '35073' -- '35074' -- '35076' -- '35080' -- '35088' -- '35104' -- '35136' -- '35200' -- '35328' -- '35329' -- '35330' -- '35332' -- '35336' -- '35344' -- '35360' -- '35392' -- '35456' -- '35584' -- '35840' -- '35841' -- '35842' -- '35844' -- '35848' -- '35856' -- '35872' -- '35904' -- '35968' -- '36096' -- '36352' -- '36864' -- '36865' -- '36866' -- '36867' -- '36868' -- '36869' -- '36870' -- '36872' -- '36873' -- '36874' -- '36876' -- '36880' -- '36881' -- '36882' -- '36884' -- '36888' -- '36896' -- '36897' -- '36898' -- '36900' -- '36904' -- '36912' -- '36928' -- '36929' -- '36930' -- '36932' -- '36936' -- '36944' -- '36960' -- '36992' -- '36993' -- '36994' -- '36996' -- '37000' -- '37008' -- '37024' -- '37056' -- '37120' -- '37121' -- '37122' -- '37124' -- '37128' -- '37136' -- '37152' -- '37184' -- '37248' -- '37376' -- '37377' -- '37378' -- '37380' -- '37384' -- '37392' -- '37408' -- '37440' -- '37504' -- '37632' -- '37888' -- '37889' -- '37890' -- '37892' -- '37896' -- '37904' -- '37920' -- '37952' -- '38016' -- '38144' -- '38400' -- '38912' -- '38913' -- '38914' -- '38916' -- '38920' -- '38928' -- '38944' -- '38976' -- '39040' -- '39168' -- '39424' -- '39936' -- '40960' -- '40961' -- '40962' -- '40963' -- '40964' -- '40965' -- '40966' -- '40968' -- '40969' -- '40970' -- '40972' -- '40976' -- '40977' -- '40978' -- '40980' -- '40984' -- '40992' -- '40993' -- '40994' -- '40996' -- '41000' -- '41008' -- '41024' -- '41025' -- '41026' -- '41028' -- '41032' -- '41040' -- '41056' -- '41088' -- '41089' -- '41090' -- '41092' -- '41096' -- '41104' -- '41120' -- '41152' -- '41216' -- '41217' -- '41218' -- '41220' -- '41224' -- '41232' -- '41248' -- '41280' -- '41344' -- '41472' -- '41473' -- '41474' -- '41476' -- '41480' -- '41488' -- '41504' -- '41536' -- '41600' -- '41728' -- '41984' -- '41985' -- '41986' -- '41988' -- '41992' -- '42000' -- '42016' -- '42048' -- '42112' -- '42240' -- '42496' -- '43008' -- '43009' -- '43010' -- '43012' -- '43016' -- '43024' -- '43040' -- '43072' -- '43136' -- '43264' -- '43520' -- '44032' -- '45056' -- '45057' -- '45058' -- '45060' -- '45064' -- '45072' -- '45088' -- '45120' -- '45184' -- '45312' -- '45568' -- '46080' -- '47104' -- '49152' -- '49153' -- '49154' -- '49155' -- '49156' -- '49157' -- '49158' -- '49160' -- '49161' -- '49162' -- '49164' -- '49168' -- '49169' -- '49170' -- '49172' -- '49176' -- '49184' -- '49185' -- '49186' -- '49188' -- '49192' -- '49200' -- '49216' -- '49217' -- '49218' -- '49220' -- '49224' -- '49232' -- '49248' -- '49280' -- '49281' -- '49282' -- '49284' -- '49288' -- '49296' -- '49312' -- '49344' -- '49408' -- '49409' -- '49410' -- '49412' -- '49416' -- '49424' -- '49440' -- '49472' -- '49536' -- '49664' -- '49665' -- '49666' -- '49668' -- '49672' -- '49680' -- '49696' -- '49728' -- '49792' -- '49920' -- '50176' -- '50177' -- '50178' -- '50180' -- '50184' -- '50192' -- '50208' -- '50240' -- '50304' -- '50432' -- '50688' -- '51200' -- '51201' -- '51202' -- '51204' -- '51208' -- '51216' -- '51232' -- '51264' -- '51328' -- '51456' -- '51712' -- '52224' -- '53248' -- '53249' -- '53250' -- '53252' -- '53256' -- '53264' -- '53280' -- '53312' -- '53376' -- '53504' -- '53760' -- '54272' -- '55296' -- '57344' -- '57345' -- '57346' -- '57348' -- '57352' -- '57360' -- '57376' -- '57408' -- '57472' -- '57600' -- '57856' -- '58368' -- '59392' -- '61440' -init: null -input_size: 80 -ctc_conf: - dropout_rate: 0.0 - ctc_type: builtin - reduce: true - ignore_nan_grad: true -joint_net_conf: null -use_preprocessor: true -token_type: char -bpemodel: null -non_linguistic_symbols: null -cleaner: null -g2p: null -speech_volume_normalize: null -rir_scp: null -rir_apply_prob: 1.0 -noise_scp: null -noise_apply_prob: 1.0 -noise_db_range: '13_15' -frontend: null -frontend_conf: {} -specaug: null -specaug_conf: {} -normalize: null -normalize_conf: {} -label_aggregator: null -label_aggregator_conf: {} -model: sond -model_conf: - # ctc_weight: 0.0 - lsm_weight: 0.1 - length_normalized_loss: true - max_spk_num: 16 - # predictor_weight: 1.0 - # predictor_bias: 1 - # sampling_ratio: 0.75 -# speech encoder -encoder: resnet34 -encoder_conf: - # pass by model, equal to feature dim - # input_size: 80 - pooling_type: "window_shift" - pool_size: 20 - stride: 1 - tf2torch_tensor_name_prefix_torch: encoder - tf2torch_tensor_name_prefix_tf: EAND/speech_encoder -speaker_encoder: conv -speaker_encoder_conf: - input_units: 256 - num_layers: 3 - num_units: 256 - kernel_size: 1 - dropout_rate: 0.0 - position_encoder: null - out_units: 256 - out_norm: false - auxiliary_states: false - tf2torch_tensor_name_prefix_torch: speaker_encoder - tf2torch_tensor_name_prefix_tf: EAND/speaker_encoder -ci_scorer: dot -ci_scorer_conf: {} -cd_scorer: san -cd_scorer_conf: - input_size: 512 - output_size: 512 - out_units: 1 - attention_heads: 4 - linear_units: 1024 - num_blocks: 4 - dropout_rate: 0.0 - positional_dropout_rate: 0.0 - attention_dropout_rate: 0.0 - # use string "null" to remove input layer - input_layer: "null" - pos_enc_class: null - normalize_before: true - tf2torch_tensor_name_prefix_torch: cd_scorer - tf2torch_tensor_name_prefix_tf: EAND/compute_distance_layer -# post net -decoder: fsmn -decoder_conf: - in_units: 32 - out_units: 2517 - filter_size: 31 - fsmn_num_layers: 6 - dnn_num_layers: 1 - num_memory_units: 512 - ffn_inner_dim: 512 - dropout_rate: 0.0 - tf2torch_tensor_name_prefix_torch: decoder - tf2torch_tensor_name_prefix_tf: EAND/post_net -num_worker_count: 1 -required: -- output_dir -- token_list -oss_bucket: 'null' -version: 0.1.6 diff --git a/egs/alimeeting/diarization/sond/infer_alimeeting_test.py b/egs/alimeeting/diarization/sond/infer_alimeeting_test.py deleted file mode 100644 index b4d534bee..000000000 --- a/egs/alimeeting/diarization/sond/infer_alimeeting_test.py +++ /dev/null @@ -1,24 +0,0 @@ -from funasr.bin.diar_inference_launch import inference_launch -import sys - - -def main(): - diar_config_path = sys.argv[1] if len(sys.argv) > 1 else "sond_fbank.yaml" - diar_model_path = sys.argv[2] if len(sys.argv) > 2 else "sond.pb" - output_dir = sys.argv[3] if len(sys.argv) > 3 else "./outputs" - data_path_and_name_and_type = [ - ("data/test_rmsil/feats.scp", "speech", "kaldi_ark"), - ("data/test_rmsil/test_rmsil_tdnn6_xvec.scp", "profile", "kaldi_ark"), - ] - pipeline = inference_launch( - mode="sond", - diar_train_config=diar_config_path, - diar_model_file=diar_model_path, - output_dir=output_dir, - num_workers=1 - ) - pipeline(data_path_and_name_and_type) - - -if __name__ == '__main__': - main() diff --git a/egs/alimeeting/diarization/sond/local/convert_label_to_rttm.py b/egs/alimeeting/diarization/sond/local/convert_label_to_rttm.py deleted file mode 100644 index 880f60fe7..000000000 --- a/egs/alimeeting/diarization/sond/local/convert_label_to_rttm.py +++ /dev/null @@ -1,132 +0,0 @@ -import os -from funasr.utils.job_runner import MultiProcessRunnerV3 -import numpy as np -from funasr.utils.misc import load_scp_as_list, load_scp_as_dict -from collections import OrderedDict -from tqdm import tqdm -from scipy.ndimage import median_filter - - -class MyRunner(MultiProcessRunnerV3): - def prepare(self, parser): - parser.add_argument("label_txt", type=str) - parser.add_argument("map_scp", type=str) - parser.add_argument("out_rttm", type=str) - parser.add_argument("--n_spk", type=int, default=4) - parser.add_argument("--chunk_len", type=int, default=1600) - parser.add_argument("--shift_len", type=int, default=400) - parser.add_argument("--ignore_len", type=int, default=5) - parser.add_argument("--smooth_size", type=int, default=7) - parser.add_argument("--vote_prob", type=float, default=0.5) - args = parser.parse_args() - - if not os.path.exists(os.path.dirname(args.out_rttm)): - os.makedirs(os.path.dirname(args.out_rttm)) - - utt2labels = load_scp_as_list(args.label_txt, 'list') - utt2labels = sorted(utt2labels, key=lambda x: x[0]) - meeting2map = load_scp_as_dict(args.map_scp) - meeting2labels = OrderedDict() - for utt_id, chunk_label in utt2labels: - mid = utt_id.split("-")[0] - if mid not in meeting2labels: - meeting2labels[mid] = [] - meeting2labels[mid].append(chunk_label) - task_list = [(mid, labels, meeting2map[mid]) for mid, labels in meeting2labels.items()] - - return task_list, None, args - - def post(self, result_list, args): - with open(args.out_rttm, "wt") as fd: - for results in result_list: - fd.writelines(results) - - -def int2vec(x, vec_dim=8, dtype=np.int): - b = ('{:0' + str(vec_dim) + 'b}').format(x) - # little-endian order: lower bit first - return (np.array(list(b)[::-1]) == '1').astype(dtype) - - -def seq2arr(seq, vec_dim=8): - return np.row_stack([int2vec(int(x), vec_dim) for x in seq]) - - -def sample2ms(sample, sr=16000): - return int(float(sample) / sr * 100) - - -def calc_multi_labels(chunk_label_list, chunk_len, shift_len, n_spk, vote_prob=0.5): - n_chunk = len(chunk_label_list) - last_chunk_valid_frame = len(chunk_label_list[-1]) - (chunk_len - shift_len) - n_frame = (n_chunk - 2) * shift_len + chunk_len + last_chunk_valid_frame - multi_labels = np.zeros((n_frame, n_spk), dtype=float) - weight = np.zeros((n_frame, 1), dtype=float) - for i in range(n_chunk): - raw_label = chunk_label_list[i] - for k in range(len(raw_label)): - if raw_label[k] == '': - raw_label[k] = raw_label[k-1] if k > 0 else '0' - chunk_multi_label = seq2arr(raw_label, n_spk) - chunk_len = chunk_multi_label.shape[0] - multi_labels[i*shift_len:i*shift_len+chunk_len, :] += chunk_multi_label - weight[i*shift_len:i*shift_len+chunk_len, :] += 1 - multi_labels = multi_labels / weight # normalizing vote - multi_labels = (multi_labels > vote_prob).astype(int) # voting results - return multi_labels - - -def calc_spk_turns(label_arr, spk_list): - turn_list = [] - length = label_arr.shape[0] - n_spk = label_arr.shape[1] - for k in range(n_spk): - if spk_list[k] == "None": - continue - in_utt = False - start = 0 - for i in range(length): - if label_arr[i, k] == 1 and in_utt is False: - start = i - in_utt = True - if label_arr[i, k] == 0 and in_utt is True: - turn_list.append([spk_list[k], start, i - start]) - in_utt = False - if in_utt: - turn_list.append([spk_list[k], start, length - start]) - return turn_list - - -def smooth_multi_labels(multi_label, win_len): - multi_label = median_filter(multi_label, (win_len, 1), mode="constant", cval=0.0).astype(int) - return multi_label - - -def process(task_args): - _, task_list, _, args = task_args - spk_list = ["spk{}".format(i+1) for i in range(args.n_spk)] - template = "SPEAKER {} 1 {:.2f} {:.2f} {} \n" - results = [] - for mid, chunk_label_list, map_file_path in tqdm(task_list, total=len(task_list), ascii=True, disable=args.no_pbar): - utt2map = load_scp_as_list(map_file_path, 'list') - multi_labels = calc_multi_labels(chunk_label_list, args.chunk_len, args.shift_len, args.n_spk, args.vote_prob) - multi_labels = smooth_multi_labels(multi_labels, args.smooth_size) - org_len = sample2ms(int(utt2map[-1][1][1]), args.sr) - org_multi_labels = np.zeros((org_len, args.n_spk)) - for seg_id, [org_st, org_ed, st, ed] in utt2map: - org_st, org_dur = sample2ms(int(org_st), args.sr), sample2ms(int(org_ed) - int(org_st), args.sr) - st, dur = sample2ms(int(st), args.sr), sample2ms(int(ed) - int(st), args.sr) - ll = min(org_multi_labels[org_st: org_st+org_dur, :].shape[0], multi_labels[st: st+dur, :].shape[0]) - org_multi_labels[org_st: org_st+ll, :] = multi_labels[st: st+ll, :] - spk_turns = calc_spk_turns(org_multi_labels, spk_list) - spk_turns = sorted(spk_turns, key=lambda x: x[1]) - for spk, st, dur in spk_turns: - # TODO: handle the leak of segments at the change points - if dur > args.ignore_len: - results.append(template.format(mid, float(st)/100, float(dur)/100, spk)) - return results - - -if __name__ == '__main__': - my_runner = MyRunner(process) - my_runner.run() diff --git a/egs/alimeeting/diarization/sond/path.sh b/egs/alimeeting/diarization/sond/path.sh deleted file mode 100755 index 7972642d0..000000000 --- a/egs/alimeeting/diarization/sond/path.sh +++ /dev/null @@ -1,5 +0,0 @@ -export FUNASR_DIR=$PWD/../../.. - -# NOTE(kan-bayashi): Use UTF-8 in Python to avoid UnicodeDecodeError when LC_ALL=C -export PYTHONIOENCODING=UTF-8 -export PATH=$FUNASR_DIR/funasr/bin:$PATH diff --git a/egs/alimeeting/diarization/sond/run.sh b/egs/alimeeting/diarization/sond/run.sh deleted file mode 100644 index 19ae40cdd..000000000 --- a/egs/alimeeting/diarization/sond/run.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash - -. ./path.sh || exit 1; - -stage=0 -stop_stage=2 - -. utils/parse_options.sh || exit 1; - -if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then - echo "Downloading AliMeeting test set data..." - wget https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_data/alimeeting_test_data_for_sond.tar.gz - echo "Done. Extracting data..." - tar zxf alimeeting_test_data_for_sond.tar.gz - echo "Done." - - echo "Downloading Pre-trained model..." - git clone https://www.modelscope.cn/damo/speech_xvector_sv-zh-cn-cnceleb-16k-spk3465-pytorch.git - git clone https://www.modelscope.cn/damo/speech_diarization_sond-zh-cn-alimeeting-16k-n16k4-pytorch.git - ln -s speech_xvector_sv-zh-cn-cnceleb-16k-spk3465-pytorch/sv.pb ./sv.pb - cp speech_xvector_sv-zh-cn-cnceleb-16k-spk3465-pytorch/sv.yaml ./sv.yaml - ln -s speech_diarization_sond-zh-cn-alimeeting-16k-n16k4-pytorch/sond.pb ./sond.pb - cp speech_diarization_sond-zh-cn-alimeeting-16k-n16k4-pytorch/sond_fbank.yaml ./sond_fbank.yaml - cp speech_diarization_sond-zh-cn-alimeeting-16k-n16k4-pytorch/sond.yaml ./sond.yaml - echo "Done." - - echo "Downloading dscore for scoring..." - git clone https://github.com/nryant/dscore.git -fi - -if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then - echo "Calculating diarization results..." - python infer_alimeeting_test.py sond_fbank.yaml sond.pb outputs - python local/convert_label_to_rttm.py \ - outputs/labels.txt \ - data/test_rmsil/raw_rmsil_map.scp \ - outputs/prediction_sm_83.rttm \ - --ignore_len 10 --no_pbar --smooth_size 83 \ - --vote_prob 0.5 --n_spk 16 -fi - -if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then - echo "Scoring..." - python dscore/score.py \ - -r data/test_rmsil/test_org.crttm \ - -s outputs/prediction_sm_83.rttm \ - --collar 0.25 -fi diff --git a/egs/alimeeting/diarization/sond/unit_test.py b/egs/alimeeting/diarization/sond/unit_test.py deleted file mode 100644 index 0f40ab29e..000000000 --- a/egs/alimeeting/diarization/sond/unit_test.py +++ /dev/null @@ -1,97 +0,0 @@ -from funasr.bin.diar_inference_launch import inference_launch -import os - - -def test_fbank_cpu_infer(): - diar_config_path = "config_fbank.yaml" - diar_model_path = "sond.pb" - output_dir = "./outputs" - data_path_and_name_and_type = [ - ("data/unit_test/test_feats.scp", "speech", "kaldi_ark"), - ("data/unit_test/test_profile.scp", "profile", "kaldi_ark"), - ] - pipeline = inference_launch( - mode="sond", - diar_train_config=diar_config_path, - diar_model_file=diar_model_path, - output_dir=output_dir, - num_workers=1, - log_level="WARNING", - ) - results = pipeline(data_path_and_name_and_type) - print(results) - - -def test_fbank_gpu_infer(): - diar_config_path = "config_fbank.yaml" - diar_model_path = "sond.pb" - output_dir = "./outputs" - data_path_and_name_and_type = [ - ("data/unit_test/test_feats.scp", "speech", "kaldi_ark"), - ("data/unit_test/test_profile.scp", "profile", "kaldi_ark"), - ] - pipeline = inference_launch( - mode="sond", - diar_train_config=diar_config_path, - diar_model_file=diar_model_path, - output_dir=output_dir, - ngpu=1, - num_workers=1, - log_level="WARNING", - ) - results = pipeline(data_path_and_name_and_type) - print(results) - - -def test_wav_gpu_infer(): - diar_config_path = "config.yaml" - diar_model_path = "sond.pb" - output_dir = "./outputs" - data_path_and_name_and_type = [ - ("data/unit_test/test_wav.scp", "speech", "sound"), - ("data/unit_test/test_profile.scp", "profile", "kaldi_ark"), - ] - pipeline = inference_launch( - mode="sond", - diar_train_config=diar_config_path, - diar_model_file=diar_model_path, - output_dir=output_dir, - ngpu=1, - num_workers=1, - log_level="WARNING", - ) - results = pipeline(data_path_and_name_and_type) - print(results) - - -def test_without_profile_gpu_infer(): - diar_config_path = "config.yaml" - diar_model_path = "sond.pb" - output_dir = "./outputs" - raw_inputs = [[ - "data/unit_test/raw_inputs/record.wav", - "data/unit_test/raw_inputs/spk1.wav", - "data/unit_test/raw_inputs/spk2.wav", - "data/unit_test/raw_inputs/spk3.wav", - "data/unit_test/raw_inputs/spk4.wav" - ]] - pipeline = inference_launch( - mode="sond_demo", - diar_train_config=diar_config_path, - diar_model_file=diar_model_path, - output_dir=output_dir, - ngpu=1, - num_workers=1, - log_level="WARNING", - param_dict={}, - ) - results = pipeline(raw_inputs=raw_inputs) - print(results) - - -if __name__ == '__main__': - os.environ["CUDA_VISIBLE_DEVICES"] = "0" - test_fbank_cpu_infer() - test_fbank_gpu_infer() - test_wav_gpu_infer() - test_without_profile_gpu_infer() diff --git a/egs/alimeeting/diarization/sond/unit_test_modelscope.py b/egs/alimeeting/diarization/sond/unit_test_modelscope.py deleted file mode 100644 index ea543e102..000000000 --- a/egs/alimeeting/diarization/sond/unit_test_modelscope.py +++ /dev/null @@ -1,92 +0,0 @@ -from modelscope.pipelines import pipeline -from modelscope.utils.constant import Tasks -import numpy as np -import os - - -def test_wav_cpu_infer(): - output_dir = "./outputs" - data_path_and_name_and_type = [ - "data/unit_test/test_wav.scp,speech,sound", - "data/unit_test/test_profile.scp,profile,kaldi_ark", - ] - diar_pipeline = pipeline( - task=Tasks.speaker_diarization, - model='damo/speech_diarization_sond-zh-cn-alimeeting-16k-n16k4-pytorch', - mode="sond", - output_dir=output_dir, - num_workers=0, - log_level="WARNING", - ) - results = diar_pipeline(data_path_and_name_and_type) - print(results) - - -def test_wav_gpu_infer(): - output_dir = "./outputs" - data_path_and_name_and_type = [ - "data/unit_test/test_wav.scp,speech,sound", - "data/unit_test/test_profile.scp,profile,kaldi_ark", - ] - diar_pipeline = pipeline( - task=Tasks.speaker_diarization, - model='damo/speech_diarization_sond-zh-cn-alimeeting-16k-n16k4-pytorch', - mode="sond", - output_dir=output_dir, - num_workers=0, - log_level="WARNING", - ) - results = diar_pipeline(data_path_and_name_and_type) - print(results) - - -def test_without_profile_gpu_infer(): - raw_inputs = [ - "data/unit_test/raw_inputs/record.wav", - "data/unit_test/raw_inputs/spk1.wav", - "data/unit_test/raw_inputs/spk2.wav", - "data/unit_test/raw_inputs/spk3.wav", - "data/unit_test/raw_inputs/spk4.wav" - ] - diar_pipeline = pipeline( - task=Tasks.speaker_diarization, - model='damo/speech_diarization_sond-zh-cn-alimeeting-16k-n16k4-pytorch', - mode="sond_demo", - sv_model="damo/speech_xvector_sv-zh-cn-cnceleb-16k-spk3465-pytorch", - sv_model_revision="master", - num_workers=0, - log_level="WARNING", - param_dict={}, - ) - results = diar_pipeline(raw_inputs) - print(results) - - -def test_url_without_profile_gpu_infer(): - raw_inputs = [ - "https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_data/speaker_diarization/record.wav", - "https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_data/speaker_diarization/spk1.wav", - "https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_data/speaker_diarization/spk2.wav", - "https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_data/speaker_diarization/spk3.wav", - "https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_data/speaker_diarization/spk4.wav", - ] - diar_pipeline = pipeline( - task=Tasks.speaker_diarization, - model='damo/speech_diarization_sond-zh-cn-alimeeting-16k-n16k4-pytorch', - mode="sond_demo", - sv_model="damo/speech_xvector_sv-zh-cn-cnceleb-16k-spk3465-pytorch", - sv_model_revision="master", - num_workers=0, - log_level="WARNING", - param_dict={}, - ) - results = diar_pipeline(raw_inputs) - print(results) - - -if __name__ == '__main__': - os.environ["CUDA_VISIBLE_DEVICES"] = "0" - test_wav_cpu_infer() - test_wav_gpu_infer() - test_without_profile_gpu_infer() - test_url_without_profile_gpu_infer() diff --git a/egs/alimeeting/modular_sa_asr/README.md b/egs/alimeeting/modular_sa_asr/README.md deleted file mode 100644 index f2779e681..000000000 --- a/egs/alimeeting/modular_sa_asr/README.md +++ /dev/null @@ -1,103 +0,0 @@ -# Get Started -This is an official modular SA-ASR system used in M2MeT 2.0 challenge. We developed this system based on various pre-trained models after the challenge and reach the ***SOTA***(until 2023.8.9) performance on the AliMeeting *Test_2023* set. You can also transcribe your own dataset by preparing it into the specific format shown in - -# Dependency - -To run this receipe, you should install [Kaldi](https://github.com/kaldi-asr/kaldi) and set the `KALDI_ROOT` in `path.sh`. -```shell -export KALDI_ROOT=/your_kaldi_path -``` - -We use the [VBx](https://github.com/BUTSpeechFIT/VBx) to provide initial diarization result to SOND and [dscore](https://github.com/nryant/dscore.git) to compute the DER. You should clone them before running this receipe. -```shell -$ mkdir VBx && cd VBx -$ git init -$ git remote add origin https://github.com/BUTSpeechFIT/VBx.git -$ git config core.sparsecheckout true -$ echo "VBx/*" >> .git/info/sparse-checkout -$ git pull origin master -$ mv VBx/* . -$ cd .. -$ git clone https://github.com/nryant/dscore.git -``` - -We use the [pb_chime5](https://github.com/fgnt/pb_chime5) to perform GSS. So you should install the dependencies of this repo using the following command. -```shell -$ git clone https://github.com/fgnt/pb_chime5.git -$ cd pb_chime5 -$ git submodule init -$ git submodule update -$ pip install -e pb_bss/ -$ pip install -e . -``` - -# Infer on the AliMeeting Test_2023 set -We follow the workflow shown below. - -

- -First you should set the `DATA_SOURCE` in `path.sh` to the data path. Your data path should be organized as follow: -```shell -Test_2023_Ali_far_release -|—— audio_dir/ -| |—— R1014_M1710.wav -| |—— R1014_M1750.wav -| |—— ... -|—— textgrid_dir/ -| |—— R1014_M1710.textgrid -| |—— R1014_M1750.textgrid -| |—— ... -|—— wav.scp -|—— segments -``` - -Then you can do speaker diarization with following command. -```shell -$ bash run_diar.sh -``` -After diarization, you can check the result at the last line of `data/Test_2023_Ali_far_sond/dia_outputs/dia_result`. You should get a DER about 1.51%. - -When you get the similar diarization result with us, then you can do the WPE and GSS using the following command. -```shell -$ bash run_enh.sh 8 -``` - -The number 8 should be replaced with the channel number of your dataset. Here we use the AliMeeting corpus which has 8 channels. - -Finally, you can decode the processed audio with the pre-trained ASR model directly using the flollowing commands. -```shell -$ bash run_asr.sh --stage 0 --stop-stage 1 -$ bash run_asr.sh --stage 3 --stop-stage 3 -``` -The ASR result is saved at `./speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch/decode_Test_2023_Ali_far_wpegss/text_cpcer`. - -# Infer on the AliMeeting Test_2023 set after finetune -You can finetune the pre-trained ASR model with the AliMeeting train set to obtain a further reduction on the cpCER. To infer on the AliMeeting Test 2023 set after finetuning, you can run this commands after the train set is processed with WPE and GSS mentioned above. - ```shell -$ bash run_asr.sh --stage 2 --stop-stage 3 -``` - -# Infer with your own dataset -We also support infer with your own dataset. Your dataset should be organized as above. The `wav.scp` and `segments` file should format as: - ```shell -# wav.scp -sessionA wav_path/wav_name_A.wav -sessionB wav_path/wav_name_B.wav -sessionC wav_path/wav_name_C.wav -... - -# segments -sessionA-start_time-end_time sessionA start_time end_time -sessionB-start_time-end_time sessionA start_time end_time -sessionC-start_time-end_time sessionA start_time end_time -... -``` -Then you should set the `DATA_SOURCE` and `DATA_NAME` in `path.sh`. The rest of the process is the same as [Infer on the AliMeeting Test_2023 set](#infer-on-the-alimeeting-test_2023-set). - -# Result - -| |VBx DER(%) | SOND DER(%)|cp-CER(%) | -|:---------------|:------------:|:------------:|----------:| -|before finetune | 16.87 | 1.51 | 10.18 | -|after finetune | 16.87 | 1.51 | **8.84** | - diff --git a/egs/alimeeting/modular_sa_asr/conf/mfcc_hires.conf b/egs/alimeeting/modular_sa_asr/conf/mfcc_hires.conf deleted file mode 100644 index 7fc2ecbaa..000000000 --- a/egs/alimeeting/modular_sa_asr/conf/mfcc_hires.conf +++ /dev/null @@ -1,11 +0,0 @@ -# config for high-resolution MFCC features, intended for neural network training. -# Note: we keep all cepstra, so it has the same info as filterbank features, -# but MFCC is more easily compressible (because less correlated) which is why -# we prefer this method. ---use-energy=false # use average of log energy, not energy. ---sample-frequency=16000 ---num-mel-bins=40 ---num-ceps=40 ---low-freq=40 ---high-freq=-400 - diff --git a/egs/alimeeting/modular_sa_asr/exp/segmentation_1a/tdnn_stats_sad_1a/cmvn_opts b/egs/alimeeting/modular_sa_asr/exp/segmentation_1a/tdnn_stats_sad_1a/cmvn_opts deleted file mode 100755 index 117f4ebcf..000000000 --- a/egs/alimeeting/modular_sa_asr/exp/segmentation_1a/tdnn_stats_sad_1a/cmvn_opts +++ /dev/null @@ -1 +0,0 @@ ---norm-means=false --norm-vars=false diff --git a/egs/alimeeting/modular_sa_asr/exp/segmentation_1a/tdnn_stats_sad_1a/final.raw b/egs/alimeeting/modular_sa_asr/exp/segmentation_1a/tdnn_stats_sad_1a/final.raw deleted file mode 100755 index 95269b512bed39fe2f2f60f395dda28b7289250b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5102860 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

5H!PdR-S_iFD>Fm5hHj&tYGE^gr{cmFnER8fO| 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

*Uhgu9K3u0KlzoE|#}!doV?NG| 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 bjKR%*1s$Bh=Z)Wu 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Ŏj3UA^hXZ)jX+U z9ci?DE%vxa^kHti^_u2vJn@mM|{)S?clTm0~assGCCfOv+Q71|CVx_Dy z|Ni9>+I#;angj1bAx#B0A*b`^uok}mJWd!Z6+>&(3|9C1DmhlvK)x3%;vk*hLJmG% zWL?^iL%lzVw`94J87>1*Oro%D-3;oz$7jc1 zVyfN{j?*+bZXU=-ZK=V|LQ|%6(uZszI&k8RDc-*eFvnyX&sw_)kFE)%o7C$e>-Ami zkrMWGI+Ka%0^#}2m`qjna`>b8sq{YBCZRq=7-~q9}FIRyaF97XR{S^7J}A5dHVX%6C5)y z6v>ou;&v>8I*vF2a`D<+es>^gF=@s(e#`l|+f(>-EZzVPuCmjSEZxh0cB7)Cd-F;oCS|dU63?O z_$-+M1Lj~6JGS--G;CZ(Y>IqX&Zpfpz}td$o9&=~BOS5a{UQ|-Zg|k#yY$O+1v=rO z7&Z1t(IU;o|&TkmEZc{~J1s!W9mxqeVr+=J^sU8d($5i0ILswQ7Ib9j+@%Jy#FTA%wNc@3jX6??@Y(D?v9Xu<_9i``DE^^ITkcc zgv>_UD7u(O!m9Ok_-b1;FPc<>ZgdgJrwiDk&*OQ+v^F+aMV?DXMuWn~E5zmQIr!>P zkM~cz2^_jJxJB~8SiEQG*x8nRO z?(E-BJII}LfxUzZQJ-QBkx-HWtE5s4z4i=N6po=|y9}8)=rI(0QKFI$w!@35cSKu; z$?z2=CcJFoI(#MF5BKvgpi$`vG5BY}mAY9t}sKhe+`BKfcJ^)VS^X3i$R`m(Mb8 zAu3dwi~PrPPtS7P^l}Wfe67Ia`!>N8JwKK+Wv3{G2Zg@eaS!h08I zIKN*4ABNeJH($5e0@Y`lb>(&o?A) z+QYb#zbcwFhGY2Mb}*}XF4CSd3_;Ti-wo17ErTZX%sq$WJ+8tKxdJ)Aw1fG*P=XJ8 zzT?@`6TwB{w0PF&P90k*;4Ulax4P82W$fR|);>#o4F(&vs%AbvbW$KD}V8CzUe5smr@A-gQ%YLH5 zXDxowy@h;Dk;VH4Q%KNuCHQ?)(9W*D4OQKp5N~UTZ}-)c>4Svsv7HK;c(WgBk8vVe zO4&u5Oq|@>!tx^YVZ@@b@LT&o4EH~Q8EZ@6i?=Kqy*rJg{l=nhnhpLur%995eemP) z65`y~gj?luK`gTi{y0IkNEr92ELb*y)bS+LClj)>Of7>mvHDU_&B=9txFv|w(KlBPYwaKD~6GOnkbPZa9 zB|I|&_51NF=r=>3F z2K^Q8@fDc5Vg$^|pN$@dJ><%&Z|rsWQ*y;UnVDusLjLS~@ZCTicj8Z`6q8BZ&*@>D z&=YffXveIAKZ_phcfd_aWn}!?|L`K22DN(*KxJ1DM!cEH+GkdRxtS!5Z>Ynj*Gpm7 zgf9r;3qU)n1OEg_@wN>|;X~jS!Ras@>@^;P^zcQ(_qUFWJn^2L3+WVDW~tC~>f5+& zWd;(IgvWE)mxUJJ`2F$*etRC-_>9gkz0^gzQQIScmVryL{%kHp zSqu9;)%jqjY=n6;3n6Sr8Vp$+0%t4ApuNjdV63bZfA-XYVMFV%aB2i@R8*ipYox)u zLZ}jDRYQ%Z35i`aoBAx4gFjz(!_)!En7oj(?`GR^;^eobK?{4Za8LtyE2NQy&C@VI zU5e7?1d^Jr#cH;HghUv?bOIS*1N#~HA6f8dJ~6tp2r6QyvF56~5Pd5|U=VzQcHdLrXg`HcS`&=Y z^sH#df)Qj(55Y#GWf=!O-+3s84S1iO1L4_9=LMYWthQE1_N5@vP?sw*Tgtj~|VdSVXM{gY_X zkTj^hcY%c6cE`?l^5`fw!_qfG#}-V;>^o0zsgt#k=`9x3e@_tp21B?run#7`4}uCq zp$p|T9kS~i%(r!q#=4JRp<>(td=N8(u1k6gZL+eUY21Vv&F7$6lVI1C4q|iavN%m5 z3RhQ;#sSyDQMc8Ud#${R16p^Gva}uyoK%Ga_Bev$fo!n+_qsG-ViCNQJb+bh;l%x| z7ZDpYpwEb*(7a6>D?=~i-h)hZed9vfnzDdgh#boNCMW_~83q2~zgfogSeD$=K}IJg zh|gv-U%mJqvMNhI@V1G)WrE{MwyVp?D}gm-dm zEL}`Md;#|B2S8G@5=?%fhRb(P1k10%AR5<68a2ifWhOZ0)@Q;G;st~5JtKzxi*e>P zLN06lh5p~_ps73sk7Vw~jDY8?ME4-6JN1gyFM28NPf^5A$3I~7m~(8U$|f={Gz71u z-NTk}Lv%Xgi&u3XkYs5Y9CJ1ty|2#0^CM2;?Smh|v}``6U%Ahe?HWYxTf#&;1V+hY zmq51n<8*j4pc$Q1i&3L>05|DcgDtNV>G-dy&{i>xg&jC0zBbw)%tf`tU(1Ia>-9jn z4X#Wwdm-$R$;PbA#W;Ll5i7n|!7|rfhuT9iWShVTK6D_J7$}d!o$f-Gw(}Nyezci= z{p`i{C%2-@)Z=99hpVXmR`90xC&9L7H`(TI4P4CX)L9SY)CC zR=+kB#Rip=&f~FI!p6eIr$ezzF{+jZn{!> z{Z#~%WN1-`pZ)CBErOT+$%41T2=l`muA2X9Y!?~%Y0`{987w?y3UNwN?6{<|*mCG) z6n~M0(~84!*m5Ux|LUu>wnX8ElfpHA^o|A}c;*JbG2#f_{ptiM?vUr>+q$4eCxiwr zQ=kiLz1ggmP+mIh3u8&qcz25&K37-ca!pfdlTA4HSovA3ama)ZJahquY}bbQ$zy3q zsWM%r5e6FH*3fIRz_(35CODNUu=3|Vp6(?}iR^g%BXA-#+N1ce2swVE^Z?!pv&Luo zF6h1TIXI}ChOvw9ku5O^tYbCsI(7{lswk{W(#F-%E$CAs!e!k}Y*oM~ICx!^NKEr2 zf0a6jqpAn_uy!xYbM~h?33fbHNrKjXnGRv?FT|Ghw{Wb|9n9CYr9X5Z5;GrjDmT}T z_FXaHP6`2dX!m$N?o>Kmd`XH=DW1VgYSnns89iQkEs5)E2V;I#0xhr6qMN1%@o|6c z!7TGAJ)&`v|GC!;uLk{wOoL(2d2TX(H5#sO zO-5!^Mns#4`&>sFN+cQ-DJfC;M0=YRDI+8$gsh0t!hNo{nOP~7Qlu$KX(@&L-rwK< zJ?f$R_I{u1IZ7*>7_LZih@O(lcTL`5%Ar#%f#cFaO>Rx&D@gWbK1^ z_iCI!w3aP9+=&LFvb5CF4zqWCgQ4{r!ip|8G}Ku|&uuri?Csa&ri#|F+EzlxXvj0! z!B&h(RAAzr%`jn{0zI!Y8WwD_5scgHO)ma-8^`_Vg3!WHxS?yulR9)bk|K`Hmu0wu zdy05Hv6uanQh<(MmMF7b9M`2i#xY-%aM~QcM}NAE{Snuo(s|d}>WP=3&uJw#uFK>1 zPE+XYE>}F)KMl68RfX8!oe-;)2{lg2e6FE|%~@!SmY%sd6!aL$uV>_s^=%AhH%UY1 zFx2I!(fy~*(NNwRmv=N-i7zz+qeSE(AWd#&CId=&^NFRoC1+P_t7a{8-`ap z2$rVYV@Jqg^z!1!*ony?slOG{5@k7)Z!>Uc>`m5s&Ki32azX!V2P-QRrPH-ES^VFh ztY$$I`=wX~gZz6!HRu3y?Bm&Xd~dhx-)EBiMwaPp+C`F1SK`ao@wm8i6;pXXk$9v< zvIA#$U(6$aLB*tVF#Eb39dH|FTXsytf-Q;Y<$NB7 z;!^JNvC@Tix&OhQyt0P zcb`eE_Xf0Cua4gyb(5b3$MNH=By29643u+V7S3uUa8n6Jx}JrH!;8RVgM{Geu~)2- zdjsian)IC5L+1AI502FDCF9E?@mK90@|pL$$R8YuWiFT58jA-w=(|<$Q_ll*)YoG6 z4L|s*S%XnW4X|P4UATR~0z`eA$ibL=#Ef6WPFG79(cFtNj>qt&$r#I$)bA|hs3d&) zE=jMYrjWT}kw{8jfZN#5MB=|vf#q{KVVTQ%p7$X|zY8M}ytCNU^Bcj_x&Wr+@ou)_ zI_O)r0!rhLLzHH|aDSQzL@&7o8R-VNEG!mZ_fBLJ{8hQQT^(%ECPa(E6VT+Qglh&K zVCca(G`gM$g2_uQ*LM`)nO&Z6ZbuvLZC-{)qYH5YpC@@Z>Lu>>+W@;>WukM|MaVT2 zLs2nT7B*=HIF^Q!+d)QxhZPaRA~qS5J_oT;%I}0d6AoaH?iNGT+RdCli{|p((r2i5sfXm& z?M2j>4wAb1!oq?Txb$5lT)VoIHXk=aLz$#fv%St-=F&*)SFge9|E3FrgH5PNs5KqA-E)`ZcSLK>7Wb1+#gV`>Gwc(V-v;AC)JV1l-*q8$Ve_u ze-6ESIEeFYI!11}?SoxuYV`cNRll2isOxeuBe*OUU9U@%)LpN^Ny9)&!M)c1oeHs)~%57|WhncIVL(;6TphOs4 z(~;+H%Z}yD6F&3z4|Sl!`)C|X_rm47CrSGHNL2q@g$uX3G0jESvH5NSJJqX9zdhdv zdwAX$ZQ~tLjy_zC=>;&%4TJDc7Xeum-LOoGGt}8ee=6MI?B-8lRnvap@ZXbYyxE6t zHMZu?29y#Bkul`U*uz*b*Nl^S(T&3*ox<$C_0%V`nx$^(BdO!k@biUu`19XaqH5g) ze~Q*|tHq%bd&m&ZSMB6-)<|*_U0I359EM#_KH~Ne8E!?~ zY;M#xzSDE+5T{^iNFQH(4%_*>QIm!WB)@Uto?G^S^`eQe?zb_$v{QleiU_BLL%iQS zssuBa2spmAho5dJVEoS7(wS^Mx7$IDE4QD{Mfg6%kzSOE)M=1!Yi|>a_-Ami>K&~3 z?>n4Jum+!EMb0>K1r=3qfsPHMxtf+ZcBIUL&2`Pkc?vgSV!=UJ{v{ko+`I-NqNg#< z=N#_YvIm!n)G@C$EyA*EiA4A=oTVPA#FbwyAbVdjDf)I&pzkJ0m&||1O1V0r=7|`1 zood9LQ}JegzWtyosmqa18LUr~XTY5>z%xm~I4toP-K6e-OWG*5ur&_n{&#?UP_h7S z!4CX7aX)5=7^7=Q2+npcW8R)&`2LD1+uGHO?)&wLZ^t9S)x~jmXW$U%tGeLES#_vw zX+u8jI1J+kYRQjF_GnrBldQT(VRd>D+-i*=UO6E+;fM<)DIFoZD;*#cZo*`l9FUs% z`hR!PkUe^kM6dmV{yaa%FYpwG7q!8;tV}Y0^h&tBLKBQy))J}Lu`Ceh@GM_zp{#;6 z=A21^c;{&p);Hlg0cABa+d*Ur?{u({CHgIX?2gYFC@I>9=M9C^BF)7E88& zgY#1+KvCpv;`4Vh>T77hlLDS=D}Rjqh`0xt({BnwOHT?OtLcMdyp)iv>R{qdd1UZT zv|#UlbMYX_X1=wl!lK_XtoXnPp5vu0oEoK!g_b^SoTDsv*EI`wnSCwYF4ut*7q!Ey zifER4E(O<{j)%gxJHdaZ1Ca{93AWwiQ1N3Bxl|~{ZC1{~uCv+D;hv5$adKE#VgTz$ zohLED_W<9A@`e9O0(uZH`0d6gQbX{R&lG+&DM#BAzNG%%R<>{4SZw^E zggP_~K5Q4KvZqo>YOxj8Nt8k4{RiarL{nDHcb`1Rs0!7Sn=_bk-vISp@jPXBdbr7W25+$ODw{ZnqMjpb8Ls}R%I|Js= zjD!>NA8>V>GTMKBiF@bdL99*}+}N5&K8*SRO8z;*=l@3IIwwu~JI9qt#i{W)<=wDo z`7)l17=q_qt}rbdg2idPmtoBWs5J{LEuEjwB-?)DnkpN-tP)JdOs-{(AF|1~0}EmO z?IGdsj55?TaAW_TZ$<7`5pg;u!Hxb|ist9!nO&tMRy91tMms(mWt9gH^k?7=Z&R4f z&&!q-qMWx#Kg=CC&z@baBHB71(C+<-l241$@XW_#aJ!d@0>dpZGHNdE@VoUxAk?R*G@aU=3XVVd*FjL z37a6XS&KaLSGGKGc z8hrT5QFym?1boj=t?MLHwQ$=Ax!&%`k?J5#@`xs#DM3D)-V`_&6;*`5<~*p0U>SYY6XM~N>Jxvq!@J*KmnRU6p$z4h?b=oTLL zzRAXH{f2gn#c(>OB~X#~hIaK@COYwn@X^8F%$_#885{_!L5QgNnR4%d*q5E zmOUVg-n0lm?tIPu9CSs$$XJ%~K%V0+<$?0Ia=57=WKXVmyoJ3dOk1AGT9xA4{5bBnY4G zFy#zq{)7>(VQ_Uq1kZ_aCi&y|ENRqz_F(&R?(afr?&i-P#J~D9&h8#0P)GXRDVnQw zZiZ1^IqZ7CL#T-3Gb`;@ROhQVm-b{NcS(O1E%ghbpA#0r<-YmcR+~9ocR9~6DvraW zb!ME-D^;3N5J3}ug;EjIk=&wf3AFG_B7ObC7xI((!SbjrYMjhvwkt-`RNk|q`}rd( ziH+kD5--yIKKbU*E-;Q$$_lMtR43nxSvU5}8cm}^atrvX=kJfr|`#}d5 z#eN_z2EL@NLz3p$DZ|3-OYl*73ys?O7XGcu75tv}7XvoM!Ny6oxcpYQAV%jB8L$13 zHLZDz-?lx2rQILV?Mw&$*eAwa3G*iwiAJ2?WJl^Myb1F{%c05OC_Fs;pTOv5uSHLq zJoevyKt8<`fuI~SWIa3!@vAwxCs~8uf4iVv;yzQ_r^79&oknTk0lJA>Nq1~mfdAq) z5V<}1zr3~9UN;E#dkB)IL{3-oSCEy92r_dsmpBK)EUo4jkkvM8Orqf{YdbRH{|ZyE~ge* zeW+V89Yvf&Ajszjn)*Kh`i=_P!Z|YcZwVfIc9hMJSPr+}s0i-&CZc9V4Bi{Rn02X- zXE9z6fO-S{xEgWW$Z{;?{RArlB*=|DZI%iK=i&IuEu5^{TKwi&!5U&d6J=>*R4%%2 z@w-Wk>pb=mCFJZt;?PZO;dufd+@|6Qb8&7{@Hy%;R1OpMBl&x*Ol(>>kNdN?2j_MB z;GLNB_;KkzZrdzNZddkxuKuMQ?WhWab0Xe^eUat*a3|6!>Slm?9+moa(5D=76(19kB;Yz_at-o5xJ z$SeL7z8e&yCr<XVF=xFM1oFUDyhAZ2_21eFuwdCd2uO1FTlCk*Ih%Fdf?_%t?tn$_r&mI$G$Hyny$sh)_l92)NFSxgCi^WB%-Xe~cl< zyDelF`rqJm{!9TIgJG}xd1y&_#a`d{h4k=NVm)^Nj@m5%-!U3+Ct45hX-lEZhyuL4 z^#i-H$Q5kVB(YQcFLsWXC#y7+(ddQ)Ec>oZB$dqIqq7TyTc)#ck78`}yM{saQMh{s zgG-N!p*(L06n^pduBT-%{C2tEeVR0E^L6Jrj5e_4W-%tMs~{oGRd};w0@Q8ZAoMtC z08*SWccW4TMJ0;SEyWP0+Iq5icRKJvH}#Jl+HMJYUrI*H=O3)%3|5IC^;C#mgF0cERd zGQ#&Z9$xc^ZL=y8tTaz4O+IYFy4AFya|lVo(vH%vlNO-5n<H)W~u+@=0o&Q<5L}nbhIi?-%V4c=oBBBsZmV7mWV`V)S zJ5$|YhE5hSy`xD_o=kxqBURBQM~miNi056OnIQNWkG>HejE51ytnh`f-Q5xIc1Wi?1gx~*+!XHxNiJIEajhtjDru)p&p^xo=*Ckihh{YC*QiZA4J zkF7^hwToosuQ+C(J{ECKIUB#yhx1R@p!VkB?An5Ua^+|pQ78$4zVgxFUzh>|X)EZg zx-FdX+eo~g97*>cQv;=83FFs}=@%UW=08&=TW<{Gr=c{FIg)TGHCqpNKL*rYASq?mC0P_UT6r03XhLXPLf^8cSFSMV;?LZ-FMg^O#ff&)AkdD|Kf z`10i>RNOCtWhL3TMrs-C8@ghdI#U2nkN>cE_h8s>rbe@E0%7#>zbrgCVm_JtTj>KAi%W0>pL-S$e1n}!tk@(Lif?VR$$iOV zY|0K#jGcXp%`;QM9ar89pS%gfj=&t)qHa%$)>|M)uEFLb{Q{Bi4rEzg9O_b0I?2Nq zE-`*bdsKuw5#tT}4EXcwsuNJ5_ny7Xzld>anDVHdM9wS!)@?+ z?gHP`w<0r{NWUx}fS%l8!3BC0J+r6cmVM6bceV*yoBSp3*(`SXz%8gevK`B{oOmBp z2d?_BUl47=_q4J^;A{63SQSztynkX1O#dAW>m@$Ij`pXxZLJ*EX*970!D2oWyc7#3 z9A!7Emyod7WbAnD#152=7tDJe1AR#o*}8jT82pCsCft;vw{tsCcl;Un5qJh(UOX+# zJ*!Ob>^}w#i*oUlZzC4)y)o^j%y~D@9+(ByXL{wH4;_fRM&{AVbHggGRE72#g^!UWGvPNQ)55R%=Y=~Mu z0TdP#quuK@WbR~j{M#`bAI#B3@i?m-)rZGi zXXApVMfgzvIN7%?7COC?Afx@8@W38x{C<8T+jC?cO!yK74s(uK76$jR_sx;0(Rm)$ zzbhh!{U_m(>RFVtU4lj}c|xVG#keA64Q#8D=camBGMQ^_&=6$6J#|gQb%V3n^t&z~ z_NxJpv3jW1h#;rcM7fs{m(hCDQ>LjmjFb2s)ZP)N+0{xdr%KR zYc=j!TSb=qx<*6<{#d$R3hw>a!g9|nLWv2=Y~NZFJZD94tz!}i`nMg=Zq|pTd+V6> zxjj59s)wyVWsT{dIJgk}m{`x>1sTPbsCe}w3_mG`eX&o4hosZl%SEPe=F?}E@iQ0S z{qcb4-i;8tyA5kLc#*T^dvJ{ZK0LF1C6>&N7Yd&}g6YxGSbOIb|8sW>PQG=Z6^eRj z$=(wSIb%>Podq6yC8^(51i6QknVMKD)Xg#$XthX!va}*9fhq<~<{jv66vjQz#h*uN zgl1-`d}l2gpCufC%o~YlCz=j9Pt!dV7 zOk1l2)1HqNs(DNyHOV?`l*FylhtBROJfMW%pM;>b`cbH8qo}JfLuj8q6TB*}LF<}i zaEMJo@wKnu(_jp~+}$sHwvl(c&1qt4b1cZA?>RW)4)3^{$e_wrj@;sMAms(W_kNg6 zmXTpLKDHT+7Vvw?-PLd^t(vV1(4ouEe`LEh??QXgeS!>cHN3A_g$oMWN}V}%VWG%3 zQX{s9QO}1!oj37k>y`)RFDc`D!td3_qQv_nSoxU1BTxQ}$W4Qm zhHLyC);N?I4u)^ht}yv+G(3CGdjS=1l1To$u;;oF@UlGC^eGnXKZrul*b3q{Zwssm zZpZ2B>(D^;0`BR*z(OL_s1@HE(dgTZt2TH*AJ>Fj&`6B@J{i=qE%1{00wURJh!0Xn zq5PCg%bF!+a4p~j41ZN;%G4R>%l+hYQ1jv49VM!K^$@hpSiqKS+Cqr=0T|Tr zAl(BTyXN%@CmOC}1#vvPZ>SjV4A(Hhl%*t8oS)m0Ps88j@fi2EiF{D=fC)MIj2qJh zIY*7ScT!SRZv0z5Pa=z+#|zNEPHS2hjRWh zoaxwO@FVRJ`Lop4GWKAru;k`x*q$dzEFZVxw~wR*w-nGKPcmn%A--bP+ zO-!cm2_~=kik}zX5_tVIV=dE9!M~KVaQ9dRnjeY4jn*!x@qR5T2JviR9VyEf#v4**8^XM=fkaiH%-~UHK#|4qkl^jeG&0u*|`RvT@ z8RWBKlcpMV{ zJ0xCY*>q_O*tqcXS&0ZNJv0{XTAm;Uw@>1^g|^_sMS!ouDUdBmU{8My2yG~1{tWV+yL)+pKy{|2=3ew%g#6} zQlpEV~I(h8qA5&;#OWB ziMU7~7CtW`NrgEOZMTvnW+cHnn{znYNdY}Sg^=ih1iaO{i@dnMfIO{~g{BlMw)@2y zjJU*es#8~i^DZM&6sU|7&vrrNoe`YfU=JLd{FTMm-ykuE`(W?>XZSfIj-77yXFn_t zknTO@Sg`Q|ri+;3d_MPoqIC!kOg_RKWLIMOms6k~Q-(8wci@@n8;R%EXBhPUAZm}6 zh5B8gkeDY8<6M<+$&oS)(B6W^_oN})bs|;hp1}28IE*S^BG@NSOMK&0#D;aQ8}ioF0FW z?HWi0PpU$bZz1c=aAEFU=`87bF|gagD2#T&i80SXRjHWx@XxX1Rvdhp{t(@EYqH6o zN^$FzQk*xb45KbyMk_fBp;K-c@z9mz4(2|Fyn0FQl43J?*mk;<)~e%7lP-*Iv1K${ z4mK>40f~d7NWEPc`tbc&-JYXtvWFQ2Sj&^*SQS#$S457=dJ>JTfw=1TYi4~T8>f!f zXgSS8;|ufrQc7*b9Gz9u>W5qa64w;;?Kp*;Ati<`K3iK2l_FmP~I-~ z+Fqz=?2-y#5hh}24`)cxB@e1-nAB+gJptW;?;pu=5 ztd})Ljj#!neZ7aqEqB>f_{ahji?Mxq5WM8~H``j>K;p_$a5oS|1DTnyr+75pntU0S z=Zjz@|6!#3ih|0Wp^&pY28#F1fQ=Wc1{_u6zH>S)XmpchH;$R&GrcezJaU2EC>{&DEFZy#n`1Ct zXD5Eo{fZk}=i1~P`9t)~1LiJ{Z?;UxKKs5&9@coT_R zSHHoU5F-3r^_LVR1(Vq;qH)9AZp++*PngfDMl!7Fi9Kf=Nee&Q4E(X-nc|KR{%Rz5 z`J)*7vrm>N|2GRAZmH7W>AW+p|1q9fNRFwYln#$Pb}ZMyP^D0537{OVXnvZ*|be_uy)=R zJeMp-W?vQOmcEIHJ^8b+dRHvOg~vm`>ms!LQ7SMAP3IY#>u^WbKaw0;1i!zBleOGu zHbW4BLxvAnpU6x|YtIl`9v=xiU+lrw=K&C0Jd*pH*GX24IWE}sgrH+f5XQXR0P8Pw zk!?H=-BdRd2mi>SN5KpDRM7%2E`DNej|uKs8HZCdKe45vn_<^Mb*|!3Gf7ZZCcRU5 z;CE?=P$udYYj%mnEkBY0^kksr`BB)=Ey2xtQ$reC|FKOyB5+numfD*5!?}6yF)73V z%c3R0b509c({Y6+UPYn*BoYrI#+odF|y~eY&&+38F2W!Z@{zPz6-i{`#BC%4fgHS_v zVP?=0(5Z>TzLp-cCzcaz$))hgKnXryKP{ZN`;lNP&nAYnuc$>ID<(Hc9&-q(qso{4rO?4BQw9gyrB`1Pf zya!T)R|Hpyv$2`&=;>SyaqBnXwlo=T*O72^cx;4Ia50Hg>}SuPzJ<8`k-U>KnnhNB zBi+BA23(FK|!*2H!GXAqEcpqWRGWIrpn7S4hm#A=AJkL+8 za}T>TBACd$(4;E+C7Hw#Sy;Gu1IqHf@8Rg1rBNdt;Kar%_$iDeaWndu=R|c-5j{za z*Tf)uHv_l%xxqfGA(T$5!@cddApNKeSrI!8q9^?TPmd-c%J6sUvwYCID;8cI3S#r0 z2>HA5II{WhIB2Zji?*)ymVqmm5I++qxMgsI-TmAtC_Fm_GQ`^0iN+$Bd*c*ntQC?= z2lOCe?^!UhU&Ne)Ea`(9zDC-UhMKf>+^B?#OiD1!% zCYDr~3*Sn{plnSbyJ}Pjb2}U0QBI+7ugW>t8^g!Mc8mwL%BUG< zFVMOEnu+laqGv$`DAV>A6R8BF$`G+oG$j^--sY3Lcq(tl6 zt>B91Y2n`v2g=T#A;o-dzV^5$v*~&T8S1mZ>rFqXRddYcjS|TAh|`;8Jm2Y5B_wG4 zWAwYTaH)C?te!i8DAeu4{lPLACF~>SW4<$MBYT{bLqS`3SuiqIovY{h6|FxkV3c(| zbpLB6-P*hd#4i=6mVE?0si}DQD+gi2dTd375_amC!n5uxsNbIf?$S3=+H5OxdDTyx z|C!^v&arT1{5OG5>SD6%n*j@uFv9tk3S9EGmsqfPKR55?F;a5w9M*fjL%&gLxpCTB z^x4m3LDeS}$na32Z>Rl%Y@s%`H2fuNeff9CqVcG!dm6+u^&XS3?N zOl|R3p2NQnB+rc{O^!(zT6&FC?~^7v>-g{9T?sNZ;|984-Uzx5rR-GdK^*?Gl*!k> z#nbr?%v2?Y_)K=gXJWZ%m~AT9exaMJJER5qqML|?u^yiKYR6K#?xFb|RpF2=&(Ht< zid}14!QY8Hp>xL_7(3ns4jjBn)_e`Xn5!?yIltB9m}Mkv&B_oS9MmTJPpINk&uAf} zFM?-3lX#ADB{Qv0!57t`AQDU9!$t{i9S1BV&=}l~?PfNGd}b|I3sri8VNI!Wsp{oU z;yCXM%BCJ=KEh*=`CO-5M4 z?{x+2se3GXXXKM-V)E#w_=7!*jlk$dciD$weHctA$5!i2I5f?I9j~>-A2}=GiHRtu zwY?dtXYgF-Ew02SJ_SY2tU#NB!)&dI1{QXF79?&%VZG(q(!bGlEY3-uQ-^Ga9`Fvj5oOrd%wIys~L}R@7xBs zSi2exSIa@NiYV+D>cD)jRg~WNj_y~M(&7T3mx^TRjo5FXP_-J8>vgG(fexKu6oMCS z=EKeSMKmgC4rilwnbj;FQTkuAE%?9kgLeM+u&iqaXZI@tHET?GugWnDbF-q$`o-y0 zeS5B5Zh*ONC}Hbe!?5XcEGV92IMfhHhrAQ;)qWe!$yl5F#dr7Gk4rXn$EHIzxX?<&7+)1{=A74CqM77$?p?er?>)YYH}2g56QLAKn-xOsz5k=L{8VW{r87Q> ze2OqloD=Lc#s?LpAl0eKUC=9oM*f*s6>f}Q`o?f$9P(Jor~$zxuNN?}b~8>3>V%zf z_UN0ePww*G@ss}V&}fPhMozzv2FdPJq9q2~Hs1u{G$raA-v9-%-vwXzoaW@B4t!<& zlZ+1I+53IjEMTu87xB#%a!u!Rl6ppbUb&4dntuvfCNJWSJed!wwU@DNNfA7}!#mSB zOZt0zXX!Ry2l(NxN7qcRhguYp#*bmJbg2YcV6u!`2o4aOSq!^ACX&>n1no}oPG8=O z^GBf>UOK=zV=;X$XEV6Zjb~$s9M_w?nZ?hG5|Z{F2;uLYTUVYCHm>>y zM>2v~(&jGs;MdRYIhF|GCv5=jPdkMfvwq<^{{n20HAJKF_T-$^I;=AOOU4A+;QdQx z)NX!g@yi~5hB7aO+j8@{FJq6=sn;h^^Dh%1=kN^Lb?O{<+A|vb)CZ|r(GeQb6AL>= zNm^Z9c$ZcfnUk2=y4=07A#~305?s_O$4wroP3L}`PN%wt!1J&xY?+5St#^6M4*k^R z+|*?0AE`=~|3{GupY)C*Ip4}fFEec`cv4s1d3d$!TP1AdJ} z?Qj;0u0%szn<~{em8aV~S8!JTvpDD8h4g0XJm_gtroKj@WW{^ReMvq-n5g<#)!*`(#@3;!W*2`9OtoH_zRBXg;33x<&euq+% z)m6f_;79O&)E0WDT8=n-`C)nVNmhTrmA%Zn1O7CMOzwQadqvCGG$&8SdpOD4-cTHP zmPaafY%!Nm)90oYo5GD|2llS^8EzP2FzyH={!eZ3alIUPuh4?#=s7T^%oU&8@!gXC zMhLA5#F+_S7#ppO65;mT$S!dl>tPG7XODno(08Iab~lt9uO`c{#$nVqgmEtdNbPDz z)-nGz6aV5ys;|nx=UX+bLDPiWR+S22Hv5DQ16nwOXX|Cg&Z6yAD=~=Av+9Sda=YAS zG4Tyym>X0tRH-!P+BZ&M6SHi{x|}em4Sd5=MNGMOQ_JDx;al)NUleL(uHgCf3>bd1 zgig*BqSb=2^gz%9bWVQ2!lb{#^4DJ=GbaS(W?O(%fD{*OMBsr}uHf4>A9Q+TPh2$P zusv-mA@>n3#PnbepGi^483i39R)YNb=jb{29qaoROt#x+;MUF8@p6>`X8mht4sz|N zb?^+X@LNj7)~_WtasQRB>3&US)7?n*cxE^E|J@#08RJu<^Ac@e-A!Pfv?c1B-I- zZ_FfxY4a^e`(&E6P=xLC*a6Q9w!)@G5ol1-!hU}ni34Bjv7$DOIILTU3vIet_kanw z{9FJ@%ln{idJS%QqsF;8RuXbvjb0Ef7MLWC6a%-kY-&pE}FHpH2LG zSFavcuQ&}QQ*>$XZgnX7YKmol-!a*ZlSx1aPi579fVNNFA+eX=5%X?B@8ikrlXgFQ zJ)p>q9jOEcT^#&Y9#0A#7IMX5s|6zFUTFS02b^vOGqXlb`a%9psbX6U{5D929m7SK zx;&J*u2h7>TTa8L)75On%V%WhtP0IL_etneTFqV_I*O{aj>#NbfL{H&^z5oc(3-Lu zd%I?`PwS?G{1u*yf2e^N`yXIO)2Bk(-5so8;36FTWQ|@c64`EX-m4bATo9+VPdI&~ zIjW7Bf?iS?toq0w48%&o+C!nd@5zyqv|0vnyDAu$v6NF0{=&~j0_HpPn0$XQ6HMwF z`JJ^HH{+5t9ju>%dD=pV>=J^+e<$eNJ8n3`phmc{W-*uP{*+w4wwCTt9%SdCPFtB@7) zJ;716W^m)Z8F#3nh)a9|5GZO)9KX)wp6R?3Ub}jc>cr2Y*G$B@5B*PYup}2#{W$DD zo=u0eZ0Pza_S7=$2^zGFM$z1@WM7*!47#RJwHhJJ78G(OG=g3)<=I4&Zi0?8$9>&Z zz?Jfj+rV23soNi7wNPmnef>(GTX}4PRZrYJ?q8%MzP+@T`~HQW<1d78Cj%Y15qkH) z$L1rIl>I}yI)7lQnFib+mqFKje+=jUE8_YG`btka)xt!Ht3q+nyL3>bhR$;@;bz?U z2M3oC>Q}7KxoA(Oj70gG~ID4jVS(*duUxQ3f8GHBwH>F3~kon+{#q=FS!Bx z*G6G<&jh%uIfwO5&LhSe3?!SR1&Vcff|&1i5SCC$Jf36;D>s*wUMV`pR9y1O#{NLu zwl@vp90?Z94F);+<(&O-AFB_+J0WYkl+`%#&%{@!h_ef^;0#54=_fgJ`Y-7g7g!}v z?V|FDRy^SB%!^Ett09A#6SyK}EohrNjcaTUBil|oqG6v5x4Zd1TpqoK9$Gz@)?62- z9|NXvdPBeA^n(@HPsicoM^Ws>xYgis(V8xQu#MYUW=0iHWD>Q)MeO0SP+0iJlN)0` ziJRV!sJT~_IjtXpSC1rNUCmg`SUDMjnqOd@rZw(4D93&Iq|K#P@>8Jj0Gs%fLtRTD zgeGc2YTH~cF#inM(ilNEZZV+w1q(UVgdOzo@USpcZwB|pI1v0jT(IN6->k1bi1zt7 z(f(1ZxS7w3aBxR2ykG4@zvK_%#qDQl=3n40UgF=CZ)?E!i9GYqxCk$-(s7gXf9Rc} zz|HpYWEu_%II`$9)bTR|zy*A!emAFZ%$$3N^j%yofB}+kqg)su$~*?K7bVwkI^7^EZs72iLJ`& zgE=9W(9%STn_%zF`7|ldD99@UOjkahd2(V^azZ;YQjt2$8%x8QV>`k0w0gQK`(n0?9|=Hd)UNz*VPE_ zWWEu$`$XVy%Q&dY?}u&~B{n_iC@YV%DX}`ck;#2(1kV{4(DH}`l`*(b+GrDkXAIh5 zYW!ljWjGyA@B77eB@n#z{yhX7bAsPX+b#d+MsuAP1q(Kaqq?*$Jk`I7HXH~3fv4e> zbQ8JbzK}f#{|SC8WQ3Uq&6vmSURJf7cj{Rgf>r)G?s)JsG#u`RRW%%hd>98mH!{nx z*TJx>+z@~C_un!f*+DcD>=BL5*U#aLY|1^KiAm;fO8wUF$kJJFFrx{J+)dl|c7<6u`Rf z+id$^NqYAZKQl`%fuyU;IsY;N)w(#DzEoXD5}PF0ypy_|QR18u`EEH}x}*X&uCnIp za^2|G>~uKqa{_uaCR6uTSz_bEkySf;Ns#(X?x|Q0I4sbItY8t8ekjEaN?34?d=EAE z=LU3$u3%XS_n@?WF1(sDp36S4L*V6O1WI?W!3fPz&_A3n)Q3F0Wsrel&M7dX^Ei~m zpT@zy0Sh*W(0zYK!>*di+z&fBIx2k)JwLUMX~Y-dU%xb1(ys^=CbL<>s3n|; zZ9mCASdRZKQ784iMx4cC9qg@f_A38}m* zq;48BIDH>p*eSA!T0Vj)GzL=2!&#);2NJ*a2HEI;2ZxkO$Z{tK3{`6(PT|%#dBG!c zW$PrsIRPN_nMz+Lmyr`<(j?8X74?D%Cns1y)UT+p4ka<}Cxi(;*bCvcMhp8T@*W&l zT_W*gRWZ>v5e41Sbe|v+y7bgY@ag}f=sX;;eA_T=?=8DfR!XE4dGG5sDiM{?)K+PU zhKQ7v8IhGyQ6wvhi1)r84Gq!IuhO8XL_1BD>U+LF!Q*|#eO>2y92?=U(My~qdJtU- zf3v6va}?ej4+kC`NAKcE?AE$<_<-j@=85VN6S+v%(-RE8UP|)s`7=V}Cy{Wm*_Azc zdYO2oSVEAQGfrHvxlwG}GI(^e3857X|=Ckn$=FqD#3cBq}(Bu9$!Nojge_C1t z|LBDBS!-=F9B~1M`-;i8!dSF_rNG_4Gk_Krmzcoz7TW-qh!@Z6w!StO zXYbEkJkIcEu_`FV04t5AV!m=PY}RlC)o^7jW0Rp(v>&pj6u^eG z?aV_$l+H&0pm2n+*^>bd;B=-NUUZ zdvJq&KAeg!!LP+V;J-|R-?bSKomWF_2OZ`;92J`~F@R z?g%Pm^2=x9Ld^h-Z@Nz^C7!^qrJ<02p9g5sQK4t$6sU2uA@_E&3g0Q;W@x@~FObBvos;jNSjFxjqXS zy6=!GJ8aB%041i-$A1H{=Fcah9;wF#EQ~d{_~(WR%+PJaxpT6c>CTFvAyNO5Z4 z?&7djIc(^)=C0~Fqv^mP(H?6+EgTD&l%*v7_%n=N6}oYxrWWR9MB#`8o}GItcm%G= zyf_Y)>tolkSgz}q49D#?hB<2tx#_D!XvB;u&>>qa9N2z9C^fMP=B6vs#ox2x7r%G> z-W!O$(ard0o1|cCoRZKkun7Xz7_n=a|Kal^U9frBpRD&S2U&B5y4yHBd~YRYxNoIu z`h@e{6hr?uL~{09R-hH#glY+!p)~vmwvT&CrVYh`M3gGMxIU_J(a6itHG4pCC3u!# zKEwCu0z*O1sdj+4Hp;1k=lEe z%zRT6SU=IlBEt~!NT-jq+K0m1!yPPju`)Ovx`di1GQhyDUC|P|x_1Lq- zd%|H+4fHsDorR=V;N3h6m}fhQn}4XDE#L4TXkPQ>oYY?u7IK3%#_nb%lY`mYL+6-H zFS0F{GhowWfb_YNF!F;O*U9go;%$;)`SM(>u(ZSDPIK|e=%)hz)5q~+oGj;k)|#Y! z=q9mqd&n)T95$=n5bVDVvXB*~SiCbCTmoD1P>C$8dp`-Ex=u$gdJ8N=YcVa#%Rj`L@9!|Fa8 zxW3LGYEORax$ZJ`gH?7xG>=pxMpiWN5Aw=BB2C z>74t}5N(Go_g@gLAQ3Kmw-61MNn!ptCCt_uLv|#Kkgn~?!U)5UX!Rx#DN6}F$pPK}4S!#W1DxGYwue;W1#)v!^Kx%*^L4V`66~;34rT7&UVyu2ql{w7%fKcb+)n^Ajofn>-_5W|#3D3Qllc z>aEa5)tu|*UClqNd+^E4hgj3m4~p5>iBYRI`f<<5883BWHou!JUEhOV{~B>kWQ5RS z`xa>9zXy+KJZowktcKUtXW&3)C~RAIjX{fz@Q}hMc+T?&d#Bj5Pk|a-(EZgoHfR;h znXC;8j?2M2!t-o2>GRclrWtn*9Y zLyRFeJhXsiSQ^mG|NaB-SG;SDxq!ZV7Sw*N#jMaCIHQz`vOjFO{jwJH=5m19J4L9D zr8Cf9ze)MuIMlqaNnVW1K*`yOFzc{1o}K%UjXBKo(6r{WFTHNep?bXF@OMpIHti-p z(()o>s&3)DUDZt4Tn{Td^wGL%CXPuzh7SS(p04x8e!j0>7%+@_`Q7Y!=Qd_|{S$e& zHXl2}{c$IMf47cYhX2IJg6Kpci27bdW0pY_?5>anLwc;~b0YD+Ar0E*ui2i|ZqSc+ zVqYCaI9GE?(y84A>v}62bM3Ff@8O4R^Taj`&x}J+&VYTMlnLgp5hS_uT2oJX28NAD z09)RP*YvuZOn*9=m@LmCWe+k)iZS7~8zsQH?*}2`kPzJY&Pt-l46qxkMPrXlqDQ0U zaN&3{>i408G>{dzy{)NHe&sy;{q+v-wmAib1D$v`e2Di1}n)vVqoWi zS9WD%=Ds{EHdF?e&(9#y!V;4@Gb0Ao^G$jHQjChyf3K*BH=PgWkq5%0z5#1=P< zpHYOv_SRT*{3b4+wuD8W`v?We*X^HJXv5Pr3Xnw=xp8L=SbxM3<~Dd9gJ*_=Sm!P9 zsI7+^!V@Gk-5B0{kcM8qTm4J?3Z_&ja@7*`u%e+GEd!#!&gBdLong*>^cw;Ck?nl< zauQRVERSA+XUNPI_PDQRnDOf;aD6wI==br*nC=m1>=DUa#vX?|e(m<&1J)4mnCCNl zjS<=`k>S3?R|*!qxJ=p}JR!Y*exb9C5qs1<7A!iI;Fs|u&@Y-vrk{1i?sZw9JFXPk z^rzCmgxh3yfhyOMn@4W0bb?ox@3S{E#F^E?K+x(Bgx1FnLI=;~_}}~4%rSjB{>fTK zQai7~{Z${>gZcN#dodZlC-?&P@O+hHX+NN4y{J&qF&>n2)S&E$5uFq*!s+Q}!|JVR zXfZttqDQ2l@!M(=YCb@;bJs&(Q_HlCTKA{b(@C(;+!&XXl#|o%BVb{J7QAxa4P(FC zbI)4elBcs&amc@owY=B}m67@wdV7OVF;~()ZI22!q%IKLs^;BCqAqAO-xzDwreOG< znRMNgY>ce#h5sU&z@fzz@=PlUET2pw%?=>jJ_^G5xy9~E4bEv=0VrSCzy>=-xzHD$ zY?kI^c=a?9MlT5i=g~8;dTu;;PHMq9;i~+-dWyl#Q%t&H26p)IyVofPNcYljL~Euv zo%So4IZB(;gaV|jleL9UNk71^@f*_%PtvWJZ7D&o(w1EhKL^rrtaf^=I%sNUhL#3{H88qB4H z>aG$r?oT0UT$n|sSS2)3X3VU3v$3^b(4;E(_I@(F zz+RGZUV}MVeiHhvT!ahe$AX5+DJEB4j)$lGB_`Ebh%QR#q;`b_wg_RJPXpT?oP+=E zZDu9Sqd~?`jFYYYM24>Dq3q@3ct=r=6EX9JZL>=7rp6T;jz~VbkkKug-?O7ueJ+=T+^^~+Ean(#Tn=j(T6>`JX3vfngFIE z*vU$v)$@f!nD&m;TZ(Yv6|>+;X*B;GSi%DKkHgb{s|Cw^N^nNJE-cn}gGVY#++MDZ z3CxSwz;Zj>7_^?vOS;H&{!a?^VwA{%%qW3|di$f$Dve!hY;Wp!-Mi(jPXNC4glJ&f{F+hI*;7}=_y zMDjZ4LwBbi^#2ZlIjM@A_COY1ioOP0zi)zv)5Yku)F}|n`!-_x2$MCKfFAPPy*ZZicOgJrB<;>j=oxv{e64EoZQnYHKIub_%?(cmkJfHjn zE+v+u+-q;_JiU&)zvv;8$csTa=_4R6a{v??Ug8cHp8fblixy27PnRm^g9X)QdvE5U z*0{Tzdq*RY>8_x&fGJxn|12Aa-0B5Ymc%LVVK$Bf)Y>>rqf zU+3R}W81EPe6a?-d8eJ8?O#YwFDs-+U5&W$GuB{=hk!f2$bf^*lj#~CajrJ*HE1d+ zV}0v*{IpGj*_9NLRl~X9ReYKx&9&eTimajW2Cs2oqAFcDyPApf1b_iP<8n6KnDHB!oUhR^^Ek5!kFC(M52)J4UROKOANsp-xFihz%l``ZRNnwK6y;*e>}i=yJIu-x zr!@=21y@`ZxVg$k@Hu)E)zh`-x+`9y-|3BTFlIk-n{*I2R7g=1k^8Lv^K#naBEa$u zmQ5MSXi_e`wqa{+gJhhs1m~wY3<##WRV)RD0Z%H;nttN(G*I zWw?HX7zC;tqkhUda@@0!wDQijn5fgx?lG3BRjF{rt83Ys;iZC$g*lKt&JY~E86FL2 zM!5iK7&m1UO10=<^UOMsnw|^tx4qCz_7{j+3-LlwFLSIgp}Q3Xv}3U}celh9JZxhz z!{<6{l@R9^Rr-SWi6Gpm*@ka!)?s_+L~g>rJHpnBt~ev>8}W$j(rQ%>(FWF60YT6{6mg4c=&)i{Ta8B zzSnyPv!gO7i724<<1TZ*78RmFy$}5R^@p8Vl*(1CJ4Ne)vmo@$FUVDy4@Ja;qh1ZT z(j$q!$hM|lg-dA6pU3F>HJUE9Yy{5@p&)IciGHhPxa8WAob7}8v~Z;fmtwt@HWpOC z(d5%)xP2;AovFASg(B=9TOdu~roN4vngQ#0#L9Mg%(7RNb zdcMtq{dGHV-rv{Iap)bEG#&u6f>vy~K9Li5dI9&6FXGr7ekXLU0%e+t$o5I+VbQo* zf;t-+ZmiFBbR6`e>b5+0KqZNoFEOXO)m=iD^~=#j;s8For%3y~{=go37^_d-NAfG3 z-438Ib)ptmy7)NuMm}SE*ZJVg=f$w3s0Q0|67XndwqV!V7J=H9NyITqh6{_frd>~L zxSj3oAb#^A<~&Sfi?YVpw|k62-vbWZxY!j~u)G8A>}`hHF>mmq&VICfV8|JHC&Les z*{tLKPMj?I8ggF;aCS_I4sW#N?tYj}_O4im^gud^PyY?G209>OWE;Zh(Kz^+_tjO6 z2gSXs;7jEs?)||L^yh)gsN-A!GjqP;awl1CbG$pwJK}|cd*M(zCmm-fRgx8{J2516 z0T$Wvf8!J>D!wHSe~9*hONj_NuTz4tUwnw{m9R+;};O&q@lM@^9evck^YuiSq+R+RmlM3w9PhE$<6TiYK zwcGgLGJVePR*`*p)LOwMHv_y?YeDB&Ho^LmDjb$qLjN{D;dL$&2fq~xYFnD%pQ0g1 zmHZQirG9F1UaNqsz7$U}*GRXibWM7Q;xC*@WQN1a~9X3cEJ+h?^| zSXDQEnRpi66@-G{^gagGyTDX~$#l2VUOf0TAK$IfW)6Xc5S_{}aoa}dyO~PHRo}7i zP2NX-A5ImH>v>H2%dSD0cq8%Svq7I!{4mQUAN#y4`K|~ht+&R&Ja!C+7RR&V2}!W$ z$1wSIVOXe>{9c&gHWf<)dSSMEI){smneZTtrwXc(bO;o4yHv92j*-tp{ zS0$()?zO*m?mDKeOlGd1oMG-3AHnn2$I;W0pp9VxnU#B^u{}W%E~oSgC*I~=UGH9i z{J(wtY(tM7XzL)3Lp6A=|FM0M2!HnJE`hcJ1$ec|jMf*u1To!xV7Ehr?)juLZD3uj zFjPt()-3qPD*Erk{&6yJEIJgW{rNM?gKV5WE0^fK62pvZZ-~nG*=$hO3*vedx#^=@ zP*i6Jv5oQMcPcTkc3&8|^?4IE-B-lC;+L>}b*W&7-faARMhcJG@YnH?54TY+|8hML^gs+0eLu%Z(qmP7nO^2Cts5LilsWl7b$Nr9!{Dk+@jgoE@*` z=YRSof`i$~82Zfw8)v>0Y#J@bjj7|=^p`Dp-*gP-MvkYRDxo;}oib$D0%IrbAV{E# zJH5~0ML*taUl_?=_$dmfSTtWY5ad6-bzx#+aB&nGkjy!uBGo(f7AgLe^-%R2p3WhP_ z)OhYvjyZgt7)ST698Gs^tHOJtlsN75ps5CjV9gsVCYb5S74?tf=B*QO$`0=Iwxw1lDiu^mfF5MK`(z;zy$^Pa_!SU z;neHOEZnpo&)IdrsirE*)8# zv&i7fdbaT63Hs4l6qo-Sgxj~ZIT1}|5Rp4c|IL2O^c&j+VlODR{~kkMikHAUNj>fm zY^P^s4$?X8Mcibb`9FS2x3K0i-`L5P?>rlSp&IHk1)l>Sqs4aEa^PPUE2 z@@&+7zXIrmvlVP{pgg%$S4Ka+$i)7N68sme!M*l7&9lIc!_iyWSW-WhQ!q({9rY(+ zDJ~{oFT`>Z(rRe%%7&_V?u7sob-HWd6_UNb;I2tA;T`5wYg^n;;FsgOc$u0`wkzKWkcM4BRW4xg4@w7&V<1{4@B6ES&qfnYngy? zQiCMc@E|;ZG=t}*T!GhWGwdop$f~doY@*k&i&4J9 z^{&SSLC17q-o3eeufvC#ZLBAoTM98vq7>9J#*hi?Ka>2fY_!>Kio@@u=-MCS;Czxk z**!j=glcaPbCq834GNQ=#GY*(IA`(7c8BHG_T*!|7ZoCg~*Qm*$`Ti~JGERqG@iO@8XC%Jk=NH)p4Qq{kfZq-uvX*+`5qvO?tjL>(MM9Wvh_J`ol=dq)grjUaVn-hHX*ui z89Zw5hMRBs|I52{@c5UE?^Yg$6RvTBEt(ZDYh4M<|0KmNKK+f&aTk(huD@Blzb_K) zMphN(0i`Q{v+AEen9(RTmbZj|p2#=BeH_R7envxj(v9<)mS*sJ@knYuTZ%hSKblH8 z+2FC%Bk2E;=XSW>1PQH7h_&nzlqAOi*ZUmwt9O!dX4i;G^I9w^N+laNBw)IZH^yz; z$BJzClV6(En585`y`^M{@lg{h_gRt-L>UtQJRe+54&uxop%60SfPKC}A&F?%k5PIT zpkFD99NFIp10rUy{roI0uY3zrjy3}0tE-v5cp`}}C=!miQ4A8BG>L|X6SwZ}Be=V> zg-oyEx%-nY;(`ZD$iI*bwoFPC?0R(sw>7%Z476zI2~B+plL@$9@Hc*=MBySPR6B7>jEa)(F4r#Dr(yO(Cd z)$~X~>&FE`t+=tXrK8R=O(qamF32d;N#( zuHe~$7cJrX(e-f5vKo?qigWGu{7y1N9LpRvxi!yEGS2EX)-CvmANw+~(|lG_&y@ze z^pU_1{ctq+IfuOc>;-x8SD3+vM!rM)2L{ai8A(2Y=W};Kl7$_2>cb0|Qsj=Cl)H&Z z${m4e)G{oXQbwYc-7!Y2y77s8Dr~&e0ZFscz&S7&qg3LdFMA!D>KMc1;?EejhG##W z+yL_`7sGnb>1;=I3??hi$9rF-+3iwGy2wzTnu(6Z2c8qaCTRkE*r-WM;%4IsIZ<$Q zL40P?1nHSKu_JgNOv#ynCm$cis!NBl_39W%zJC#os-BRk-i64Sc%Z1upwPEJmi_xw z4MTPfU?i}n#czw@_|Z<*_9crByA|=@vLE634pETVxfkn&_u%oDM>t_bIJ3F%gE^k| z0QuaHi@dsPbiy7?>R9``F8vMcN2xkZnNmoc}O~?*|=Go`ui&XP@dHyr42#RjUzGu#usOEGKAKJEgJpx1s* zz-#w!;gZ?Gwr7NYi^?bqgA-I^(;;k z7e{R)b8c{vI(NfPg{zh?r?-`K*oz%yn0IQ9(CFfCNWXXphRTzu{Djfmu<>H>hX?S} zHbj_a=*qP<-i1{W^U!0=G;UgQC6P!P#YuJNGD-Q9aQLPHjD48~3#3-iciUdW2pbhJ zo@~#J3J#`~mqYNAnG;)ob_x9LSc@+uL&0^45tgdE(^GjALIWLXQd|g?UX8+uOWMG2 z+iP~kWDNDUC;-m~i8L&Y@81llaPQR0;P{mkw(RNzF7Dn6I-{VCeJId^q*o41Z1^Z0 zbS=R3Dm)wFRw7mNwxX-O-a`G=QgltQgPJBgdSlfY;hoL>kTm=VO`@b}$utFSLir#` zn&rhEn`2HFyFJ2HFY0jq3lsXwM3&QfIf@=;MyTDOMj>(@MEw^^n>rjht;3aYt8fe* z+hWIM`|_NXpC1bsac8Rd*02ABc&%0e-V9#dc3qwsuDiM_OMn?J{}pr_V9m z5f+EFGiH*_7hHrxsWaf8oEPoaOAuH+(u2EB$5~(0QbDKiJiaSv6YiBtOoKGoXLK z6?eT>1g~?;@v6oSgnBr}97JFhcC#f@;)i{Sh2R|#2(3**QrdDuA+6lvYL^&(3 z32=PPBA&nW1g7pWW%D9E;BN6KQh&#eIp2_`TVE+lrN zyY0^q0_WO)3I0wi#wn*u1?7kAA!WS*F4BC+riMMhcSD*gyFpsTHom8FgVWcWvB3es69b?_e%-P;c1^Yfk?tGoK@|IyepH=uW1VHfc=fsRq0$ zGbg@_;+X@_XiqvZm6XFw!B0I`o+-MC1ZnpQ{_tLBvN@WZ)KNwsv!i(7%R+RI^8taX z5?-{|M1LJoI{MTPls-O@o!GD!WcMVYTi-tzn{xrn`&ytj)E;C8#E9GO8}Q1qRCqQzqk~y|EMBYT7jL=Xcq1)sw10v z>)@6~F?-Wf#V;@<0gTQNpQbI~@R;X(DCyydzw)@I;|5dTAdSD*mqL^uY8N^*ysM}ox4tI)~&MKh)=@Oj+F0-I4^ zVW}0L$-1SAPAs0)NER?3)2$#8A4sOEWiqw9v+?fVIV`fIo6Sfa5IhRW!6a8;-ToP9 ztIftY0J0MV_KjBsPqLJ_ z9Zq+IPKq)(X@4nx*eb(?gqvZHS~R|Yl1lCrsnf;DeBM4mkve7-(} zobS=4x2OUgm-8D7=J>F2+b>{7=3D0ex{viA-2Jb2Od@|H+l(nXwMs@$OG>zS$jU_XXCizgrkLUIxuI4zZN*@$`GdXgX4&pGZsz z=7OUO*?dnWdb~^$>hk3A6O4c<`Xk|D_kC2;sz;N1QjKz-{b8|@AziScoA(!p(far& zg80A!ygcDPrqyL)u(mF)R7hoUgOg!$qATl+DuUgX%Jjqh(Kyp#E;j;1InCZcqAMdu zb(cB9Rgq*InsW&)W;Me4pQ_v;ziSYc&a z4tpO2rOj#Rt3asX#e>*!O@M(Kv$za-K2t4rf`*$k-HF^22W^u(k4j4*cQ1m>!~7M(}R;4r{<0)LvC00!djf1|jxbnjxCLX;LPxOtHSrp#Ha zOM%|XEu?AV2{Nv+8lO9PlVRg?g2MSCTuIX|a*ygU>$B20PXVq**9Nb%r+IL#itHH{Nx{OhQBWaV&gm2@m@Y;pq7l5OZ?}zx&R_bvXwZKer;a97W9SOvl@$b)j^=* zIh*)TI1c?mGhpC|5Sb)o{u-i8FM#ahKUK2wO9i?rzb$@NKwu> zrOSTi1T}c~DFLrzEbM7KBK)@GE1S{6^C6TqxmTWwq@eX0H2O_JcIzq$FP_0}2fIPz z#9#OhdU5FGPF#D!53V_Aa%YRW@Z`~VXk3wuQ~G7;@}y`em8Q@(Ar7s=Z8$;zk8Q2h?U53N>e{Gc&FVW2Ljvy{wt%kZmSU8YF1x zlUQ~z+8WjeA7NrY%FwtzguOg<1Roz>f(z$2bLva5E2)}GHvX$mq*DuKk(j{{&SBJS!J@ogHuv;WcziRIT3$}Who5C= z#4;VaM)5p;`KA=i zs#W6Djv3I=6JyYPs|_*t&t@g{{{%7$qltxUJqDO-Q!!sdPOn>yTf}!!ujz~8wm;kG zeuGRhaq$MyIcWqnjNx}3snZbY2s zUY>e@6UF4<-1<@U#_s^SJK2GA+vH58c(&4S7zv%jmvBzc5!ipglbhP7#C6Vmjc&Yq zHe}^!&OiMtE2f?LDuyR#XMk?a zTQ;LR0ajoKX*!vJoJgCpL=YAl^E+pc~Qx8eFaR=Mhnk6V`K8aoq z(~0$1RT`_UK%9mt*+czqt8! zBJrFy9$y}^;>`Bk5W19C;0KTr+_7Fj#(metic#&jUp|wJys;M!PmIJ|vtTl5=_7%; zOq@XOLNyi#@od+L^0-313sZZQkbgjhTSlMIZH3!PNAdGw4dy;4ll2N75RJ6k>?Hqvp1dXtGp2^(EV0wj z6tNW)UMkVm<@InlCl+*{q~X}H8zDxqh&?loM&BfB+`G5mKKhLdq+89S5@#=hx&9_{ z>z$BHvE{i&r$^8xt#&5nUWYr26d+~l6}F^#5+^yjl)Uih0)=xIv99Vb=w7l$+cWdw zP|j{}xEGJ5f4a%0M=tgoOJ>8~39aC<>7C$})jD{)+6HqOpJn>$A<#-nCrcNP78q@l zW?2bO@R>mx&b?Aj#;pHK;s?#hD=jlz&%1=`mW|^3ByuEkqBuIuJHf7-ZpM8*ouGIn zpE+i!U~0xN>%6SOeHv#VJYUoSrXff1;x1o7)IJxGYTL)w?^}wyGEMnB#5@@HPYXh> z#Y4&=RXjCp$DG`pu;S)f_U`vg;?{ncEK*E{ieVXy*9+$zfV}6aCZ;JYvPEdxvI)e_ z+F|6zN?<;c;6|TdL+_NzM=zHcWIR*8e z-eA3UDVW@EizNehP_3;3inZsG@&gya(JK?Lh$(Z!wbo!~E)RXnreaE-Hr%c05QO?i z3yZ#_qx+B>&pJKHX65HVZsd1x_8*Ux3nR$3d2_iF#jyehyS3=JyBOXGCxF{RbqI02 z#_|gv!-+Ye=(+PLxVPMA!mstrSV9!Pzq|`WBh!$3bA>#wkqiHA^J{2lF({brF5uBnt5uPnk22j&S z(k=#i>%0UBpO&yiUACy_xqxjwc?RDq^pWKaqruFOhcZ^}gi5CaWTU`}%z2UwCS@tbAd>n)Z&U2yI`Rz?@Q{GgB*>g z!v5y_?5KAllxnPoJJomDjT1(kTYL*K8J&W1^X9{b5g#zoTnkTz6$y0t9q7$xM{xPB zQXKgqncNiRcbZGpIHlNgEMe|R7&4OsZR6j#$>~34l{x_P#eDE|-VE>Ab?A&B=2y$HpGcsSm)$>}y2lr*!-9{6(L;nXm+_{q_8kM0nB=P;| z3=|#tiFj>Tf$RFWz~x^&G?Nn01YHH}wiEOX66Ss&3<&FH*Q+ zYZl(`_)OmSgpfJLek5|;Bse2G0hVluZ1U^>CX^yg!d!<^HuByQ5V>%R6UvCg^qDAc7Nc9|UnB5n9PMywCl6ngp^A71*|BvR`<$8&Au0<{QZyc~ z_5hoc^oS{MeuSM%a$)iFNho`zD%T#@L) zzsoh@TU{)svu=hH2eI{=BtELE6)dRyL`qZwG2(Rw-p#+sdR{Chp12pstv2Es)eGR- zyk{u)MiO=(&L?jM^B@A=kt)+_^IO>Kc4w8XC&{Bn*_9Aw^04Y zX2HW}4&XRLlHQ9u+vIUz5QZCM=}q}YCcUWx%Y$0TrNVUh9(Dva%6g!={#z_|XvK!L z^{8*T*S_BRA$U!rPJYaX9i>sQC^495d)2}B$4^+SGoOcxiUD=rLA)>K z7N*!c!YcPrjC`Jj^}eAjcwju#+iTJEh>wEJV#>7kg)H4%BEjWpd?Cl*{X$FIVA$$+ zjqUq+7yGtc6#Oh&#YGgZ*|#dbms(1z0-x3OWn9TD=D|)*9=;_aR_qKj*&Q-OrlgkKu&{awdjnb z(ccbYa8W!r@@XvDY=4eL=QGe)`k7=KD03CB&S6$YDcY`o4uNusm~`e4-iq+R?Tfs) zLdU;MBD{#zml<(im-gYg?_IF>;aS#Jy_8dGwBW>^Wn;@<|EBPSG&tUvk8#ID=sW&g z?p<4m{u;yJep-QEf0;s`aieH|P!`5b<$F>mcvtAr%dpDNftH@L!wI#C{QD^udZSIL zN54AghIU}nn@ZH==`+FS*W-pu`{;~GBjDRC5&GEoE3@KO2{whgkb3jKZ2$ZTwC8{& zr(4TEzvFG_iA^>5y;`1YSlkL;0((xSMS?sr{QxcjbVCx#(yn^?EfQF2mSjTTI`;R2+mP{#&)EE*?En_eZ6jXYb`EA$RN zI2nd3=O2QVvqzCP@@F7Kp{hOVbnX9OUYVVv(8wS^8Oud#RyBG*9;uL&wpu z^qm|A-O*x~7EXt_9nu)3y%|Pq^MjD-PsoR9vgrQrD289!gVlMWw5-CAPCYCMKj;6$ z;5QR!JSl>$vh|qL$6x1XYtejh3COfH6T|OUiCW1N?q}LdOh}Gqfof~9UuPx>z55*8 z8g=0OzLhw1^c7ebkKvZzc}mXoPs8vt8So*U3N*tlnS#9l<^4@*>z7)taMK1n60(s@ zc`<Ok2kmRYuZAr)X2vDi;Z#F$*J5YUQ_G1IhWjxQ09C#ejvGiFX50? zW|KlOpSf?ljFVTshDQ#@@OjZ3Af09~t}GRwPFhOqyg5|cbDKnrG@=n=(sb>bz4)tR zg|Im)7p_N+1*$K{g-ny9FRV?eP;Gkg?E3;m_I?Jp!jE3E?D4<_TnJNn$7<_0(&rbokDR&d^zx}bjJd3d_x zI*xaK2PV_Q1yYOn%)DwIH*YQPjE%YjUvJ9NWAcgQ`;Z1bJ-Px|YzotMK89AC>)7gF z03H@QF<@pX4o3IDwVva`-Zi$=t2q^eYra9)B6}Kg_6R$hoXpR~t_cP=$Wit$3nV`3 za&}?gag~BC4cz>mB&2-CXg=q;tB+FkPA@$0axS=6t8-?yCe*yJPjKxe?=+K2V7r%_ z;fE*p@#eGZ?9dYh++$%sB9M^DCs%(- z;@i+DNO?IP59!LYh5eCu+Rlcv5$VC+AO5U2aY$(O&m5a4kLH|5S;3ZWZ!CrBkSdZ5 z5%;P|`cFe{hyQh)DBh2DX2+1La|GWx$3VYfA10~#z~RybP-+~E4RieKGW+Jv@e1i0t(8wfj-2wGzjK=Jr~q;Gk@xASebUrdYB z-}N1j9qD54jMJcPO#|+fSxCx1hhW2tH^Qe|exTJK8`9=b3T8(w=#k(>utD=I8|Yg~ zlI>5iVtIL(B-l*>v&gM0>I+18o6Fw0PpPNf#l*Xcsi!P-F!&EUCxowXnQqJ$Rhb z1f7I+q{zRDw5EvBuf?O_cWW(v+%3z!n>4_pPA!4!pH;BWI0p7zs%A0g&%@jl{v6U@ z16$+nvUcP5(Erv3R?7beC;j(hbdegjzrBXY2QOp31G{1Ve*PY5S&zyhKXI!1S2*62 zg6h^E@Y>89xZy=P)CG0I{1qOsc|-!!)v?9v&uWOS1n(4eIl{h1j6=0sDWpRy1DeH4 z(A`Ll^Dnwf7I?1`F4J;`<})=IZ}AucjlQDDwTrlQ=_Y6!AxqGrW$^Zc1jpLm z!mw~QnXBsyi*5HHQLDjkdo|%wZ9Z(+H9(&DiPO)U?O?W~7y8D?;D*8>b5$isvkUMTu%FJ2QnO(w-1BT)hq z^kf!b^pApxtgrp+E7bxzZU^iNddQYm9wc#tH;8LSH}4`g<+FGXAoWuj8~aWg?v7dp z2EHYrpR|-Ie=NZTOJm8^ZKm9i%}IRR>PCiE-Y1F2t6BD1X=qj{X3b({_*pFjmx#N7 z_w+$8UJ04b$C!u2ZFzlEy4c2}RLvHohF%Zp0lv}ed z7atTC*0Qv1G4T0AI|g0cfbZU1fLGFHApa@~q~?DlYwxaw9owhTbU!n!-1!LpN6~rz zbNRh-+?GAE8$?6WP$AyuI*OKttTZ%e(pG7Hl9iQ&$Vf;?6b&lg=Q<5(AZef|Q5g*l zrBc-Q{{90V_YZIPIrnwFUeBk>*c7Ib}$x#oOVKdiZF2eP@2PT(9ri$+^`LeVY*$op3d3-#>q)yUI8QWoNzef6ZuKnBI1 zFOe{RYxH?&gbzB_lC>?8BxAG`+za1`89kC<7JmX1_PipqSu@*r;19{Wwi{oqzKAn> z7oh+CBjkjoCDuU{-c4ow|ypzxKu69I4}yo_p0LOr~k+qJq^+E;s?yD z#{w2_RD=_Iy&+fWA~T#P!xIgYM7|1NiQ}%j?ECUVcr@`n{FuEJS_f|te^j`|tmk{e zu_k?X{oy1yr}YGWY!27ob&4vdT$uOAALPd?5#II#Lll6 zsXrC+h1_aW;TEvpPlAt^N9*kbCNULh=(C=~y1{IH?ucNDQfyx8?om@n` z4(H=6CpYHdEudVtSirVe zZy=`~ouqimH2#n@ftF8 zMgO5KY?|g>I|=U@HDdIOmHgsHYrJ)LH1Xy7RP#b5wq0BU zszT-?1=GOnO({71bHY(qM&r3P!Kie%2tN*g25FbHh|zQdx@x%vW;m=si^;-%a@SOB zZup0f|5(sv=~{ey(+u1%a3=rhC}MXc$KR_>NQ7&z?Y|=>IA~D=(P;hw>xCn$|I`Ye zqqK*3-8heRe}Dh~e}jIIKZ{vM!_ZeUQS|+%E~~N{2@^s;62E0b@wKrlyw>O-4M#4s z%MmSX>gIFePuryFwil+l45UXIIm6vMOwKS)K5Hr`=EKjPOmva$QR(UKR3=|3Jw#1#RY)!egoZLf+E{2aGmjJqr4$PdKQ#ltJ6*aiYkj ztw`5Q#8<~3lkR>SrZFZE>iyE#k6S)wKK1?)P%fB(akCw0^%)sHv#3~H+wKTc><;nGZz9otg%e-W zrcU45JOK4IgZN^L1>AHEa~6r3 z5=>)n_o4mU*J8&}hv3sTV?IKJqQ}piaL_0T>iO4!ez-mja;+5ba!?LN{m8++cUD7` zK5!Sml9=lhtk>yA+RH^hNU>1MVACsJ}G`bYCp{4%_}DHyJenK+3_Fo+kFCW zCYdw!T5j8UJ|69jV|dsJ7l`dTP6ED3qw0cs92{qZwMrr6)Y}b^_T?n@4qr)|&)U(b zu--*;6&V_uqS%cJ~>q`yj`sY}ySQI;7aQ zxmIvC`Zri@y9L`W7C^>9OMJ2BGj1&#%& z*gd>-!3A2~JSmmb!ZnW!P;4tW$VE?}_l5?%X}gCB7i4(Cr#KYYkC+}~A`T7|Lrc>W z%vpI>$c9bb zu$EC=wF9@)`()TPRT|~gflG2n@t{p};e`4uP+MpNf&CZJX`wFJ-P#B*!nILLO%uA- zUBO}DA6Tu$cnBPCDSV?&0ha@|sJ3bfp8o!gZMrKEqFNG3W#KkRZmR>`Ji!kYu1Gcf zf=KXjU9!2RgGsL~WUaIFiM-Tt#KJ5(aeWxHw-n*2It31o{w%x#mFY{Pw{}pn>OK?_H=slECjXVs(N*gz>B)Hej=eP?j(iCTP6WFzc2 zzYSJQ350sA@}kTVHW#doa60`?H~WZS^rt+JR%d7 zyW+uUQzlcP%cg|%J{%&2)3=*Xzh3H|PLgOxStZ5hUnAC{(j z57glryE-&HA<0)3hT^g&L*8|<4(~lx=G8La$q)TPY|ov~uOG;byL0eMt~&10x((Z|hLioDq@hdsAe?oP z6PyZj8GW`JuA8Oek{=nc=?@ckNi~XP+9TLIyK5}Fi_p|no+#dNiTs>TK#JWyH(okEhO77W9i~ z9D6x7ja-bskAH(InU{?LmA>;pyr3|OmQC}=#j7nKVbc;4*%8HTluBV=qC8g&_>6aZ z$pL<=QNtp-$iuW+tIo}kEZUgr$y3w9V+)J))) z(3CGSd(92tvz}luyu=wF1s%KTnCjpQykKYu~eX*M7o_ z<$`Z7dm$|}{SW3Fci^^CeV!w0NZYm~k^g4SghwlHLg~U`+#_@cDg8K1yy!|3zHiOO zF_OJZE8w1Zc!eD}v>~n+n4Pna`(YM)z|2-evHSHpbWo=idu-ApqFBk8@2Nwe){$j@)Faq z*y*>e_J=}LtT@eF#EW25>0$g7@RlW&=73ZA>1%HNIgn!MgJ*aABjZkOXI7uaLaoah zFb=$pXT}TeO-F*mChukAKW&Alk?)wxpFOzy*Ah{|NeeVTcu(wh{41#vt;3}JXBgJ0 z#-zH-aNAdDT3)RH-|tn6C5I+poiOuK^W4BD*Quhax(e!@F#_$B;UGWA2Iw$5QHT0q zs$Uj|4QH~D#RNcH%W`(uX)&B^9)LUQOJQKK8V1D4qlEH#CRubE^Cf5FgNNy&O^t$Y z(ntm^<;%fio(KlMXXJ)=F?)SY8P|UsMxRLC6V=gG;6Ks^EWfYBG?&S!Clw~zI>wCK z(*QJHHxNzSui-7l1oraJa4tFeJ47xLz6IX?BNczDnCYT;k>n{el3;BGb`_!M+Nq0G zPy1NR8#Q7-A{)M+-T-B{Vu;4gHn_J~n+_T13;Dt&rqwZvVF(HueUW>pdo zui3D??gk7jk{0%m1K@#Z1G+b?zycFhV&I+tdydMGcwB)eUAJMPkTY2H%Yob~p9ltX zRk^_3e z7Ji!-{{wITE}}YQ4kQgwhPVa&r0a_k-DxfXRZ}Jr&8=_6_rylHQZ5$!gD&9D<3n)F z=VYuuR|v`R68Pi5UlwE8LcVpiU~S4QH2<5AthN!$nnGdaK*6odW5BjD5|?LsVxL%( z@7cQ(Ez>8JSsu8`M!su-@clyWdH8#rY|x12b8p&SKOjbl19PEiRhOt=wiW90I?0c* zCS-lhXVMdV1J?d6<3DA!?0%|C;&6x4^wzHqs4cLoItC z?J4@r6XxOa;kah$1a6d+O(q=4L&=tYShq2b%Km8-jd_tu-gd>)mmj5YmZv#4-?NcM zkP7_v!3rJ*^CSKd_&(YNF9|(2tL$GeeViO$(WFF= ztPEo3pW3m@EkDWzJ$j6LiWI2scp+!L|0@p76LAZ3W16;KhpVlWU^|@D`L``mc+t3s zpEa$6>c13DZT~{-J2YXh=UJ9M#h5R6dmJ>VCJl1d<%zO}{AGy1`*1h_o#uWp`Q$SI)9JF%-UJ})uz=vE8CUl zKa`>}yBfj5z?i4bUQHrPol!e=GkfXn56@JbQR#>cja3T9Hdz(!vsjY{en`Rr&RtM3 zUx@}Nn^N_HUYN93U@tzo1llrxZGY`NPhtd)(AV`F$bsee1lMpO6g_?k1MduhnIAXd z52ydgQpqpicgT}C2d2VL=Qfy<+eLhe?!#NFbMS837^ZvhDLND})S7w`AD0Ca{^U0? z9Df{kyiXVTn?@o@WvueQf3POo999)ZFk*8oPh3(S1^LCiy7Iq`CVA7_z4d?RP$^9*f_G*!aXqRH&};CME0 z@Iz5cu`&PEAk2t9G-Ax@0+iE{pc=k=;r7CIkUv%-%wvV#b)o@u=4jKm&3&Nz@I8z( zDM6NW25)%T}br<8FF~>1?KnqmhXqfsU1V;om3x1IZlu~qs zL~vuDyIo14f)0N_CkN8>NAgW?49c!vR3K|z>tVr%0bHq5nWwiaLGzir?1K9o^!nr} z9@-tjf?8uq$fa6x>~=KEZ=VJ>hIb&KTT<|h-oRM_^LeF88K}*D0E5;?LU+%2DjBg1 z^GeoX(eh*5=cOAMPEey(uUbGuc|5)omC$!d_rbKY5?zvIdGRKD(Y1F-lw5qE(EA%6 z**%I{*-sL^-2W7B+!(;eEA+AA`F`MMDEJ_g;zW;}me8IHb9wG+0@V`X2B_1Zt|XW|{tUO6b5=C2N?>?~_kx^_3r=5YPHhHj({I&)lOB4ACOzCv zJ2x-m_NNT#>x0k5p)N7JVwEgCXz`H*ub#lQ6z8D(Vhg@4(-MEqo`oxsf%&RL;uU(! zX48fQ?CP5#`a5(X{JrCjArc+73mVhWrF$iYss1Fv*0N|htc2VP6JcFhGK61IK-a)z zky)P_kO{Ae^$1D2HEIbTI7Ssqk_~7;oIVR(J4^g8D+W)!+KJgR%Jl3XNvdc4huAi+ zg89l%$=ONAVSCYee0fHV=jtevJi-P+#`ecc15A#gx z78#EmL<&?q@nGCHNDnv-6P^s<8wAFqqwuT`rb=Kztuua(_kj85{J>(-MQ9msPkhak zL=Sfe^WJY8VChMr?;iULUVM_{&U+8DxC#!|)t8Vhm4xs;r^T81r^x)IH8|lDW%ueM znAVdK&@<^R4A+?hrt=0;m&a*jmsAU!nw>)i&uS2DSo9ms3uS10lrJ_-JI&rL-34w1 zVHmvs1WtSMkzH|q1Xm}Nk^>)ZgMYuL;7)EJL+-}Hio_mv`}0_^lFkMHg-uu&6u@)L zW`Ob@L$1;y0e9gh8!I)QpVlb?Pe)mVuOoTN_0xQ9Q!w9ECr{PfHt{@@D_FeZ1S{-Q z5%LHvr62X;_^TLso_wI6*q^tglO_e?;DM8A@d_88%LiX730we37#I^%|^J#V!XB{PLLf#@4HLjYQrsPlNAZ4Hc6ll zD}`J3r$zVlj`CIKY-n+~1>8$C1zx4WTc1)IoO2(J8;hB2w<8o3xg$g;l2+g4Fxh7b%1cT zBwQ2rF8X}y!As3GXXckp8h4lYcnTb<-mB=eq79zx+kvTr%Aw(w4_1yU z2gB{M9M3zz+=KDNDDfPG?R<`T*L~n@VkG=gJI(x?oN@U3v!cEkO&B+jqTln|q91qk zuwKRhZe&`ambL`)jESIjXchT)QB~lw>k!9T#SrvHkv=&(j{P^TiLFzbM~U(`vge&0 zq#RTP)w2?KHTIk6%Hb)Pt<#CM`LBsYjqv;3avijV9>Tg7feEY|!HV`Yu{0CH=Il5C zcm7)Pkt1F~gGvOrG`aCt)0^N_)(?ECbpgzuT_J+42cMK5g$EX^;Lz3tAkBX;;k3XL zIqhC%J?IL^Kc9nLzxIQ6Mm%@A@*malQ>U@&dXPBG7wgAb(CtPceAQxO*yz!V8cTD~ z+-?vZ%MM`iv#ngFrIf8w5;KEPfu}de0E@MM;+Ias$7UwkN_Wg9Q-4%pb*k_?ZnQ*A zAwPLy++}k5?Jr0Z@;cV0_1G-A6Ln+;g0Jf#Xb`wjfkP(?t|k$$bkYRB0u#^{?l#sq zgtm@MKPuY6E~`e8KkcXB$1iC}^%mn}c`X|0Pz&Og5}dNA7D`5D zGxn=l=!Xm!zUkhQF|SoAE{;U2kDh#i=}h`BKwt~1&f+ICOu58_b2w38x1|Z)ir|~G z;NQYNc7LZC9We7A#+7LC*gwf^$RiGa?@k1TWF1_hdsnZ>F3Ig5{6lvhZFB)f>kfAE@#<3NwgI*BR1Mlf&#Z zl_8|yIqrI}3ZDorl&pesoWD^Ej^v$2k+cFXU9c4j#>Hde(^$}5yBJEeiV+M;MF#^t za9w~T)GHeCfeJxn&DhcCxX!&SOxU$tiOnV#5}feVu#3!1|1kCyX5f~#!)Uv7ok;tE z6Yp794)>38abU${aD^Z!x)ejkulGQ$Nz&AG{b(w?O&x3Yc!T-u>ui^?Jq}mg3**X% zpv4G*4NhfvU1|r*88?YBy%~o8{fQR^ul+1)JzWE>y+btmXD}f0qx61xAKLkTk{juWEa2TUf zLH0hm3%6dJhmd|%-gGt==Jn>1MS1h_^{Cxg(kj8;FZ~JIRc5epW}k5ACL1J|FTj8) zS0Jyeg1nudims|kg1>e;x@)V@u*WOlto&!e>zobsgHOWmsE6!bs3O0wUd1}BhVz`n zg>c|oFuK3~OzKv&FqKEcggKTGX*>S{2fRszbYp=BG^biLV!r~evkn43qfoSN4;F_j z=i;cN3-R%$cD(uEgxGV&W|-sj4lF`uvB#AX>|#YA`!_Wm{}}d>^gH43r&At+^yY~! zL`UH0mv2yM$Zy!_6%Eo)N(dI3(c)?uVl49sl7((a)734u15X5D@81{9>_#8#-1`@1 zmg~Z^=L<#8Y@Uif-8_faWgsr(^TzM%1dPvi+?g zNfockp^R@O7LimGUpX(X>r&*a@0Q@>ub0@mCP|$B>Ni}u9uS#Jf+;|b_}XepBvJhNq& zG%-_YSlQkgJ@8t(TXa&+4q{#eh@<01;>OUCwCKYjJSc>#2cE0I{Xs9tGV5ck_IxoUa+dyAeg~@(OWtKPdiE6`9oGhV(!^T?U=I=q!^CAO$Y=!UW zA{|tzor*P5o5^Rp5LWjfoE$v!OFZtR30S1tM z4SK*nN2_7?)|KE~EWuSlhFd14vva5F;X*_pT8wl-m0jV?wM_-Qx7Fj&FXv!D=y|bi zhj3;)w?p{qeiA1YNRK$@v6@gJXS4A+**5wVSu{D09qKoND3=6?!+vsi%SW--A4>L^ z$*^lnCgQ{DR5GP_B7OE~1n7Rv1xH~%btlvj-nUudycf;fMk*eLl6#Z@Yd54lDAZ2$io_#D05Qb=FmCyEGGaqGbT5AnQriE)j-auK zJ5BlOTi@Z8>pZ9zdJdMRTgA`R?8GNdX5s6z%2ey6A?@fFSd5jL5U_6;O&u-IA?XOV->Id*>D6-rYj}GqMi%3>wCB=5r?gF_jdykAN%3UEy0#wJ2n( z9F2NAl-Eqq5_rRzuzOk`6IYEQO@mDEzQtQmZJ7>nePN3*AXDrPSvh@8+KCyr?x-3mI6Bl?H@d{gO z3^BM*rp6lyzOO!VzOf1PY-4cSu~(uuR|?pyY8 zy{_nTceM{JvCoVqjZouWSHH2W+@~W4_h3~UQFl;PcCG^i7e7j+!L>2kew@|FmpaxxUb-{a`J(E#> z56Mf0z@bbj5TP)iSgs3p5`9>zdkM#X`y~2zj?iaMT-ef{#b|%=9NRWy4tN`EBc~4? zqR+NE;R)fL)i5^Nwo84x?ZjI|d}Dz=@)O6)@<-^RUEwB@ub)$PrSJ!C_EN#yo>3Uj zw&QBg4Wj&AvfO@QAQ^IX3c!t%%H+%lS;?0HbW3~>(I~pd=3NUXLoR7B&kMr6_x@T)s$IeQp6KEFE#pYfP=Kav zN0@Y>lLS2;jaE>C2QRAPXunW$+7LZkD%Xd zJDv-|KKix8Tj?Y$9NJ2D9+9WMZmkQa}>4Ry9T{_fQx{~1UL;1I?G;+&h zIX+O!!=nn#)Vfq~{Mf!0JbhYaJ>(IrSN_Jk=qOrp@)5qObcZi}Moj_@DC)ThfuRn zGk(_51qPLe;B!kAI?#LwR~6Vlflj+{!Wcb1yV;OtH9JF7$8|VfwF%vV%kg}T0-U=V zf}2iEqtX91@}KJ}dAU^@RQd}{gB1qc*5Mw+wUvS-J4%HUfCVjh5U=t?Y zg#OrWDXL^%AIKR?IRsDFPw&%gn;j~8laCS@d-}dLRQ4Q?D4R5;MUyzf36gp+bp8$ z!@fiJvqYTWJcdpq6rbD)LZ2&wSNqpFymBUrHGj2)h!^45>OGMUC>5jaOdY;{jVk1t zEAheQ3}%@0d3rkZHlM=B5hXS|-4fxx&vN!&R*840+d_U{imi-o6I6HV!l_z;8?R^w zNshBfsfh)~lfwj*bD?+Zc$l%Rh1hpiuq$0AY`<&=~ zVgc^XP5|jo`mlb;QhLf~5EsvRiQ@ZjVVh<*J7qLRq>}B6)6`ePzP1^3nz5K%nk)yy z&uu3UC4_lB%%+#ar7-{daADV?OST2N)dWGx!6*^LOibZIUMlm#lLluybps|XOcO2#X5+_$RymZ;tX~rFPOiCK3-ip zA3oeTh?A97nbg{o;9O)0{>%OmvdKYQGX1ys36j zvEee@`eFnM7tV<%WepP?Js+6<7&-oV_brqZ{9w9|lweHQTyUMFO)u;-5Y;Qcgyx08 zcsTPG%+N}Jmgae=a{V||oD$C0us)_8TMxEx^aU*E6nwLev2CNn%A|M53cbT(yr|a+ z6P6p;TB;0%S2ojdiAa@w+q?tP){Y=nz4|ai*!9-#N(PyNiCF1=o*WE14f)w$SiQXj z-4)ykrz6@$i?d|7*u)M>t+YV)^9ry_74{vj$Hj33MtZ5k6th9ykEt)U26e(HQ?o{sp~z7bfPBRG$8?z0IATDU|%2-mh8gUE$4 zU^st2**W6{+vrx0Bg|SwC#@cq#mg(>mF-8sdv_A*nf+nsbHrq}VGP;X_!ON^L|{O5 zAWGybqVJD!g7Y{9#|kVMQ}6AdKO_s%rA~=IuDT>%^q0^}4#M4hNhxl79)hJSUqZcI zGE3g5%8wNuCF7#XF?X{SK1&&o_ot4;N~Hu;&XD4Ns-Cg4%TqCcw3D53rsS;qBVro6 z5)WLdCk_tQC@J!XoRmDWPa{%1w?>uP-w8wE0?Sq$kmN6Qs>yr{fo-r>&#up8JKY8< z@F+Zv?y?+*@=fI|RXr6?tr^aIG%w<#Ntw9lng<_h77r;ir{Tk5GrrbqCp>Jv30yRh z$LlWwV{cO+2NH>gxi#-@U4|EY&*EGa4}hsNFka&Ux-`wF-A5cLF*uJY!-Q_o!k6eP zy@*X$jp9)nUR3hJaM0UjMDzZ$qxY_gLFS|wRSo;mE!TwRhWuvh!V@twMwxzD7DoM} zB&lzF3kJN%C8jIh!N^<7`FQ;~;L)H0XHwK~OjIGWHd3JNx|Y<~O_LtTUya@Z8}j6k zb!gzB%y$XT+FUc0B`;5h9Tj6~>3bEbQB2`|(J=ZT%8tiO_zCvc+wg_JY}h=*mz_T2 z#l=(ZfuG!ch|jKvFYApVS7$X#-7}3t55qO%kMNU&Q{e5?(=-o#X=b7=&3!cwUKiNV z5^$vZMZ4&J{Y*C3VKxu@5C)TKhG6Ra*Kq1OaP<@)R%w!paeDKpzkLor(>8|AfBA^4 zK4D1*q$MGwHo^%_T{?C3X#Sx2A~E*-fXhTlEN+>n;PS15mT}P_f7p-~bicx7`Ag_s za}|2Q&={Vb|HtlkFU8)g2ZZcYFb?{u#D<)1CQbs5OgyLq?+$k*_7eliB#9zcJSPH= z70$w!Or7?-_ zf$}**RFaZm)7^s*IF_-Y0aqdANvOa=sDp=1^sRA0#f9$TWo9SQ^vV~~)wlt?zh8m26?PzZb1J>E+lb!vGR7!rcmAZ{ zI%K@QO&sHu=@bb!9GBdQCQp-Cfny;04p@n)w{?X%nvlN@vlh5tuH5J*p&xz=4#ciH zoc885a@ls6WuZn_KL5^o9fe*{^)eD_JCYB*m(D!SJt1?wFF~!23b{Tin~jP>(cgip znT1mVH}JyNELEd&bWI|G)DXCGHBB0 z&A&y=s(d|k`WeBh4FZ_vU$ ztJ7fZiyJUGJqMK+OcyObQ_oaGb-1$LevxFt9S}c_2Jx!~pqTo{eQz9@9UmZiA zq)Wu~h#qE)$*|So!S_M9$SZ=) zzCMaYMIIql-m&C#)+3w2TPEOZ?{jdWaV!}14u#pd$>KPBSF*oN4IItF*g@^fcuuTC zzrDXp{FpaXO-#dOj+bEQvrN(8*Z;sMS{0R>6JUnwS|~AZ5m@`>#6!{@7nSc6hlJk3 zV|x|x{o5O~l{DEH!<>A?{Q=;-WD*S2oRq{#L zsT|If$01IMEXwRLaeY_fFlci5HON-?=e1SeySR5#tH0>wY>|O`%OSRFuPhb@E zWk{|I&2h&+SW7c$_gBCuLZoe){|K= zZs7gui+FqHFzPU+Q@r-iK+F$PqfUNtXx?d%*ptp2l7)Hn zlnfTXC6OFi5`b&JhL8@mTq3`61&bEkf~y6V-P5oGwg%7NiD!>FOIo$Qh+%gQj&?T3 zZ-v1)!naQJ?zjSN+)_>UYOjMwqYuE6wZEX`-2m*XGAEOD$AL+C35MODfC+`hkX#1r0zc@leOx=pdw0~-xC2P+FrPNQU;qo zxqwXXdyf-_A7jc5$BD+=81VRW2?pQ&iNE!RW3&&!i#igJsA5L^Ju;zPI)fao9fhjb zGSlP{F@a{~+yLTM0EWiT%i@nHCGYS`- z)Q8BxR2DU{Q1nGV1yx_B!KJmCnCCW_N$gLASM(@-3>IrvmHF&ABz{(|iCd}{l29S0 zd+)H{4=)kPUJu+KG6ENv%mky8Ex4*I?VJ4O(roh;@KM2GIiRG&m zF{0QVldPYC+~6qoWk-5Y#_DV3FNA;-CAL zVjGQzi7Ap|cN2e1oL<7}k64p!M2#DcZ4zB@%qKnBieysUYT7t^DRg~$Mk=&Y@GBdL zp>qvM)sAhLkSdEK1g1r{SooV4TfjQ?nsBeo0Nqh`d}qW^2$kUA6_SU?zH9ULHH)C$ z=`^!0|0HfTlgI0{0rUc&lOf7+Y~6-0tXa8@si`E3lCLZjdQoC=Nno+)+QehbwDTIw z|2csy@EgwO4s3!6vWr1gVEp^PE+IkJwxCR9sIce!W*cp0h$>pLu)OmG)Ov-JY^PfM zG2u4YL~3E9ggd6ax-KrfE6iv-=OHnaXG=!N60k@j1EX)E^pRZnaJsLo@%0(_Z6M5N zk1m7JdR=106KXL3wlr-N-n}Z`*9m&pkW|b0uy{v_Ay2zcVbP!ipkUo-+xBN5PYrE= z#$~pA_x*(+HDVX0RerMZ&A3t)|3s3ux(uaeArqH=~V0xli zj12}(^rrPU__%BYx2+1n7OfhnihT!99Td^{izAgPGldmpAIg*$>(X6bt~5yRGz`Vd zFvKzm!(8AKM?cvQUj-Idx~Kz2o)NhDMrUBm=sL7nn?($S%UNumGN+#vsl3lp zUVmNqX0Xdf_xwrZpJx-M$-TpY=YL}T4a#FW44C&)FM55L5;c%{f?n1Zbc4VkI##ue zcbJc(hL)qa<>NjmoA4W68Xd$ge|f&i=o)+4Kb8*NxeH86-e8>N3ane-20iaO*-+gO z>|8&EUVwq%EqIdc4#@H2LZ&<0LxoSsoJrH?ghAv5HJWn2Qq=H3hnXa3@Oe%_qM7-3 zP-8?CE}O3^p1L8%W?61JTeQ}cj@a0S|F*Wn-lZ-0Yl;%J?$MW&Z#~IRm-0|-M#M|H(p-z`Jj)MfN5v2dVEDpFj0%Nk3d2z4|ny;V1Vy|bD!j@ui+xQJV z+6+a^Cy;E5_#yWAbQMo_`C`_MwRos@FxL87i!st))aG^*l0RyoqW4oglQ9G&y~bi) z!vb`6O^5L3(YWK23XYidj*Q;A9^Z`H%|a~8QEtmRSUDm9QXx6>Q(FKqHcJnfvP+_;e&5MhW+*m(PyC z#O6(yaZq?yOq)#KHH^l(Gijg`DMONXBL$#gNM`OHRbdwE_O<|{pS1<=vb&=er&7k}~mUQLM!2I{V7-Tb%XiwDz z{aZcEN9!ug{Naj)v9~a-Ae*fIRfh{#bYRGYi_Ao7FdY393Qlts!Q_;!_+5=Yo4zI) zUCTVMYsPu@dVeH&w<(i685u708?aw+OE7J_D`!cbHYeNqA3FiHzeDR6SS> z(Lq}v^T<`a(9yvTFfktMjlgvWp0YJ_YG9Yq3=DR9jH=T*!1q)LhD{wnou38c zmx-sC>ZOHXRpSPFnuB=WMsM-En;y98)nRhOSdqfvcB18w4YQ8du?X=ngSH?-~nN7{5uqsG_CN4j13wre*?QJuGl8DIpN<&X?X8i5We*ZB46^Y6T62*K5he~_gOL7^*!)xnF3w4_z_5SU&fP$)==?%D*Uqu zL$kE8s2m%@`r9Ac-aAuui-R$mHZrM0M)O=Fm}>g za(nG~JSMh6Q_GdGvgI(k|L4I%6rA}nVUM%JgBB0lbrKA1*2GCCe5bh8r7_ z!N5fdbwBI`rF_AIHRKn>JUUJu{=AC)6JN0piHRVW6e_Mu7aRzC)(Y(VG@NN$gEMw( z@OR4wfW@kZ{H?2+}{bJ0*rB^pY_PlG7!iTZv20530|=YGHUobx&FcL>dXID~m& z0!Vmi!dBjRDctO84T5AL_wU&TdhX^X>ZEH0YZscJ!ubD4_~dC^ORgN;Y2Sgmiw($o z+u@|)(sU4{90ltLpp$iuLvEiIx5I4(S<`f%NIgsxa*M}wP@rVBEv()LRAw05l$Ax|hf>Hc@@6(SC zfy;hv=KS25zOnIyYrI2@ZJ7dc-{+G<4IA)WzY(Y2oWd?rZ& zKJH3}b<6sp`Byc0)J;TVQ3A?$Y{yHHWAFgaZ9E@k3iiJHV3yu#eEdkBd7EjVW=#S9 zxjqbz8W_TcIwX}F-H}C)1MA-=7`P$|9`=vLF=u0O?#^Q9$j(Hig+=7{i914=cmSND7*p9_aac)GX)l?$KZ!%zDE|kgVtU7 zf+bsu!S5}fy?j(e0{+I~C70`{dLR;2a-NV?H5%x6AdDOs*D5k_l*g-Q!_ZlF9`=cy z#Pq|iIJLeLE?qh-8nxVwrraFORqyx27Y0}9qWnO*E~%T;^Y@(0*>6P2_tGJJTNH$D z&!cZ2ok2~WS@C3TH4OIZLxR~`)Sonyyxqxj1f56H6~ouyqUHy1>XSJ>H_Ha&$-8ir zmN9p*!3OkujM4c?8yuCECRZj!K?Hv&_rJCvS>HVH-+yj6{J%}~$n6wd5@tbG%zZ;2 zdHa!f^S40}k>w7I|BlCR9iT2I%Y^k$3Q6%QcOfsOg%@p6aIb7Rxh}bgxuicp$8v2n zKg;KidB?Wmy$4jnBLhO)p2Ju*W1(JVGJHQ-fz8%;!An?)VOkNeuf+207gGI0C`OIeY^u9u(#3Ff?(_Jd_yOBD^>vOJZ zCirytf5KADe28DV8NX^x=cZ)OV^^)l;F-zaFzaj#_0ld9o-UgUf(T29-1~^;c^}8P zCyaNHmJ*BNw?q{E7PqeaBuXmWPHUPPQD12xPMCcU=al^gU#Cc@`*BB9I6RHUTzyF; zOON69^vUFe^Ix+3Zao-eG~<--*XjD(yJ41P5RSK>j29343x{RN;wZOr(A~^)z^5D` z+XH4`aNiZ&`8prpB=eHguPez-K4+_tF$k-6r{a+jHMnm3DQFGX#+UmHQF?_L`fDAh zizf_1-K={!_0TwO=+<+x!`A?2Y}4TSmTar8F&aUrVh=9-C_;#EMb9l`IOW~vVem&D zjkH>eU)%10Lv1XCzqbI>FkMdWZ$3P~;Q*)2C!knq7liE*QK#~JVS2h7wZGR&TFPYk z{<$$*zvmMyetnjnD|DdCCZ|ICy^%~Hr^3~Y5HS0H^D+3~D4b`$gJ?VF2#u`|V#Lp{ z95Y3f7&k*{30In^( z1U*qC%MlwB{%Uti2Ab(9jTvS)B-?MfE1xq~~> z(gQ!-UqJhbI4TkT10KkXVlTN_cwXm^;F!MzcI>N$_Eab6?9gZKFN0At#(~o>TgpCo zu47f++nBS?Ml{^mO%^O#&nl06g8nf&>|UcKXMekji|xFM&-@Q?1rHz64R<#&fBr7w zDenVcg643p50YTtJ`+xRy8=6Pe-5{7_$F?u1@8|0C5GOQYPqeOWVx!^ItauRmSck}JyW{#n98UTlV{R#Wz7{VDF?I4v$#BZlKHUc*0D>f9mC6!>^XpZ%Hl zk}izsgYg9;gq8nkaOx+_x$=bu>RS7rYJOb}9U3}V)vHRk98JNVcrkw8-I`6e>ZMU8{4>))$dyYx zAPY;(*}m8aI6%+RpI5$+^$UXOtA%56uizM&{z{+w=h=w$a{g$Ocnqb+e#V9FdvVW6 zU8wd8#MUiAc>RVXzr!#{d&oOcU|bHqoVXhU9*IbAP?bn*S|^mxP6bW*Z_pk(4Y{B& z@*$0H!OZ&%rtP0-dCgAr7n6m~A2Z>rnP*z2L;F8*I2PyAQEz#kj_*I%!81&9 z$|O0v+i9>>^NLVc5dJi*PB)Lz&zL0;%mZG?fBwYUBj9=ocP-$lauIBfCo$jY1 zRkmmMwN7H)hIOJj4>q9Y7%?bZYQjC?G`MTZzL4H@f@^v_pKZIh2>eH1fU^B(IBV%h zm>ep>EuUhJ)6ZwXyNtKsv%y7}UzLCt(~omgOozZrZ5%hQ;uz!ygyFcl5nSG&13us? zai#1rt}Rg)rOs@HFJ9`XXq8=~=o>7$)<9UX=S&QLyM|iDA4j#%t8kM16r6qQ6r>pi z2$NTC$B4i*teQ3oFZHLhyWU^;=UOS+%(Y?P`loW+Zw0gV^Ota%sU5eVeLNR0<-og= zYfx(`!|D7U-_C#i5PokD?OzlL-kJ*B>)*@SkzfCjsVZq$R%nZgYC9=4P~skZW!6H#5RsaQoo_Q4(noJi`*( z9!vpye>Z4~}> zg_)SPxEm_Q+QIG5*;JzR99+K;3JET)BzR2}Zk+oQ#JAf)mPZpgtdl4**u4P%c zHM7Bea2^fEnVh98!j)VP-mfCZmM?1+7!?NMf7@5mQD&!*itBJ~hL_-yq8-E)oP%KA zGuCxXnX7VgNB!A5K+S3l8#5ylepsA_bD5*rm&{6N5*I+^S1H`Ru>lkmM}vk(G7L{W zPUY>-!4lJO*w%3q58Q}EsWJ)l=edV_XDZOJo<w;jUed64l0ZDjX_8nv^blIX!iJ%>S zkZDSq!V8bvIBn=KU3YOKY(w>(C&-6b*fgGe8AQX1*8r!zs^WCqVHJp~U8 zw^Cv5T(Dav!Mh|T&{lTUvNr> zG^g6IiMwW`#0FKSV|MX0xGU-e_E#ImJ>1N$7g8LwbZ6_%=8`qXs>vd)II`5`HdgX? zm)wO(T>fz->T_)y+g~@DehQh&Houo-=3zRPA2u}-jh#d|T@=L*Sg=|g(0TKDLC8uC_QY`_4pg3j7ZVjx!Y&<_ z3{zl!v+lvG!bdRYbPH(^li})JR>A&%DSG*0$*gpPSa8hjX_v;#L|B#C&VW#{D-+?PG z3gmbF4cNU^_JR)6Hkcocai0^frFDkV1ZZz`6DOK}>ScR~EX z20j;(3EOwHW9C?C*mXM{o_+p^xrD)$@S|-1xD#;X(_U1(G=_LA9*O;7YjB(Sbk@2y z9UgWa<@yhfVdr%&2^}*gR1N<%j&m+{WWU`uvkiaGuswg~af$bz!uG|J*?<40bF;0K zn9ZX=u3lN3^>{uO#{C?}d9RYe{lhr+YqJOUa{3*7(k0*)_lmQcr!R^5eJ|K~1<%iF7o=$6NvdZhJ9V*ip_3&upm+mt~;o}=@Y+kQ1chDPq)NqL*A1& ztC4sp70~>~ZeiMn7nmiv47Ws=(8q>*z-7WKSX5ervim|nu0{oG|E3d9dXmouU&VmG z`Sh#iCHQx1G4a!tfrC76?=ycUROH9tiIIV5HgFMSNBhC>UrEAKmMS=Gt2{UU-ElB% z)u-2Xgn{nJDxxSYM&9^;2D~PO{N>5;t8*0hH%ftbmyhJW7Vg1~D}%t|sl#ch; zjuxe^eurgitogH2MW!Yt(nBBD3&qymAgTVXv}2(d8^1?}_2pE;uI)$Q>!zKwT6UE1 z%g*0qFnkWmpLc}li+%8RuPn21odJ2?ayabVZaCn(4HD{lgg=I_LSNzwuX+MuZF4TQ zw%v*jhhLC2gZ<>n+Y~G(X*9WRD?KD$41x^{$&`-E@JX)-BL$P04fJ`<1;nOg3X5*bqgA3He*Gl-u11g(voF)iOQ~@CVivp*1(6$td&zY^12rwc027x|p^m~M zvijj<^q(kB|BS98yJjas_@oqazD*D27Rqtk&uOzI-&CNm!U1MCt8)%{WAIt?Ud%-W zP~I~{59EYXi$^Xnbr-+)zd{`Zsw;?h(+%PNE@fi*Uk)fwb0)6}%W?g;i>UAL80PO# zf*Uu+(z^9KadWB@Zf!0F$7?}&ynxTw9%}<7gDf(q<~>Y0tw;{~7SNqeQn+wMGVSn6 z1u@P8T4Ky#+TC4P@?#x!U8PO`dzOT&^f!P@={dZZUrIy;9>U@bhU=|5MbkB-aZ{8e zyjyw`sqm-B^Fuo|_DH~KztoAURjsIX_jnxI>I<>OLufzyG!^zQBol3Uhl_72?cm3% zqg8LCN5?3xW%@AU9pDPq`=w!#hbpI5wFCSVr-)i#apeAtnIslRLcl*A$c~7F72ibo z{emR7WWgA$O(++>8QOqi73$#8oF=-WxBzq{UQo%j{opJ#BaerT!*;!NcvrcaOiGer zL$i!|#)}9Yr}4d=vS{ke&+5!)*Ao@E3SZ-EP@pY>w}Bp5|Cc`#Z?-{vMiZYiHbc{Y zt6(1Qf$CRe=o*krz04lcTkbD~re+s}cH%sv;Qne%RtHJT32gxS+ z;ryNdBnF)w&pWk70EwJ|*7RgeppOr1v7Lq=6?WoOt><{bJr0Wx-9_)#$rxRq2+Ie` zNV^Qf;D2{;`qs-(_v$6;S|^AM`CJ$en8oNcq}B@etK#^c-)0FNVfp^$qB~jF=u>xJ zXxe)lloE$==R?edGUFPc^!FOxWAqD-*M_1&K`;(({VBR!t0LO=Ll>)`tD#3r8!k06 z!_t7Y!>%c2q*gXPMBAZBHnjy})lY*rgirn`_fwc777b5@EmPlv_ zYF^zvjgDp~;rpudm=HgTZCn!s4&g_jMEMLk_~8lpW=23W#*Dw?j|BZ*X`ZWR2yx$e z7XZ&ut+%S?om{s_;|Oh>!LvC zlfGi{hdc=XdLEx=+|DFgF>jW@X6-iLc!!|^oxr$%wC&Fo6UPfpW1kb@9mXfSEj-)$G^j^a=ql* z%7p^6q&l+cu#ae;+sm5h)xFfGB@*0DR)Bj^IZ@e?j$uYqQO+tD9r7i(lWEFeY!`;3 z`TZfawfo57uZ4okqgRm2)1{eP^JLUs@E>e#&d0R;<+LDfC9b}_0v^2P^L{^%;g&Qr zx@_nYP8t}b(Uz9f?Cwc?*icEv#vFkv%L_1;zlWF|pG;ksRSTU;r*hByDRoo%N~TN_ zho@W;%=XtnYm-sTYn2dQ`8R@D-bCBB89l10Zgm*It6Gx=ND1060iVJLJm7OWZz zpXXWP+QH8#KmQ3m$8!;<+Wno!Ys1~OClnt3a^5n4&K+C}h0W*xbaRV~`!ewGea20?`I0EWAmp0sI*s5^g*56O`=7!v$Iak6rRmxABvZ zgLX6?a||bqHlz;a^+axMk0@X67Bvc70q-ZiM6vAxGQqGNa%Q@Leq9OJt~d$yd~fD} zRv^_>)WO7HBal35#m|8%!BO}QvzAUpJDC>zqc;*AZ9}P2VIyq%sRmabwSu<)2{72Y z8Eix`5OdlHjMmu052;Of#CbL-%Ng@On*FgumlogMwR7a9S7tHxRk)xzN_#1aZ~dIiR21=IZP z-J*15DOPu21)j}m!~?bbGiP-Hjuby5OkH1!hBTV`9hHTgac7`#j|FG>wi176P5_x3 zoAI7jE4JROfcOhpV5A#PZbV+A7OB!OJt2qE)IjbI)%u0*D{nw?-s<}9 z#dt1dtp$`$bftxxgQ%9WH;hg=DSAGl0ER|y#(25oBH!h@T%h+>^5CHwOr4fSzvza5 zMv4rapeHRFOb+!x!`6j#+P+M%2oi(Z#^1E_<{S*TMbOM4HYKGyWM;1XC&buvc>?#B=o6~5(Ix*jFJ-8oCfu=k& zsM;EhvxSRr}$m?uA{ML!Lg%Q$??xA^|QG1X#+j8HW07w)n%#SnIhBk zH6rV#>u8)j0Y@8+hdn0@$<~15@MfnPOurmKS2cbVRhGxzK(>L>p&f;`by+diu(p@MY6^R{n zjZodW4Iho$fJ)zuAi{F9C|XJdoKF$ykg zZH2sV1z2&_opyg266W|N;cn|oc<$ah(#r25*{xVdgo)m4)YVp;hfXYkx7< zV35o%7wlnKy(8G{aXdfQaW1`j_c?fukzxPFw{Y4g)!Ey#$C&+$VeI&{d609&fa_6~ z;cJKW{4M~Wbw5^(%GtU6ySx~V^4zw*pg`Q;t<2Q?rE&4u3b_CHGeYWbV(Y(^**0`T zyr&}#*tZ1pe~o6dX+B-QLI$JY9SHyNytU0**wz#ZB`ZtueE%cZK6X57Brm~n+el^* zVa+O3u0!Rraa>u<9nhHgk@&r=gqA}|;3hB0S?s(|>{_(h!l^ne%{`GDi|d14=HA#?n8N!8PYzO=0Y9 zJXt5gR~F_ZVow(N+HS~Hm1}TcvK?;zs)5^-USPUnK9Lyx3qxDhpxi$V#LR!#w>1i$ zc3c$=?nuJc>2et6cmPg4@+MXDEphn0Jb`iRBNCYv!~!L45Wf9~9}j=QO^wH}+0h8| zABJM`8WFUm93wAMY>Djg@!a~0x1d_i8OxmkR0D2P)m%x@OI2ksvmS%>-*d@N^_lQy zL^`c8=DmCei@|D1xxnqW0xm1pg)Ze(Qa)1#O&=}?w+FpwbJ`zXp(0*?>j($WZWHX@ zrNeWwaxt~!H*x7d1k*bA!`g38$oBhEBBzS?HEH*}>7kn2Ae_p-n`>SHzBqtxpPWh3 zT@zw(!47iQKcZsI|6rPC6G$1x(;ZekQ-JTi9MQYX&lEgy@vtP29mZ!>0xnTD>Ly9( z{EhQdPGJ6s=j5@`TcP}@`9$%%G41brOQei~ML}x1OfGyjey%Bo?p?2i_2Z3@wMF7z zzMlS%Wl@RFSHzU_qc{0Ez1#X_sJwlU_`a6oqJ&FnNq+=6b);F~aTD?A5_~ZACPv5$xa2kqPGy=qX%K*LQ_gYN`PK@Q24}MGv5zrS^$^rw zPDNRVu}tk*91x8_PQ^2n?SbLUI$=C#l`6;OJh?3BEJl12eFispv_t8XyVQEkca;CK zfZOg74VCL7z~%ZN1bYJZ4A*88@9}ryGZwI7lR3+4Tga)W+JjyCiJAlaT*zDU6fscT z%!U>@!jQ%a#JQU6zq9gW``&XnGoTW+*NJiSUCrTiuQc~oeh}@3yqWNtD-&v;z{a^2 zY{hGP41Ya@mP%$^2w$tqt_egz%P^~561H6V`ZCc@M3e?_hNtZcU1+9{1DBC2iyk`+Ow%)li2)X{LE3NKC-rE9G0$$<15qWf*_9D!)w8Vp$&;Rc| z@tx{uy7tdAC@&CTch~_kZq6U@UhqXUW`q$={xbn~?_5#yIXM%y`igk*+oq*{X-!3GYQxx-2rMAdTiIMM0^#I zPA0rOOBBz@u~&0sxp>3d%zbSor*hs2UA2<1`KBrtF=IdE`Ly8Weo4&RCgk??e8&L& zBkXEjGw+GcgZ#s%;oH{DT>3u=?m^ip5@2Lo6aUMZjT+qxrvzizy$@eVnQRbd)f;g= zJ9{zJR*b9M`E=19i9V*<4WpCkh*J+Yj{{wIAJIT+&?Qrbm?f8=va8er5 zY|9MWf?n_vW<{5^yrP9Mp|&&?20Iho}?-ozH(T21Fgrg8#zPfn#i7Chc6;F6&b z)Ywhi^d_DeUhW<>;r)4VG#;1RemeRic&n==e&px0m_a&A#)M;=V(^!#$r$)y{$ z-0DS(mh3{4=M^;jdosRWHT9hZ!O$rjz@xui2aRYpk$K`gS&a0 z)Js(^;g>mdIHvGlsvT``nY&v{;lM4|~K7pgyD45S2VP4Za`q3txbijCwvj`OJm^TS8-*llV zK2uQYq!=fDdLt3n3#TPY4`~45Gt_lXT$m;bKhMg;fuocitQ2Q9WCQ-;V>!*IH*&AE z-;nj8WpG#S37X7W%pNbA0AIHmvntzLG`wF2?4GUYJHWy0mUC7vts1TH?cSd+r|m7w^jaragk;-63>$<}C=weg#j5#d7898mzhg zAdQ{60~(4>Ky^n4|M%sC=^=T}Mc|M7C6&3GN(;GbuV!NU$oX9EvU#A_F2OoH3(@)6 zCA_nt0iLvJvz?~$PKhtCjp<&MV0ejD~BkmtweH$i&MFY;~L0$Q}@EuHkHhm4aR z#3e54vGn#NmiS>d>w50U{m37OYQ4un>-i(-;n~>zx##iF%nlqbs{j$VuR?&O0`6L} z9G3l2;gnwLvpvCuLjSH;_|d$U&pGyz8p$}686hBB_FSg*OWkW8%pAww?ij(1Hc*3s zi7wDSSb&nweBI|g0~f3O!QtWjo@w`Lyi}`=Yc7m{EgC~O#6Q;)w^fjux(OUh8-Vtj z2o%@LCV}7PkWd4j>waAqQ~m~G@1p@jJP3DNApRiT_kBqp4nio&Gl zq|~57bcWBMrFo0tq`?@N|H1?QW(`B1T^SJb)&SDoPZN^_evXqSf<)-~oOgjkZTl|e0?KT)w?O*MKaCAnU|N{o>(#Jqt|^m0%Vy)oJoCMtDd z(kdkIEk`^9{dXNk-x3i;+g+&B z)`VNm@%h9CG#@$(Z{Boj{H517KNIz2g#u|#ePj>y+JN@d612-6e6&ERxF&o zn1jk%UEsHt)oePHi@JZGgPs3H7#}s3dDiFRVC@o`U>rL;QMBm-&d?3QcH0w}!$Ps>XC~;n*VCE9wt?EnF{pGw8m%|96V4|Xs;D}o z%>PRJ17}i)+llaJ>UY>;8c$v>noU=q9L7w4SMs^jnYeZ82{b!9hw7=<;2Fu9-`w!_fo#~fUH~h-Qt1)F7SvU+!pQ@N zu)SyohWj_+pV^IMo5v}d5dd&@vKJojdm#ERh5wEmal-x+i=cwoR_)juh)jPjZ4b;6 zZuERAx+3|RrasMsrcFu2q+W}`=>fXSCkThTRKt}ACq&7Y77NXqF2OQ^Iv8HbAq^$+ zI3RfjIpZi{lWYa`>rdbrCZ;fQ##nk|auhX}s)sJoA-ej5H?EmK46nt0Ac4KItYKA# z$f&l8cN5EUDaR9O);@CDo=hn8P7xjCb>!E13j$f}=0 ziT5gW|CXP$KyDtiA)?_U3%clHAbwsxM0Pk1kW1?CX=(dpc(FGDm&aF;C{%{s0m}ebqDJ)9!_|*uGiV zm641MGL>ZYxq0w3zK^1l1gShX6>ExrV*8!lB>9XlP2{}yj)-+*h-5;q2pU2-6{jvn}|UXzFotpv^bIDF_Ti`#B$qrz<$ zU=r?lt>_^xIZy{@8-g+7=50I!>maLEn_!$5#H}%-@sY74?a@+U!}cKdQfoeQw|U1D zA3WvaL_I`&j1O1)qYna#c4E(!i5#l7!ynr?uKiO67hLuOzVLJ1&#k3oL()cAB-+F0 zt#ToX?>lv77SQiYl6cj|GQ7WAhpXIa&N&@4<;-Jv4v*(arqL7uk9VKL;fonA(eHtr z5+^d^TNsqCjAO5S!(irURY6nMPc)A?j-3xPaJtiQW?U9ecj>)`y3NIqUi1L0lXO^v z#ZvCZDsASOEyJD+{(`67+u5F(kCD3ug0@6}qp{Z9q(cHu@sR)>FJ%jL51I(~&-Gt!Ed`_rmM-!?`P;#n@-16s!Sp=m?Orb+B*{bb?v3F@rw-F+(76@+?E4~aCIJ_1YRAYSztj(T1JW3=?x ztM8WZJ?kX(Yx1YbvYYW**?ID7MLsT9UWcij^_Ur-j;=9}=(j18;oUkr?)cwa8aICz zY~XabyS(dk!fJoc@m?NHPLKlCX+`+yLM6YCcoxl;tFgH}KjTG$6Mj9J1$wqApcL>3 z3!J@xmGQYn*X3}uMhr7Ywt%9(EO#q$5m~bSfoT5aPB^u8H$Dmo#h4Zq-ceDA9uf1P zC_)p;yj@95QU=fQ*$Ff5_zCAE>EXvQ3e52*k}2NGFgx@FzEJYUi?;7c&of&x{bC)k z@)XEmd7ypo9cIiC!-Gp)pz7Bs;P@O)a?yQQH}w*ZI+Tr5te2t5+)-St{4uiXh9X7| zJ4;h+R9JHDReFp}1aSpTw5Pn^`=vK=>obP#>Jo@GONPA@YN5MAk;E&kfN$q>@y@?< zSQ?ar^CxYENfW|Ellf<0bxjM54VeLxtRKVp$F(^Ap9`#+G7_8X`e64#8Se736tLL* zQfTz}w=I=zF53LN-{)yv)M@qAO%TwW->Te8xF;)0e z!Uybg#^TqZyF@R}7J5%^A`k8@q+@Ld(IilrX~kB6yy1T|N)yNKgMT$P7??IJsUAL2zqbmz|C%DVf)a3^m&7tXvVL4em5foTAISqVzeBH z-xfzy*@7?D_o3*`BO-5L3tg|3*vny=AbG)=rfFu;9795-Pi_TYVJw}mKML3TWRq=I z6~Q9z38qhN#T$A~SaHuAy*=Jh=U-#^njslEIlf1I;0$aDwS@A)^`Naa5g*->!o%yd z;IEGklQ;fD%|g8CTi-m<>({Pub<}Ju=KVSgf1bs@Me}HV)nR%`*8pxFs>IHnvvF|c z0Nr-#Fm`LU(wAEN{%xN%Y?fJy)Ce1Ygp3`u!ZQ~9?ny@$)J6Oh zjlNTbSu6hol|5Gk&CVX!cryWC^X?&s(k-YKc7Y7=Ocq{=#e4kb!y7++8o$sUCT`sV zR?~H$^5{nRbW52TzuZkdM+!kHcR6k?x&t;lBI(~iF?3?lnDc1{%?-T-Y|;umyr>Zc zdX?~Cvl1%j$wEVeIIETTNLzlXAXoX5PO#qyTa{fv;h7ss2MD0IHB0pD@e6Db45tAT zePLw96mkg8iQerwNw0kz4%d1Ykrl&U;)=h+m`Pm~84+QG=jZY6Fz2iE%JO}9caH@7 zk=YqH$Z>FS@Ewj#jEAVpQ}v zHba;LQ=t#ng$+^ThGVGT<$_HY?-2!wUf6Y~7T-=@4(aU_W*Dr)J%he*Zy~U~t-<(B ztAvbM-AMi^|AdfEO{StSlF29Ux%T6H51XHT`9d;)htRgE9&Ug6NS01qhkdHQFxcClv+usd4c{T+=U_{?C)SHNsaiR7 zF&v4tkNucC&p%AlG(kl!gm&_MZ-1OfET?;kibKWO{w0b`JbNY=cFTs_W4N8%4PQvz zj0#Zrz#mS{af0nD%P{i;?|L#dz#T2pFj+^9g%ng^Ud120Rk)05uKkD#VY#T;+6oHW z6u4uSzFfjw4Pt-zIH|XOiOO$7q2f#+x)+}ybHiWJRR%S*HKhZb6lJ-D{9&kCw}|x_ zk0QB+z)YXrfPH?qXjtes(U|vrSaYXHWT7a{PB*1e`}yr~^TIrCQKSW<&v&ZhPLX0_=0lW9KL)`ofh(G@nQiBS~-c_|Qqe`388t?_r z3r8`=(Td7{RDFn!$efb_QQtOjSKje^-?uH{;I=l1AlmlNX7A$ShC-oh}SBU|9Uo}+_Z7nZ^1J_9+_~u zX5UH4-AEWQ$raZ82}N5@pS~#>#(j%UzzKXmckzNRkbb}xdk&W1NR9V!ZOsULH0l@q zx3i7L&9xyme_rDk4M)(lilM<_;=<*|He_&Y5PpB1MGO`8f)nORc;EHuyo-6{TX zLn@o>SvUrFO6y<_UxS<`a>8w)`luK7kN#7(hlE{MX`BTky9cL(S^Pn``eFhuD8G(2 zZ)+iHiU`Krj^WN^yn~VNcY>ZG;#@#a^Q&h418WJhuac`cy5(4vwS_1sNedF2FIr&N$|(l+cQAv!yNj(t&tqM ztpde|Tj1cEWccAzN= zk7#cZKUJ)IknL;N?9)*)7VGz=sM-Dapg?-;QkXHL; zP&_sg^J+3sr4zfbYq$_d~(pnx(7%P?NXisS`sfI-MHN0}$iS@o_Wa&u41^e1(7DOyiEH|HxHImQpls(1jCs+G6$@ps zafULR7c&T9{ie8g{WJLH9?K#J&d{W}23+_3tK`zsTd1Ub2=1I#Vu|lsYVyvjz~(RF zuzT)5tZ`H13L}dJA04mLBJpY}BYMs|+{(c7)qF1h>_m2Oc8^dhMv@ylz5!p4@`ER8 zGoU3+8%?MCa9dC7vIIWkwzzu%cxzY?)0iZvo@K-4=O1RTB+u6vMK{yo4!L-!d=F^w z+5g*TR&sOx3Rxu_X4^InRd4o+U}kGiGMAd&FnB+J$;_4``+Frhn}xk_v*ZFw(MnFd zdl=2R8z++Y$^nnM18ngHo~c+}jGfoyax=SQ}h5nS4cuv~r?_o3k(sNi%Gdgmb6WM{zXqt>J!I&mE-gm>}F zKwwylK9hW~NM;evh#k(Y?AwY~FrM?=`<7Hj%QJK9CG_0)Oju?$1q?JpV0_SZI&Y2y z1g!|6N99z(zicwx&~QN;&pmiTZ9FcV$xv~%DR@TfG1WI!_-JbrCN{O;p{^>j>eK_c z(r3kzFWdrG%?Ny87Xkhyy}~J$MYzdpIviFTK{`uL;MB*{anB~+x$$=zBn=jm_i~+d z+_S?}$f~e$U>6OY5k!TMe$YLyybrvF89-ysK2Yb)TkkX+pP8EM|M7@VIfho;q| zfeTsAe3qMV)$5-T;gxi7wjED>%?w!N*HW@0%Af9D?1c$|2cbpxw@^MX07hL`qw;}? z=&;ocvgV#9k@M`iBH=%reng6eddaYT;d0b?vA^)vepM`)kVK+(`A}626TC6fMQASl z5+U7`E!YwXPSRzYXA*XCB({CcfLMjD z>ZvAY@q3O1J^V`_e?J!E{6E}<;q!IzNAz@J)HGh0Z*WfNGcXs&B&;Tfi6lMsZ~`3d z4#2`$Q|Z~!i_xrKl`c5aDBPF*mRLDV!R7-(94&nb*C~wUN;Z38*qyJqi_fnGy_bX7 zwiJ=|8zubl^*Q{p7zUqDXV65NN&l%w;E>d5n#X5CmSpo!!uIy zuL=Dfv?$BHi5{QT;gaSv;dZemI%aGZEX%e6lQT)E7^KbV@0>(|n#k ze;oR*>Y&2lF7$9sfrW35LDRS@x}+gZ;H{W}mYao~(h7O#`um11$Xp8Tdb;T5Ck?^* zkuW!LCfCeGK$=v#VAzZ8`0{Qz6lpfnD2MydxzZ6W1J6VKcxQTk`U8?CuprCblhN2X zng66`K>7Fogz>?ic=5Lk9sVo}HTGU3UbhBm=U7u%tZ0lU4_qe(!~`LRDe0k#E%w^N#Yw-Z;T0zoJCg&0s4QH(pWn^5%ZE$K zgD}6yoIA2^JM?9r6Lxyc=Xp^IoWkWZSik#=@VMk~E+kEhJ)hP={uVjH>z0-9f>pq{ z#sRwQGN08ovtSAi8(`R!U$E@#L6oYO=L`kS|@(^POD$t$Lbw2pk6G#m(^Q z(sp<-bq_kNxG#)hPOzcsDGKa@X{G#08X)aOMoNqnMYrZaQJ@YyzCIErEnH1+eVj`) zr8s=?el;$w-%RqbN0_-Q6{KUr@W3r+;plrRsCp#`UL|i6-g>QtrF(Muz27G|G;|6} z69$Rh%2If2cOFb0HIrknH_`UY%QQs69>?pcW6PAQP#t_2Hx?5-{5gQnqY3Go@1b<< zu^PN0u@0*g+MxNbv*^U;VKksYoU1o^h%-;5LDrL9=sJ8Qj{e(6o_Z@nZ{{Powq-ZU zOWuLQ2A5Fb#w>iX#~RgXH#|Rj5|6oTAfM_Q;QRP3a8(!t;iaEpLc$X~_htij>~A1B zD|+af(6bOZei3%QUcm1nWMh!|94hqrOJ(0(#}N50sNG~l!{)WXqlY8FP$wN~GvuK3 z)mXT#D*%HE$>(b1eIs43g z=6tu$Cs+b~BE*?r=MIs;v;#0{-cMv*;;6&(RuH?d0LH4;5ru8Sj~oK?bm5`XF1R1k}LRl_9|YLbf>9g zE*Wo@fP*E|si4ysmRBecklsXkiw?rh1MQ?prx9u{F90*ob=Q z7&odog&gN?8toPrF)VyL&0N=vV*||5ZmAM}RVhK4r_sQ^8;8HtrP)8nZ7?BKpS^n{ zkbIYF5?TLACU#raqPI*Xb&72TrM8byDwzTs&)g>$a$G~`K~!Ue{> zy~oOr!4b)zwp1R{Gz`GEeGvOaGX}*SkBF-Ltwr5-#bmM87o7E{4rN5Vo;j)uQtl4r z?q?q3V^v~tqnJ7y(Qyekj#@|~QnJXDd9~!VAcks_BCh&|km+5qg}qv}1Xc|)CjG;1 zL7TTaj@^&|<=kJ4Dei;fFC)1-r|QY5fFpE8-)J^N@i@Ia=Nx$_=0$ck*y8lYA};n_ z9^%*&T=i8W_M)#oH!n^^)QnF+!BjP_$Sa73YiO_vJU(5iGmkN2To1w9!?5#R7>^5j z5|`{5&F0$QNA|!{c=h2*rK*7`EAMMhhn0n*d9p2=ry9aKNM2=s8damZ)?-NM-og$k zO`;wy*J00L9q#UiW1Q|RUHZ^^2iqCy$St$7)%|CE5oI^ zIo1iJVP^$&9vuZTo<+20&0DJRXB}KBvgLrsdi%9_4SRg=Y}~l)9M0F%Wk>Is&hB)5 z56voB;4H&q-}BhPi#Fur-;Qy(>$RaM)$kZBvK@tP=d$2ej5&mL{lcOC6WA8@=^y>MS*!JAE8yxLTa^uq&o#d)MF*VHme$YdW2A zI2|^bmEgSd6M6sLSM+_p0R*aMGkW?LLBTML3~%^GBYR>4hf9H+kg7N{*;!vtuIW3Rr=fNidG;ep7C3)^MRtwRyVBrG>J?~+Sy3_ZceiMfpb}P3(}TCKlOfMz8drGfAZpI9zJH;W?KVcY*i4O%uHk@u-10`<`Q%1(V@U?l@dN`UI%E)z9<$@P1$w=fHQ4EJ|j|Lr8)I_p!K$R}WJ+p8sQIxz7 zz1vmL_tFgdYL1v_MSL5W_qYih|2omL3Ss!D@;!*rA*}XCo*PZ-Ev7#G#60{QLp08| zlOT6K#v_f#y2}WKmV5V^@#zlu)UFPzLb^d#)&<|v7K{(j!y)BSM7F$1v_s)4?tN5@ zo%OEh7uJYIe-x;KcLClvFUEwjdV1oZ5l)u7i~6e8c*)=wjPnb^Z5a{t={HK34Cc!W zzDFWi&TxdIQ)137f?S`L2(2ycgG(;pfM~X}Rc8+Y; z*#$Gx_}GESOMsPX-0>Jca!BcKrLNpr+~+?74~FwT?@9`+*x?s&M9cuPm^{&VKK^K~ z=4;xU*Gz1Vhr{kR=TR(aRaW~E(DJBNg*umOjLzg)Fp+*8i z*75dTgSS+*VhvOmRD-p|DOf!;8XxHK{H@|qIIFh+6pyW1>r@29J`xaU(Dp-Oa zs^`F}ec8C#>?0N|RK#!og=o{|Ao}`T1(u}*!{pEwwEaFB+E$MMyR8B!+cchqnnl#` z)id~W|1Wj3UkX*1V&Tq_Onk!o#C7%rkUjUUneOW%QTC|wc-!m-shT_>0JBH$xh)gERAY$G@Arpd{}Nh8(>m*rvM{ zgp#T4C*hD&G0A(Q%BfFJgNg+gXxFJ=9F*!wZdG?P4|PkKYjIh4_R~c?6Rk#k#1pY? zjulMr(t_jo7SGOK4vKPBnBDlAF1&3E6641}Zs9T5${eG0aaXChg*RE$|D8^J9!d;9 z$+Idwc{GyC6+P3kgl~@%u=GYLdL|ij+3`b3s*4>+$d{3KyPBy|pCTTY@C2Qt6R?NL zgrXKFp4Z)hWZpV~haFQ;#pWGeA6AaJ`xA(Rv?N{ob|O2LNvE3S+rTds>6EF4AbR$I zMlb$>`i3I7u|tbJJ2ePTTm8m~K6Qf63v;kHw3gq;-o+^)LKr&y1Ud$dgKN)i@v3tM zMlp!Hy%VT|_!+uQkI==(_36{mlgPdc=Xfr_^Keza8s$eML9E*_ENC6d&Ft8V3!b#1 zN&j8=Jfs{x1df3dXRI(KaEmBo8HKcCiX>2Ov%o_3Ejq*%k+Kc_#L#OU9dhkFi1IfQ zrxs5Va&0Y?uQ!JwwnjwFD_QhGg5hz}mXnYlS(v#lgNXe(3}0N#G4cCYj4&CB&s=qo zog9u=EXDDCvlP|cBOr?DhIEY%?-SMI4=4P?!LiGVWT&6OFSgqtyEYLl%nyQ|lRx-2 z7(zx~40P#^X2%b@OfFhkK*r}YF!XF97+!P5Jx`r!+;SN_a?~2GD)yjgo;asxd(-zvdbTD0* z91eo|U1XS<1Z0=}6vc?kqnb@4UTB^OP0K5&b$&7*^V)?AZt8J6I#Qwi-39vk(P#*+ zoWV@)G=qRi{b;*dmN`?kk&cP9BDR)OxEF4lz}Vsyezd$TNbb8W$T~5FOe{K#`kxAM z^@H6ad*1%7GSUsloIecC-CYFcDZ}mqOK`&DHK;ptD{@=qDeQ5kpGt?Lj%p?>N=buf z2Q)|qAIEr8-juz($AFX$8*hHsXd9_lR)e2=6>#CYZkTuYCZgd%X#1Ulj-jz6uVD#3 znKvFodL~v*&h4W5v(5>g2#2zK=r-y`OXH_!-$dynF4Ln)!#S5gMNIs;3eMcf7G*k} zfPipQ%vksrmtSn9>d%I|coV+7oevb|hnI9*xUZ90g|hb?l0$gAeIG zn3hloX_w^boYVvG_gW}88Rv)uRojVOhZ+}Rdxtt3JmUSwn;2bl1yH;i3gVT+iBq;5 z9^n0s4*%4KGuMBi$0Q5XId>30Z3gm{-@m)%bYtB5HS8Kqb4>m+7&b*!W30juqEz4v zQ+HZ|P|FUkWI3bH5`9QN(o5ScWpU&=dzg5u7)qz`F`Ztw=uO)t#4O(j;-%xTf2s*u z@mTZ`LN~1D)-cnh2D3gfHz0hHKHiDvvCOcUuAX8^M&%u+gEn3Qt#j6(+9k_oZ?<3p ze;meoqif(lZ91+}WKivB0enfi4~FxKp!;Jg(Ko5Y->JsXI(-6cVr-H8lR%2U7~Nnbnt~7-{u2L~Lgm3AEz1A;TtG9a|P059_T-8P*i_`Uf8jr;P77%U8-S*#M{ z5m|&kOr%la%W4?82kUhyB7VoJ7jS;DE)z62{ zKP64~wVuX+NB5|qOfx*QEYRL zvU&^|Bmb6Et6fKXw*=U+^DS8I74SIx;$)Qe8=@1o0ebgc!hNbQNW;pVFxTun(YfeM zIAa5L~Uy`BnwYbIe^ce|)##s)ZS(~e(yiZOtPcTIZI2lHRdzzXF@ zbZ$)_Z8uA!ff_$(?uyqaurJ0L^;tvU<=kmVJHXy!xH4NFc8GEvSG7WQkm`s&g z2=(3x!E*U@g1G`-Hqb-wn3=THS%=XwOedpd?M0FID{)rDI zT-&G*XzMf*$1)d*hD{jx>~;>qPu#?W`{t;hQvo;c4CaoW{sR8;EM4*C5()SI4K3+G zcw4s$zkId9M~&UkJvj!lGAH7n+b`ho=sM9Y9B%5>v3k?5bkl*A#mBJ$_>Azi}v5#Y1G5zuv2gt3(s28$ecmkg^pr6^7K|REo2I8 zVH5~=* zUUg_0r^XdL6B9WuU5Tms@la&>5sGX!3KAa;X7%UgfcaWw%;)z+IVZKb#Zn#g=!PgP z8ug3VZ0o8t)F{BPdl$%~Hd)rxPKvdRHX)hzqe0tkH|Fh|g1Q-sJZ_K%{iHe=hR&W# zM*g+MM;cAcUad}C6ulN+nz&lOabf z$#1VixLPs{<*6sEiu1y<8hNOHl7{`cY1rFe06N<V#(j4 zYa>sB+g3&Hrd~S4AB>_yELz~|INnD@sgX`ID1+-?Ls5L`DKJPn56eE)LI9UQzS_6I z^G`mwaZJG89G`WY_TX3b)6=Gm|635jdR2z-u`HQ;Ha{g#s-T4b7 zTqQ-}nLmL!3($5f6jEY`L77fE>~rGvX-!8^eNHAUXubecZw8wer-FTj`{|bD`t)+W zCwjc;5PcXC22Zm%>OJiMA`Mf5-WIuqWo-a9B=nvU@nu%W7 zL{Krk!o0T^f~V&d8h>C9UU<8gkMHF$J#h^@SFaW%8p!wq)qxdcJK zGmw)Bg%Q)jN%MqItX%#GZ236jm!*eEoh6`5Qz2~HS3u!-5sp559{YE+kwIT~5UrVF z;3nHm2AiH{dTQiRwzhy+Rn5k*4sT43pM^!d&*j^ea?!-EhafG+1dq;IK*!RbIAz03 zV)61bisubt%R7c)^X@VTo45-vN`I#sR>$B%@(k$9*+&Xv1$b@Eces`RNHmf01jkRB z046+UvUh^$_>35l7au==>XEnLV6Y*0#6BeXL9ukGVH%W9h^K3Vo9L5+|1ZPiQG|3%Dojp@% z$I-L+Y=|W+zhnZl+Bwi`TaG~<`xvQ3L3l>C7iT|Ojk%*%LF?+<@bp6#WNavfvaU$H zE#?L#6>)g==YIIM+kga(UyHff!O)*}gy&$ofMLzHOp&dEfb|>(X5Z7$!^oBNRPxU_ zz4B66`8?A1Mj4>-kid4N7gHG%1H-!b--Lt&Dy<14mK{UTS#>y_XDx)H;mc9>Z7(@* z&Bv>S{T97@B#w!1OK93Nb8dK^1l002c}P{p`4ihn#9LFWRhf*jG2?LN$+56VVh~$3 zdmW6nR>T|T_o>ThOZLKqIxt<>M)JkS5XaKHXL2@tZ{8)l$W zRJN!$T!&=LkAuR|$Iy(fg2#!knCBZCNMwite(_eLo{Do(YfUr$p3(?k$C#mJ(*xLA z)JOtG+#tjJr-~frHKWOcSX!prgGn(ybiuWJc-wbHbgm{C^U~{Jt(pewF~k|%6=lIA zq?Q!D$RVNclj-TC%a|U!8y;NQ3{tBjL@}#|bMj4diN>V6#BzE`#p~AJ*x-nj<|iM( zyKQ}|r4KF(M;(q+S_jKjfIg+$pBLg0|hmq$!#h}u8kxq|j7R~Eh z03U0f(kbe(Fkj0H@=or>k={+99Z^Src&$ad#vx#l5QaKtQlR0{gIu*7CO;Ktx6NIQ z6~=KeXd^>>#iug?^2YFBcMzSXexA%8pG~ffnF{@b&g1d0QnEy26-E?)M4N{vp}%P& zj5w-<<&wjA-S0)RH`tN*HeSHGsgLQW`*rAOGZhEh7UGFbyF}lk2a(h_Q)#ckYA$fA z3l?9Dr5;tI*;=!M^pF2=wqunUJ9PLW&NO#FRkd#=KjOnlOS>2boXKJKB%i_SX`S$9 z$_h+9u#U&KO~P@%QqX!x5I(TfrQW=3=jlA3vf8^SlZaBtDY~ zhj@PY`L9r6nFL$s*~^?iq09c*n=Sg8tj*Y6tivxde{l9`buwOQl4z+*1l2gX8nJyX zJMpv*YN^JHUawk?YiuUK?x~kxeBBSy@{+)=X%E5vZ3&88gGkQyGTbZjg_F)7aLcy$ zxI|waK92cC&n2J3df~!c;i#X3j1;KaG4%wSk52uLIj13-JMu;Hbhrt|{;-7?u?6AvY9fbMWo~yiGFT zR7M`HK(xDBozeF$8eX%VtAJ|5|kS*qj3W-k8W4u z8X{0eA7_!B%+1Gku(!76;Bv8;SR;9+BgN%jER$84v! zU^T%77H+m7Fo%gX=DkQqr;;q|E?{OEs)FhCaN0lV z7ircWN}}J$Fe^KDqDRjYGwYQtX@sKSbVx{OFXL!R(^A zIDCF~Gl~8(n8)Q8r>fphMNw^XoC1&Ecf!~b4@NDeOCNloyL9(cUHx06*EF2m(&zc= z3M4_XX*fKST?Zjf3A{c}g;h%bO#XD|<3znM`pvk5`Em9^<@|aD^nb7jtHU(7tKJr{ zW==V@ojM0>b~0AGpX7a8a!HRU8T9|CpdT9n=NBJ@=}S~esHZiSu5qGAQeWbf^Y?IR zttYtaJb=BUimjk{1AsFkF-do)+{n~(Rh4qx&=Fn9?Lz$HGHhRS_{zt1`)w_5+GmadcDc|z+>6;;rN*9h zia|~oHZ<_Jez>TcFp8 z|BkxXl9LAWX!4FiPMtLTl%b72KOf+6Mo8}^iQ|H$5l}OzL3B7RnM??DVRgg$ zh>30yY|JbMb>VqYV}A@ZF$Va2+Xt$1q7=Lhb>X?jBOF${0hD$of#?S?6AQ&a<`%F2 z_N@h{N>}Lo5nHLF-2nj;OhBW3EIIjG2mWL!f=!zW9vG2Kd}idJYQGK0T2?`zYas+4 z-i_BuBP=;zfodMLH0#u6W|d0=+49VSn;c-pp1I!!X_C&+@Z>6-(mpLJbV(%{&wR*U zl^1l@i-o+u?{6qKvZEzmwYXsiR58@$2zUot!n8Lt;N#2S%Ik$2@ob+8=$DRwh(EQk zW9kQ5vRI7l)z}0pbYzf53})F^X;}X;kIFb4gw&LEg;fad3lGRO|JoTM|=eHhmkmbaUSG?fNf`xjyAgl z{kOE(3pE`5J&$lLGfvP&E85Tq#?ce(ds6m3la5}01GX(X$NOOunw^@776x{x()L6Y zxw?ujjbDT|UnICg^&)yqdpq zneq;fK1U3+DnMvxA!n3s;NHzgaob9FC{j))<?$ zRI?rA`qXk#_wXvdy}{B+pD)8Msl|{fBTJt6O@-EQStxzdL2YLb#WO*3P(^Mv?Avk- zrmXo5V?5L8vG8#iu|%5Nprp*ruULhpn@oXc4#&&Crx2MCf5;7%#f!Zzm~_IJdw1Ln zCMcgL56{)2^PzeWs}Ny*oFm+sCIa&u=Nw&JH48B?N@8ft+jJz-bKm48wJ@TGt zDEI<cf|-7?t!SHM1a<$@ZfnsD^QNOsuMaEx{=go&wUY@@_A^4Wof*xRen8q zn2&Q?pShc`N90-i*T;|^t0aZLo};R8GE9GS36#c!qPo8gM7@|mLKj{XO?}ry)uXQB zv$0cQmcdT)HGKu{xvI?h$7PA)b*3^m@0}pR$}rf@>xw&CT*<1vGVF)dgMgJjMQj>U zKu_x;P7g{Vwl&9aUsWm3&tL$0JS0ck<`itLx+XH%(M5m#(7^f2H&Z9&WK89bz_k@N z;1%&zl>cWj92+r#)mR*YS7!UbHphL;)ugX_3(e^%(I~j=G`QND4oK*OwD-YZqB~}Uc z!-_#F>!(bcn-4VYI7+_ERyEli_4*VvL!q-n2auKRk+tF)41wABe?YTuUO$U zR%Dz16dE?hh}Pgqypc7Ly^`z5*@~UVrDNmq>?__+?Xy1$m94q;bq`R@^eT?}eFEJ7 ztYF1{CZP(dK)l^!q%{emdqe!#&HJ?3gHld-Lp}#uBP`f6SITJRSL6-`WnrkY5W?iY z!n5N?=;jHJE}3n%=%5iesZl^=w|K1KdzU^WgYP(3t z7+Dy8_aH9haoKM?>IMs^EQm23jauNUq{0i1SB#;|g zu?A;P9?3;$@;cRsXjoA2TIBd~IYxP#aR#r?@|=(S`rtEzEv$8ABX1R;_D~gacBT<~ zcS|nbd3jHi5ZcY#{8-q3dMLJfd_g%48<@0RjGKL2AL^I>!dIS=uyKDX$~yE|l*xp# zi&f$w@ZM04S+tLpH&tfeyy9hJDHGI*9l|LLmSs~u@Hhtk`|0(r1(5pvHuc$+KufU} zhT0#(yuNJ2#tvLnn+&V9hI1?3`*CTb1g`ve4=f{<;6>?ZPT?&d6L>YciZoeQ3=#iFTpi(yPSCGm|!WjwVm4&%op;1@6uhf4CS?3b*qvld+Pw z>0|4k{5$;`EQl@_zg~e;H_RmEJoeoRsdu6@eQ{3KO_KAi*9Gb7`U;F1iy^1(!AoUt zb_;JqY#pY@mY)d1S=!>4CPv58NHaO))UY2M&uJZfh^$A8?7 zTWcn>_brF8PnjXC`zbpvMe-zWX&a9AeC%>&>JZrB7lWC$r|I-ncj2X`4%@dc1}>?j z;_I4;SY=m&9%tiesqzT++Iw|O7tQ2WeNCVjPwxX$uhHbDwLAES48kxgZ&-i+8jP+B zqxQ`gxYz}K_%2nRo%J>tcWjE_#0>@P8Q)qqPY22Z0BmU%Gr50*WtLEHmvWy>1^IcE6(5EjkWF^&Pi1d=0YX&c%1e>c*SJ`YqP!x zmam%6ZgfjW)$fbxg0xlamieBboHdUH96OKU(T|< z3huY)a(~l0P?NV0M~9suv)3(VvpnA8r;=3CwD*XJU9QDO20mpNktMB@s-V9d+C-}x z)Zu-Rlb~vcG;CUFh^mxu$;0^gu9wX;H%*?$W;x2TRiDVZEq<`d=_ocnI!JEYb)tbX zLuPH1<A)3c%@W4&haaUr^!!+`*5-Sdrd-kej*`-U!ps*!3^oR*Mi7?~&kI=N4epgTd@g z)mXUyz!F|Hn6d}-qj77+-zU6cb!>uuoV z@IN%d@c{Gj*?w|;`(x3njb~ZQFK^jz=Wntu6VkZKu#ucK?-O@0YYR7|Nyt9mVTwav ztHE$5>q=WMaiV?gD#pa~7*`L?xrg-=>64pIxHRZ6Et%nm5h;n>%THo_7`Q7vn4-^i zsNBV5Cn4K(O$<}suMo|DIFTE_K)}5hEae8-J%dG^&cs8i3lhI?;Vu>cP0{e@&MvLP zuhE@&>d7hG(sK&G4Sfr#<&D@qwHf8qU!j23lLz&0;OG`ZoT7OLw|Wlaj+ORdL%J-O z^E}yy407RlMLqI*2h5V4&*OHa@z3%gO-;$+toPm`A7&0_4K`YHqo-N0lNSV|^c#Cx z-C>B&pUz?>~*7Pj(6tW)uM*l)&ckeAI~#|3IEx4ml!IL!M6C z!X;Y`=jOG?laKzp;bw0lhz@MvepYL-SEj6k#Gf*3TF?W$=Q4|%<|@NRkK9L}*c!w7 zW(jV{p2M8QIA_+*{uX|+p3Lt0rpOj9Pl3+Hy@58&FKJGtdWKxR=W6g z)NoF)ECY;=uER%ClH6CNER209B99Axie8L6fZ})w_q&Z`cW=$Xrm|UVR$Bnw!fhg5 zEpJ6TZ>@%u@K$`hD;=M-?t_%x@vOw%ML}h z<3Y2?54+G$>M4Ajbe<>_S&AgmeiA1cTcS2hn_7K{B^z7{Fh{bsa$RT)_WQiUr5A2c zuOYU$$LS=#C_colJdz2v-vhv2bqp%UPi7mx_!BbIWBm^M^*-yj?qJpDELE567ZVdJ zUUClps072)T~1uPb1Q6@F%;&+EhTMZ@?m26UesLl6J{U1#;!YYNm$Z^_-Jb>)mDka zt~^Vj?ZXIM?ir7-GRAW?dd5{QrJIB=lUAe2+Yh2fpN)8eH$dJVGK}LEr{Ji*Z&Q;5hSCee*z~{heG#Ib9$$27v=|y5x(ubj0?*T!sQvQ z6*q&ms<3!{m9NDzCM_VV%EPLd#0N&u}O! z0E7=?w^n7K9-bN}sr%88bt8O2L-9Y_*t;jS%Cg zIZYFv6@C9AbvR4F*AR^`^NC&brM!XF=gh$c3D#G9SBFwX7} z#)LMp!?sUnD;gxL#-I93O3YKL{z%S1qp0h!<4q{1>h+C%(fyfobi2hml+0sqhbz+n z+t;XB`wHtd$Fml1-*A$N-r&?W3^hB?^P8{>Jdk=KvhFMB2wOAmyrz@T_Zbg9p!X%AvR^11w%;R!Q5B zXniV;zEX*HwkPoWuPQvhJ-eaaCCJ81wHZh0eh+JAk2zc#Sn+}UR!LuSanGyekB;VTIA=; zU)uk>T;lDz-q+3E&BtS#E1xF$FKwaUR>$>Qy*=G_%=6gcyUk}ee?v^{k2SIK^xm|7 z;3C+PcN|&o>*urHbFR;NR}VKYUn_Ta4==Y_+qQad^WraAb@HF{h3mKSkRQITUS3Ai zeB3#8Ze3|t=|H;Xhvi8`@H}P-PB1_kM`ng&8Z~R{i+0)!2m}9_u zp?GNt#+S50>Muj#S-DTdUaB0PT=N$=O8MrHC^!YhNY0l z)Dor?(;D+%6ixxfdJ)IN$%U2v= zW#YYPrr>J`BF6zZ1OPBtCF$C`pC??mw}7!uCi%f|!@;uqgE={7aj0TxpJyj zG2^8fv!OhyG3ql%_7@GL52~3i%$TIlK$kr$cp$@69%O_whn^njYuDpKL8G`n^Zhqv znfu2F+R_|5RT#QfO6c@OKqjTO3qGzaHh(lMQjlPOkG(zKl>OJHONj13+nQ{f;CI|D z7_Z!5Ve0XXHAuKTeL=`8ZzFyjk-Ab6-tmpqx)m7!>YuW)^M=W0DQp z1v|bx6xj4ni zS}A5v>=xE&a5a#7UTn*gC5%~?l5nwB+CV-3#^+sKFfiXkCC%A*@!Qk4Z>Zu?J8zJz zJ$5s;JSZ1NY<3jZ?wL1`f9p3_X8DK%g6`IDpdS~`ME6FL6J9w3ePEWngpdFS2%ljp zc<|&0yRKuk!N2+^zS=zF-*Ma?7lE7cIf3}S$xPltN06946b^MS7Y=!Kmh^1(P z%1YauVn&QUI?&dzt;YxI74H}$4A6Q6aeWL^&K)9U{nMCTUfzZy&5VWi^1EjoT{KvD zuV^ykHSz^13%)4$QWYW?$up;1%gP4n86^fY*PRn=NVO#+<(ERh>AmdI-yv+yj+cT5 zPpg3jn+rn}UkUfjT|Y1fE3aMz{R##1*x$+n&+wbn9Jb}H!oah!F?AJ8jtc_057P#o z$G_}=74^wn!ty5RwvS=^8iokdpJhQ!%Pyv+ zcNDDEND!E7cn*xSYtwUhR(h7X*q69^>j^Ag0%#4O!%?3iO`BlpQe=G+dO?`ywkKKftQ+N`?IzM55e~_?` zXDiM>?!xfkJYz|9LTqO_2e0Ya+kxE@Xz3TcPcBb?F^=Zr6&K% z+vZz_7Bwl{~PyaaeBOrfZgOIw*u_e{;pR%7LoFPp$P*|nrKQOkl3)2V6 z{7FoQXFiAF8eebRt55&QU&LRpd48LHr{N7PVwFsM#pZ!>@g;!+Z8{a34;-IZb8ypO zsc`M%$)t}jGeMAJwwph;Hw6j>3+q|KLM>)lU?t4s=lNg%9~QU>dxuS6KdJY_sQztm zEI0wqm6o$A-^B;&FA3Nt%vd|k{2pJ&^;W5YGG%_-gaP8)P4$YGvtGAv4D@@)_{4!@ z)q5Y|WPgu=e79}y3o?g$LdEg_8k=mM8vAeF#zwn>*vbPI<3E`QBNt2a&UzFwUjzva zv$hJ)PYV=UEu1ot@7gQxfqMS+^S|eNh{zyZ7(!NyGGk z{Gsq0_8eLVtM>Z{o2L-=#_s~QZ*;;y|7@P^6dH9p3HP;6A9&^_f@b4?_5bR6Y4-0J zw$~HP#I{1R>ss)LW`)E2)CTG<_sC~A^KJZ_(*<9Sz?mceHO3Dw>;~%n*M4xzb|JaF z4m38OXJxBa@b6f&@xSy8;aQ7+^Y^Yh0CvGh;qlQ~p#AVLq&`?AJoejL`0rf|GH`mKe&2_DBf@zk`Ix z_i=>0k8sQk5BMOdFWhls9jy7WdZ3LH7TbmXdAr%D@)*c9SR$-TJPM|p&QE{d<_mm8 zG)T@73J$GVHc;o>gard-ycg_ed-ytS+L6S_%}iv(Z}&03rxh`iM*1<6&Nwl35$$BT@n6!)?q|L`$ikX~ zr?dEr^*M%oL}`Gp6qb!v(=HW=Dq>9B?UNF2^{Nbvj|p@+nt{P3uucmy?7g zK@UlbOdaXz>mcFxqZs*$Dn??IKQq`v49ZfDGdrgKAcGRc$tA}tL_%u^BYyr5>C_Bm zPMjG6b!Sg7;hx{g6Prk8`|4)Z}ak$HK&gM1e2AeJ}d89O(5*wO6HJb2L0^xTmKyH63!8N**h&ohWo|8s#9 z8lEI+7mt(E#{(FhIj@*|QcsB1nL|umyA%{ApCeAQ8kp2;mCUQLr~F?k}0>oP$i(&=bsRK`Ap-6wOR}bC0-9 zX(x4|$C%62iOd6|M5c?)W+t6TVhqytfo@7AdQBP3s38%|tnKO$aI>G7+Q%?66xzwi z)*e#uWem*vZABKoqNJs%k!;C6!Au-=l#!isoqQhS&bTlRpfoFqDe+Q*Gv;53LS6_X zvooJu=QS%`Zi+DPd@4g1jvz*(qL~XbP2rw2@6MpfvwwIWWnM+CWzv|hO9&J6+=uzx7SFu=ew$3y5`(uo;pE`caIjS2ktk;k zhRla5BIdn6EdFqf! z7Ck!0)SZoHEXpI9R`QxmF1|<%C<9NDWB5ErnEh1;7<FQ#JpGhK;AK9}v>`hW}r(o89_dvo@{w z+W2pbVq%s;vVa%Uyga-%I`HBmpSJ(>UJLSH!rOn8O?Lk!wn>WdC0ad)bJK;{crfS} z)jFOEFE8!~a@id}{u&GBGZ)c&FU8q}giWFw-wZ%Cb*fqKgfj3bt)`QG4Zth^Fco$A z5T(6@+^ab)D)aq7d%Nu6)uLjk$vjS^+aHpgwl#P`&k=Mt$B+YqBw#ZS^|xkWI`eDa zS!#673Ym_vblIX1%nXv{%~mI=ZI1*!`DZ^d?72%9z4%3Y?)X$@pH+cB-vR~h3xCqY zUEi=^QWKpdC(E{c4J0PZeMnZ`FLG+^IoyJmn0sqtY001hN}gHL_gom#91RsXqow57^0vhBED@TFVz+ojp-15 z6Ar4pnzsrZ=eNMUttZIR@%`p%(LAkyD25EbuFY5pgGtfgizIQwFtF)ADG-0u4#|_u z>D($~wyrsmDX1C&kN7aN+8JjV7X@b;Q<_SG&y~@mSERtMGZ*i#OCsE69(?i%Pg!6# z8&j;7oLw$Y7GLHeP?q{KqXJ}c(zJKvgI^v=IevjL*(*tIS2&Q2X-BYn@Gn_8qvHj~nWy<=mrMRTMCy2<6>75_htHMC?SJg z>89}Mr2&3Bw1g>Y8%hgK8A5GSFumq{k9uBN4%5HRg=Gs@;=b3PL@mX|81w1^J~fx) zp^T2u=Os6w^Q=Bxt6ukb%=`%bv?x>RAaIGt%_42l^CN!#*Gw5czW;nWU^ zc81y3 z(V46UQa0fv^YnW@T=Ql{Q&pGolv-lk!4wZ#2{(8Oo(q*{+{D=zd-SR2C{5h(_Bv+B zD#5uD4Vb6!n3>n3Pj=LXLgmJA@}z;_lGi8j@BSmCRp+sw!bqCF`YFwJ2YBLv;g*mZ z6wd6sn6ST$63pFfydx@aOK_1 zj4yV<=EJ9nGJOCChnvH(uw^hp;yRh?sDV2(6-3or_cFUiox-tE+Dt(OPj_H31dooK z4~F9ijP!g-3soA)sJEFI_&O3rmVc@Fsw;vDeJ3V!?`mpfJ&2_II1Undtt3p1huO*7 zN4|J1greL|da`9F?~Wu61@ni|AD8b?3m#G<{O@7foATuUqv*WDYJC4VUP(kLZE35F zmXhc^pU*)gB$~F$$oLYWNJ836NP8#A$_UYUKKCgrWmH1;EM&&1I*h}s7?Hb$?)N(kO$QgTw`T`R7q6MX1XUo8ij>7==WZ~YcPXGba1OL| zkKuB1PLYYCpuAI`gHbCgV5e&&d-6CMTl3W&Evvn0$I{`5XUkw|g)`>du*PZb<>cm8 zg$@daY~JpTP^9(^?+hQ0qb|xbQ{#oqtY#kj;r)o*#9v|imhJ>_v(k>{w1@ziw zOI9^anf>hB&M6Jv3lApdQALd$3;T8mw)Ib7eY)*vtcna?4EKexS8p)ikF`+5bL?!g zFWD-tgn!2_Q{lQaxV&&Jd{-@kvsy!N&JkaLH`;h;U<&^zb{gp2GQ&|G2dHY#RNNi( zh%>WWfFB<%rj0kwfONeK+R0|q#7$YK^!6bAUOkh}WM}XZ7tXSaZ~95siLIe2%M*T9 zDr5QpQ{4M_F~+nk!@{}<+^8}Z(>njdp>k=Wdy?1a+v1PGJ14OZPP%YVz<<|&{KJAi z4P;j1ridl6XnymZ7*oaoD6fixWC-ot=ToE%ixU;rq zAyOb97bb7|%3Svq;r&;Z;)(r^F|EG9gti_F2=0eU9`ypcG?8y|yaBm`${qJ7Z@}K? zia58r9km{{z^}s|P~Mi$4I6QX3tWE*U1rY{@IrEE<)V%ooi2c4O)=))OU2}8QRKDk z0sWIH!^RvPc&+k)<~GPmTMgfm(MNOfNAW%QWB3tA89Fi1`ZTsy@dZ1jTF5QCoQ+Et zRFY_op!Ay`#mK{quODtNNjV$L#0|nbGVTa%{J~3ZUVnq@T~5;1As)<*JlK!gObk~( z4o7`!!7FMH&FRbfqVvX5ho(N4$4m5t}yo zX4RVcy=?R0T$~zv49Z<>aoGSFRv6jKyXtsJt|lH6|XvSB;o za&@s${SyGM2=G$fjC;M;u%MlvsH@qLZ9SZa|2|&e+;=I6R~}Y^Lw^m~?4{pH-nb8o zx!n!{<26}vxG_DKnFZS6c`&RwT6z2 z2{?IM4nOLS8_OSk7p6FWW%9DUBJblFFyQGbevo!Zm4#jrI`r|x@Rxq*a|}H;q;6h1;tHgx5U_RGFU%#!?b_`;DT$N?R%Ziw({zc|zySRB=sJ zH%+!YPe=2c*+`9c&c!pFR2|>KE`9;qV=@etX56A)s}bVmBh=^_D&UL@MOGi0mhzhRsAidfs`$LQ%= z#apZXgH-v^&~j=3d)~Ja#>sABM#^y*+Ft5tWUPWCnwH`q>+2lzO2)r&`Y_~J7M4w} zWNdL19Qi3UY&-k#k*(<*h)Lw;_V-_H5yg*bd^q%ROY%_2r>SyNMQh{p2pt z5qvpQi`ehylDMb3+*~6c_H1JXor=gK4aXkQzHO$covI>kUtK0zqd5r{#rV?%^FRFB zssO5py2GS{&cccJ-XuHh1Xp1(R;VVwWEvl|0IhGpA=N-OD#r;vZ$AsaJQkwUA{Ayl zeK>A+Tn%G=#N;h~072Js*!DQ#wn}$6E&fk|jrDsCW5%xm-`N9&jlpwR@}Q5@Y+)0< z65_xf3fI85G>e_-W68(WUm_EIZE^0?i?DE`0xsyP|Wm^+L)WpCuZ{+i5A<&9*%r#LL`s)1~G6O#R_3fnY8xzTzl{IMWAXgzxxu2%Tr zq}lp-vu-nOZ@5Rl0;@FI!W^y=Q8usTV#>Hi{eMmWiymVpv#fhaK5@P z3mQx|be93r`uM{faEf zR-sZpWb<&CaimH#)aM_%|2acXuTFu0;A^lYt{z3GO4gra=|*rgRI~At^I4baWc(bo z^D1DjPWQ;To@mL7W2l|8nT`k*!VezlBo`r^pHGFbf&rH$ISpUof>{Nw1qqbCk;NIN zrCf5)BO3gsz*cdkCxf5!HHelUtZ~V~f&JU1#38NYtS^xhcFiX(KDIAt%&%&a?W9MP4 zJ6;dDd;w=UZ4AcNjKZ8@XZc$p1@Jv;4OqNE`FLySMq)_yT8|A3I7}W zO!dRlb&FYyuy>iSR}DX$M&s{*T#?Ric_!LE4(9t^!?-F&_AjmQi;Wue%B$jR0hc`H zmztoqD&$*tPUq8&c3_r`9G;zNikoV7W1xNyjFo4gd}lR#F=7iXYL4ZM+um|bwt}ME z<`IaK1#H~LGE$zBjoJ^FvvVq%P;BB%wj(_GTQyT4xHlW_we$iWiKebH8UESZTVRXl zS-Qe5zAH15ec&URE}X*G6S~PRw2=HHas0MIKM23j&{khn2Z@>jJTZPvZV(S-+@ zys{zJU2DVWfi{2f_b}=RjAv)Y-i0Nlg?QZ796Z!+a1&Yul}XYl<|(YVbF+?7_T>GX z%jF<&Dvh9)Lpk`Sw=Xj(&jfD#1#;hEh+qC&BPd9K$yhFcfKp-qAx>hU7cO&MVk4%m zG>5%^V~s&NgQSN1WctKzvtRx>(twx@>Ejt!`0#lf@#|n4Ea*`bKeve|xwj|jzy=-G zo;?NWdz^UUhXOcwq_6nf-)teK?0|A7n&740WVYsq6V|+~fnNs|*$f9~Hu~@kW@DcZ zCl5zb7*4=ldUbF^wU_4T1c1{O0j<1jpt$D5W&UVz8WzOIF!Sqj?8Ph^|0dxO9-7rg zQ@KJ6J6%G-?{v6n+%V+cg4FZHK-Q*G!sgsl6wls~BK{+*ByQLaa81boT$~p{P1ihe z}(I!utd$Jz#{pdr0(zEZ7Q(IcY1thwN@2@!yT< zn7Tfh3;t}(;x^Th09av%ex$+OmCmfLa5uZ$wF_L12cf3zRnQNPqInd{-M{I^p6pvn zTUPeRM4wp4VZz#ec1sao)pd~_m4AveB4og@^8&bTRcAj##$c_t68?#>Vc#80qA{0U7$ze&6)4GEN3W$9LhM)u)-drwSZA_Jv^3F8=Gsk>c=j zAsU~mEKb?Y;NMnX@&D`UNeO;jmUShT6$H}_xdP$c@`)yNn~`K>5Eb0tDIMve$SfVo z@uJ*N&bsOwxP22dwUfDACyf(b7!k-1?GnMbiThZe1Pxd|?JU(!jFohKDu7kb!h~mF zCH?m?otbV|l#bf`3e`NbnbE_e(iwY=m`sJGIK)Ghi%i`|G9Mz~=@JL&GMxi(!n%hu z8-0h4DXZfW&Ye26kE6-0e96E6RN~E?wD}H100DI<}6Qh8W?RW&6Y(afhW5l}Y078;clR?a#add{|+}T3Gd90|rl) zC)0T-4N!@r!?zvLxWOKrF8WE&=W_gxpcq;Z*bQ>VG1ABd!?-^=Q!pvRg`IBH!3Xm# z&{SzEv$?qmm1ShamyRfkwH{n#E<0jjQ=5pbu+|XI`H;<@IlY_JT8*cV#Y@@WOSQbW zbPIfMcV|a`j)nNq9Hxftz`4G5tUW1((6^gk>e5Q4x6RlF#eUorlbcZ0@(Awztj5Gq zv&9eMUc=U+a5z~hh$_FWgI6k?bdGWv%U!saTls1&YvpvAZD0%4S)Y`q?Te63XHfzM zBNkJ}g!85mzp#Y6!)YGVWLM17*xki~CWihK@6ri@9}b&v(9&A^zT+MFmSjMp<7bew z@xhzZzEbG^?XYU&Etq@i4R`LW8*DxO3Vzm`pzZB&YFb=N|KtoX_1-J!`DZ2G-zSM( z&NIWvbaSS#sV}bma}08qZDa?62I0t+irD|?9p3C>8%j_21@C%6q1#^z^}DpBmjA60 z|12FLz93wx&l*3Pj-`d6f%q@~*Q5(O=hQ;7a~)l+x5VkrAtP{5oF zJaBm!jJkFK<&=){dH<%fbt^=i$72Wjw>?1IP^O7fL&|A*jSM^r93n0_{l&3dMTtGl zb3`3u1Jw2yC7$WEmrmvPgSNgw;%6!K)I5JC?g@7kH!KNu+&;oks`_~qJ(snSUi&i& zpWk1AL$+>UvqrkGU%tE8*{~68(KNAmoBv`=fW9=>aTAr5K7yRCO=SGF7XGW=jGtB> z;bbSCr&-x@;uLeCD%5U5;mJ2>o_Zg&sLJHC>V$X2h*=nE9~Rj_WY@#Mb#9Q>4qXZB zLV|Hy*)g)OO~uwV4OFw(Q0is-7?b-%(~W=1xW@W9jSf7{Iaw({%H7Qn|2KuAx)VU7 z-(2yvP3?j@djSo7HC*gm(hoyZ`{TWYyL|2a%k0JVF3kTjo9V3VBmJ;uH|b5*KlXg4*(Vk;z-9^+nOgM)dJ*8b^=Sf3qb@`pW zwj@>WM?c<2N)PPvMM=vr3|bXO9(k^`q9~t!DG)h#?t=pd^u=4u6~rAaWo&KVH0TO9 z!J=V(#GTLeS=8NqEb*2Mj6a?S?}}H!g*it=NyX=g|1(+8R-6HYBrX0${t5o*;sN}d z;whL~Zi%b=M=*zsdwkCy7g&bf7cK=I$LbXx;x7YZg?gTVm6R!AQz~xq=FLN;D(SbG zi^hDmwKoPPyzC^ioR6%&bB{E9c)0XiMgbRkZlGAcN`t-rGeTUSp@U8GlSy$AgChOE z5ssZUYbwUsG|rqd6LbXYZ96)aT~pjA7c zPQSbeyEN;$N9N0^K8%z89xR6AjwaFxt+L|yeY3<9&I&rs@h7NNejCOr%CTDkGsV>- zH)DR!7*>>hoib5acl+DZpYm%gJ200|wf+t&rxS2qzd`KU*LHgGegvo`6Nq}%@pV$V z`0n=uFzTW%T^l+Yy#2Jqm+bpW=8j6^Bxh{UNv;yY3*X~-D=mz?+8^bf?GradJ^-8U zSUUb@xcExaKhEn)FLVCx0eaVk@BaC8Hb=S^YM&}o*hYWm>fp^hN&{h}+6?haxl)`z zKaM@=PNYTd1DI>CHf+7Wg4yezh3Lm;uu|nYoEth#oT{ga3cKe+mq0K*Dsw-4c zKDI#D)dRR{(O6V>7$+#7W${44TTFXs4t;}nuyHO*kT~KHC+!C;M|lVQ+qhO*&=idY zEj!6oNkLpPJ)P`BL)bF4BHZuejRyk1VQXJG49;Mz`^IgINKq%LfCZYPorsyfRrflx{DycK z9(Rm(#EP)c-eF&%)LL9 zsiew4jIw|M@jl9GOoiEJ(EvDi<`fi6pDe!JoGqFb9Sw;c3_E=z(XV+8Gb)Utl&4?V zlza&uv73lb5<*zckCFIFeZN?Ckey;J<- zr3L@1U7t1CXfSwJ3U=}~Qj^LlpZ?Ev}`q{+Z&ciXU#Z3+djA9 zrPrBoIZ0K#N&H(p^M36zd72U7>G}8CeeYFukpigeKvXgM`#g{2$5aIoK?~h ztebw6<$YD-i#83wfvdIIXFFN0@ZKsmXTWdxFPn!&)+3?AN_m z6%q`yRW9PUORu2Ia6ScVsfin$FOb&H1U#TPTr8`2gIZ)xSG_*r27Xvb7;>5I|Lc$E z2JXaXj~;{Fil;2=;vSkY!Cn01$|9~TGLXOfX^l`hIZKBtJ_@t?9h_Uv9c;a)i0>Yy z;TG3+l-S0Sn&&h;rf4HJ8dptcE)8ZM+EYkonk=lmbrSB5R$wY465y7yhj`5IRXFDG zMM?WEqTWPT*pT-PN?g3y!Ie7F)CoI4TkqPfZ0z29PFISn?mx>{c}B)?#+)wrt71G3>(=VOBZu1E-{=%f`3N#-+V4 z_#?GHsVYc^^*i;RPcGh1-{%{_Y7ZTpSv?B-p18x#Zj%!?Pv|E-`(eIR^}}-3b?z+M z@gJ*xep40ByEEBwmGR8dPhISpIvq|a7twzaEAWqtHLKrpm9>?G@jf-X;FFIoolUnF zk0`Q)!N0xVm+FEkr$dfUp6FD9Pd}CYzD&HE)!ap`+?9uhm z98-+JKN~sAx(%%P=wG1BKGGA8fxN{IUHmGS$A0(xCL701AX=i$|CpFVAuf58-l@P^ zr~i|P4;*C?d2h-3?hi@PgWXVkPgcAxwN!lnc?DfPC&#RM9`kiahq3wHk!-kcK3h?w z4sYHKXEr*K@T+eq^nP__u@|S|E%y&l@Y@0(x~-rc24ej1@GKP9Yf;W|ea_iC2l5_l z#JH^7BY8;Wfs{%YS{zdVUKX4^l0gDa7t0ZHEyST!){MjA0 z0vc+fpd5U}TPZN%XUR+)ZbV)iBVpI-W>nFUV+Vw2!$I|2%5+P^;64Truq&P#{qrf$ zS&qrCyGN?QvGA^YB)9#W7-a@ZMS;>rprw|0BFvZ@tGke!w&?{dAI0G?uP<=?%@(@8 zu!joA4ZvwKa`GK6ywxBc?s^AUf_K6bi^>%Y_CU0gJZdpKQ zfz(kn=Qn7*R>A1?OC_?Aj?D7TVfZmllQIq+U`vCR;Ds(NUT=R0&EoFTxZ&p@JIDe@ zxr6wwFqvnroDWA0*{JbRze!z)H_z&jIs*@pX_{5aVw@aJkg zw`1ZgnxL-3t#w*VhN(;7{pu@dS=I(yGBdcvuQpP{zI005Isq3i97`#I&$%F!^4;Fs zVeyY|eCi`he7VPhb-xZ~W?Dnh%`p}SCdX2bMJHXzP=*~p$}#ltVqP+|gA4DgBRWw( zk&RlB#ByF7gUtGa^igID8#c5MZNI(e*F6}4kKz_{Q`f}9tmboI-)M&Ro`P=6OO0){ zy9hgI9l9+Vi6M_v@ZGy`W={@ilpDhaZ!P2wI!}O;$9&k6T5q;NVuw?j$KkImEpRU} zW^x7Q5MJw`1fPJcgp#h>)z9yY(_tJ?!(yHkjU-h0(v{VaMYRid&t?u5>o=OAMA_UY7~3nwdop@{{S$@^ZdCOPG}? z2SWQ*37r)7_YH@vFl_ZWe3aw^R}adfT;Vb<{>Be@Yqtq!oh^auLy~bBw*V(stK&HF zd%k5sGdPJ;Xvuvu_I0@t{?w|3H9ybrQuPJ+P`6cdca{rZ6Pkj~!y{26M_4~TchRc; z%INiSE&CI)k1Y?M%YM9gL$4e&FgkDxY2F0z|6qI|%avufWR8V_a{FA*Kvi1lv0{Fe{^TG%mkgRO|PPPG_ux zEHPoz^?h)3iW2)TbvLHkHE;)(L_*ky3vlUqBW-DX>!?4+fX2_WW7bJ4Sc>;_O!2jV zDZ*^Zccrw-@!}e6I;D=Tu};t^F9pSZ`E>rlYu@#898g&{?>BB6ed#<*_uk%R-cxUK z?rU`f%`t~to9>H3I={fI-?#apeN52%vkNZ&)c(T-?LIT{aPb`MlQ|qVy3NG;){BxS8{hIy`>ya6vK&NO z4`Zi2MK~(72444{#$+yz1>0U(R&1|{E!Rqk8i#O)FS_$OrzWz7pevFcQ>NjVDpj`p z$}hCpvzF}-n1hceEri!I)Zn2>2Ag&69JwWzvatQv*vUE5;lv7S7Etn2G|&40seBuR z=5sIbeZtbUpN6H?uJ%DVlx?xcuT&EmH72K znQTGN5@zjvhUS^Iaf3ED3v){W?<_sS_kCId4Z?bpbhVHlb>$AT*J%ZVk{&Gj*eiM$ zt&7+E4EVDe2dGZ54;v_1!8YAwlu|pFotk5WeCID1=~5s$*AU9Ld(I)7e*2;IDTlTT zCgc9I2Pt~|Wq3AuJ-5}CXrIgswkqN=ghmX(_Zbhs`t@!qjp~7Iu5ncN<2!wBIznb{ zk05fW2-|DwAxA!*p5-oL)BSWX+G7(lyJy4xCf|U!F&UH>zKMD!%j5T_d2IRqd@`La zsKS;6!tOs`q1xL3ld2cf)wZc@?0gkW_cdjmMH$!n`Ddi zPLRaQ(Pho4^lfcE72bBi=#om>>lea5U$YuFb@XF1j!egg7p?G}+;V){rNb_S7P8!D zBXHPL-$06W^0fiyAaKN+`wp z5*KX{M=MST@*nw$eABvl^sVO<46@N@%hcugvrjAe^OACY?!8r*{HdM}nGO-MKyL8I zXbUEt>7b=w3iwAlv#K&B-u$729FWyC!UvA=G-di_c)xHdtFbbo*|S|yds99zs}8Q= zj}nB5UcgJXhi*L=?m4H5;mNgrc-L?ho-u2sjPZg-!fh5#91%t1mmY;~6CGOMdy;Er zpJ?xU4s{PJVb->ToTbh#QvZ_0c~vC~nvbR2@b-Z$$7493zkDzA4fNs8>HY?@VS)5- zk3S4n8!efc7tUSFA3_i9`oYAkCi*)+h|cV;q*lvin4HndPaC*c^dWR6s%-0nC%Zgg zid8Ap{AmY=S~uocKb47h>f&xeYqn@jB~|n_he02{fZr;8yglzIP4P2CS=&l_i=2Ak_1g%%=S!pc&iWO>P4^-tsI+? z{R`HgdJpC`CrDk*0Iv<|h6rOzI&aj=+x3ZJ=bMjG%}*hBkU5jVpc8yt zHD6Ivjt0vb0PN@SBA73y#WYI}(_PM%yvfsijYfF) zYz=f=&!l!zhb`+s$XK?+)Lg{v$x77FN6h8d*YVb#49JpN>&kvq9QZ#ndI`&IdK}788Lxnv>+v7U!fRh;I zADjZ8+skQdbrRmo-i~j+Nh$yIebL7V5$Topp@YuJ0K(^K4(Z|5EgbQ<&uSWeJr#=A zwQ_n!4P;s}0(QA2(9uiApmDAb>Mr_@;RTN&wgKaJ3PdbIvTH*pok}kc(X39G^%QpvBcd|A?D{+*XFdrlfl3l>DO#f!ht za`RyJV4k@oE^IA}JJi5i{*h9_&d-pnEyER*PG*12hq5^*GT@bIGQZNyMf7t^A*{XL z3u`ikrh36b*!I%`!;TxOuI=We9pyWGDu?$9~*GKF8<&EG9m z!#;DJVX0j(*ew}`+a9h%2gd<8>2Wz1(G|^2<_}P7{7|Ufc!E`1y3_S}w<*Y`jb1Es zAnj*saI<4IT>B@_Ebs56A^WbwrTY(H@P#1O60e3D)lb0Vs1LhYwF^YslHiA@KivB8 zkQ%~`*+F*&KFIh!?OYzqnXYQao6A2@o!Ty@bm$(fim}4A3v)T?l4v|QLZ7)+j^)NR z2|118axP5FVD-xwQPLfT0TmmtI#Cy1%^k}B(DlcEPXp+&RS>T2*v{0)E8&q* z7P|B+mtVEe7T&LtW1kbMV6WptK6AMNld5&|Ho|@A<`^c5UH=tV1o4=2$-2rEe9dN;^ zoAlW6F5MV;oNIjL#R96A;=Y?2xc+)Po^jNnXR{Sp!>@esp7xo$4F9n`H#VWQl_mK2 zDiCkgm-T0*qV+}l&~uQoIA_3qYMZ|TXUNQ9!O3PU_pd#gY_W#JEwSM4J``sxRiN3& z+Nu3&0vd`>aOcl1!5_Ec;B{yc`jyUO1`=C#GiE58CVQBz7;TKl1r&^)!&p4@SsA0w z*Rz9Xqsb(G03%^GBUv>Wms!20I`uO4UE7D{Y*)Z?$JOkK%NckSzmy3(7Pi;$CT-bb z$@Q!|z`7TPn`#e^|$N4*; zbz1-{id_n&35WQGCzgVWt_d6#Xp2V=jlxFZPG+@N7E7}Ec zV67_KoNtD&zy5|TW&uLkN<%u;t&J`&3JGC3&kKbeV;k7!N#%e~_sq7gm5 zEcwYMI-Bgt<~^E+Uv_v4I?>g*d%v}KOQ9U5HOIr;`R&vcpUsx|e`kqKowUEeOKfJ* z%iSEPh$H*7!lkGxE>m6~pZ%)iJI>$2!5b`SWz>4|KHb93PbtHP8uO_p%AW$KT;OM1 zTm@au225eAGb?jlMf;bk;+2nE&{Hv;Vy~);qsQ>zQxebK{LKbSmr^Vi^ogf_M8aDk zroD1LK#giBs5Elb^qw3lCuKwsVx)8UtO@e+ag!!%*;aNii-3-{v zbQ%|PHbJWN-Q^CJuJ(kr;T%8ocP>S(8i{l4qA|AeD!c0{X!%@zQ@fu7HO>m4GA%D2 z%Ex2GzfS(&o<_2Wawby`7p(Yr8lJzir1Z4Mq>y_W8deODR{Ygve_PJ6$)D=DkZ(i9 z=}wtguvJhqZMn(M&Pv0yrRUgPzCV*5ii4;UWf(Is6FZLz&(!D^8hqy&dT1v=dW4+x z_n=3-%-%dqIQE`XiYOw3fD_p7b1^BIb%W323NpLCmUFkZ6`&86%;91oH97qg^?zoL z+vg>AP&sX?t0$vObBr%}%k>^N##`CVeB8U?_@-tY+iTSeSMGBBG}rBP zwc;}U%~rt557qpXd&m-ly) z`(}mF85O`r6vL11T}bPqaO%qQ(D01|+!{l7?HgcZt{<$(3}X()$M~O#&1{@aHs_~5 z9AVcBiupI6DMSiAfm2iIa*-bDeoet&Udu7!LkldJ_K=$94H9j1*MQqsuCn9JxiIKY z2|d4_#&p~VagWw1v!=!raMCNm4Jo5=sYe^7y=sI7i^i~LThCB+Kn?eM`&llRABY+n zvuQ=}GhVvJ9le@EFu!e{}D_jrASke@$w zpEajFgcpBzaqdaB80zqh9Of61rO<5g8ytj2T_@S&sw9$V*TaJjJ-%Ll0vvx@Mx5Jw zC^V{qm9u(9uubU9{D>s&EqWBAI)F**eK0KVBD0EA5r3I68{0N2QK(%3yKX)a{GH55 z@8%HpX0Icg@!1l;91W&Vq5ok>b`n=IRD*pIdPyEXg4p;Q!K~lkCv-{UC)I?M^F_LRBjz8Ss%kA?r{6IH%5&#(-(IyT|LW=O>`3SUzyy{twUJnx06&?=*E0| z%qcDU6X)(Wk1f%@$?oPZV+)Q&vWaeDoMYaIbqQmIan5U@-R>xw#NC8b7V8*Y?PLbi z9g3l z2~8~#Iqj0i*L(lq)5t_-eL9h){tBi3ew#40k>kIljCZWJP{HrTy@dW!w#Di-6b;ye z@*YA4-Ru@6Z~9DHr~9zty7QvI$N{*s%mPeLPRHwWLviuXX>4VAGz@uE2Qz;}!SZEm z(ZyDu&77}{9q&v~BUY6aE?ABy)jIK`yAPEeUxVv^ET!(oleE^3!JR#brE#aQ`1(Dv z4?ZOt{bCpbw!ES5Z|ip7^P3nBKYf`C%5<;`moY38dayj+yWW{)=& z&iiB7e;Qd(G;9{m9HA`!+FnJEN_ZA;t%Mps-m;;8lbPX($z)l*fek8{f#pg z@xumBc0pzbOnZ037BT03G^`$cRTrwnrq9P!@9amWW4U`FyZJlmDe zd?$T`nxP}4<)$?lduIvk@Q8(bdWr0sK?JjyB5@ov=N~LrYsB5<4^e*EZMyCmEp!En zdFPt!ho+DOOP+7JY}1PxByW&2;vlY&Xq#bA|Z5+o&jR7t1fa&r!B5 z`y;69HMJFRl4L$B7XsvQyC=Z+J?7XEx)DrVS5V(8GF57&Kgh04l{yzR2)X;dRI;xN z(ia4R%nwy@#SIBR@us#^**$@nRv!46J^@|xm$3SbJ>|$rsW3PQ|Ag*g*Ay!0x%C7Z zFj9ftO!K5>eSJ1TF$jx?EMduKroxAkXWZz?%`Cjz7-zeBW1_j6ko}tm*;o6B)mxMB z>55Va8DN6P(}`;;{v!!JRZd;KD=}uwB~1S4!0r6k2(k4gsPAvU92U0;+1Z6`-ZVA( zmVT^?`)jjTs|f4eoI!r$JsiAqHYPVn`P~j1*e3yF{Ks3HtrpJf7yfb3zQ}^S zT$Xa5pSh#mm*)^@n#Q&IWwlkIC-Z&)i1bO`vF5_~lh-CI)L3dx2 zFEJxNXEO^LeGMW;&S$>H`|0QeZ{~ly1uI%_Q?=7orffQs3^Xrbk$M&cY;yrKVQ&2J zsw#V|eTb=hut8v=bl`#LO4yzSSgfWKS`68QGM{%tpUUs))4UezUuW!-NbNC>8 zbmRbdWgf=2H%5ToVKuU_vxk|YwcI>GQ}oSh6Z>#@EqlDI4K|jAvt_BT;N!RjEIE21 ze)M=P%u+gd{mMJ&($YmD-AcaLZVCRXS_)n(=dc{jDU@h*mkI)up-yHTYtzdHb(?1p zx59+2Gw6rG9fD?avz*Wg$YYZh-{B7w?8d~77M%HNEO+%pBs(;GfGDQrD*M^>f-hEW zqY4oRdlw?jnPboPCWT<)(TU=Yn8%#qlmFQL9XViFaDv27Oz>Hxn0YiF#IpvkXpg@Q zW*$i5?!Vi{>J_i?&r;(gS50T4%#vcZe9;WH!5LxEDK%Vr&_a@X*%)U!PN&ABZ8Xj& zklFpQ!?!1p%^1|lIk)=JA|G?)*WQ9fMehVkc{ta!ryP75S3}-VZ`$lNnO}b8Hcc_U zP5lQeiS^F8QmC*Vo&8=*W|bp3i-;8X93z4Lm!AS1d<(@+iX;$i`PNode7=&Sn6aN| zy|7G}u%dkGhirsLKh5wFPv)~pD7(LS#c4;iZ zol~!&c;R8<*K0?$!*r_n;LIb18hS%WbCh&;<5mzk$u`Qeo5{eWn^-Nr%U2 zF+(E6CwkQn7AEz(F@M0xg86CkcOv>k%M=9gR%mg9lnJlPt0=YJwGWJu^9tXDv z;-P6#xK*22wN(bjxZMPyr-qk(Ed^ji5zHA`1lFThpy%LHkT#?Pa{#{w15SLa z%oIAuF}D&GGL*YTOV{SZx>>2PZ%!2)Rjfo_$c!6KnvMrIt>io3XTYKM&7w;V&iuM< zWAXiYb?MW&woJZJmp_*Eh(Dfcf(f_3f~d=d<*DmIX~bRj-|RBx;c$EYXM==H|SuS5oz0{u%EL1rMX?&SZG>_r*?~AaMm8~;MdXkebYFa z{=@*n-l)RQwo>$3sKt7(sFBvjU99;?AlMJsO~=|a*@XcKOw&?PT&LGca?cXk)sX_! z!%rSt581JgOHEvk*$EW8p)yVoU|mb^LYlaf&y!$o zhYovLn?{pY3>Fo4Pe4VBeoW_}9lj5WMEOZK_`pvB`dQJG*F5|J%!`PwS1uw|>mW|= z@|4nPQ-(3yjwkl)p z@MzvZNe>V06_XZ=q2iK!K_fj@)ZH1uLJY2vc!DQ8psRw_?w9z)*9Rb}$Q`>&WJz;q zHu{I?vQr8&oZOhbkn&-)fN6gLO-4xji~w&;xh#?WVaR;F+Gykv3G%@`{8+-QZfQTHwh`5fu&uN3r5Z1j=7iazGk6*nqsBXYT zuDZhvy%XGE%tud1Tb)CjlLlh2c?b6+Pz5AY)%dhDZI<^T7QZR2#D!xUL1p<{aL?%r z)B6ZB@GHA$>P7*E7xv3NnhhtE`ry z&gD|C@xdx>t&Owf7?PdyWmI}c6Vk2g{pPYy(>$we7pvxZo3Xgw_k;IbN+D_y98xH;YC3~dzG)8rNqok`rzahOL^~} z*eZ3m%@Az3k)1v70|DO;Lb*pYvu=oCHT~=P)o1q+Kk^7)J*O8^XNXwj{Vc9vsy(WX z(uH9L=U}zu0R#@%#jSQa1`(e2keqsub*>)DmInvXf@vZ)Z+l;e*qg+ZViUNSakKDc z?lPD=>PwT5JH;TWCt zDWD2&wrb3Qk0$5t@#JH4?Z3&&RS8^9IwKG�Kb12PpEe9@rG1>*R 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


~cX3P7xMYGOPEqHRVi1dP{ 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