hnluo
2023-05-29 0acf868dbb02642348e3addfec8e56974facfc2f
Merge pull request #558 from alibaba-damo-academy/dev_wjm2

update asr recipe
21个文件已修改
35个文件已删除
13个文件已添加
1 文件已重命名
5369 ■■■■ 已修改文件
docs/academic_recipe/asr_recipe.md 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/academic_recipe/images/loss.png 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell/conformer/run.sh 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell/data2vec_paraformer_finetune/run.sh 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell/data2vec_transformer_finetune/run.sh 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell/paraformer/run.sh 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell/paraformerbert/run.sh 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell/transformer/run.sh 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell/transformer/utils/compute_cmvn.py 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell/transformer/utils/compute_cmvn.sh 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/conformer/run.sh 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/conformer/utils 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/data2vec_pretrain/run.sh 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/paraformer/run.sh 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/paraformer/utils 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/paraformerbert/run.sh 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/paraformerbert/utils 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/run.sh 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/apply_cmvn.py 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/apply_cmvn.sh 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/apply_lfr_and_cmvn.py 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/apply_lfr_and_cmvn.sh 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/cmvn_converter.py 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/combine_cmvn_file.py 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/compute_cmvn.py 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/compute_cmvn.sh 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/compute_fbank.py 171 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/compute_fbank.sh 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/compute_wer.py 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/download_model.py 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/error_rate_zh 370 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/extract_embeds.py 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/filter_scp.pl 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/fix_data.sh 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/fix_data_feat.sh 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/gen_ark_list.sh 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/gen_modelscope_configuration.py 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/parse_options.sh 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/print_args.py 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/proc_conf_oss.py 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/proce_text.py 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/run.pl 356 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/shuffle_list.pl 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/split_data.py 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/split_scp.pl 246 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/subset_data_dir_tr_cv.sh 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/text2token.py 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/text_tokenize.py 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/text_tokenize.sh 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformer/utils/textnorm_zh.py 834 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformerLM/utils 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformerLM/utils/parse_options.sh 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformerLM/utils/run.pl 356 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/aishell2/transformerLM/utils/split_scp.pl 246 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/librispeech/conformer/run.sh 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/librispeech_100h/conformer/run.sh 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/wenetspeech/conformer/conf/decode_asr_transformer_5beam.yaml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/wenetspeech/conformer/conf/train_asr_conformer.yaml 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/wenetspeech/conformer/local/data.sh 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/wenetspeech/conformer/local/extract_meta.py 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/wenetspeech/conformer/local/path.sh 补丁 | 查看 | 原始文档 | blame | 历史
egs/wenetspeech/conformer/local/process_opus.py 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/wenetspeech/conformer/local/text_normalize.pl 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/wenetspeech/conformer/local/wenetspeech_data_prep.sh 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/wenetspeech/conformer/path.sh 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/wenetspeech/conformer/run.sh 223 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
egs/wenetspeech/conformer/utils 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
funasr/datasets/large_datasets/dataset.py 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
funasr/utils/prepare_data.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/academic_recipe/asr_recipe.md
@@ -12,7 +12,7 @@
Then you can directly start the recipe as follows:
```sh
conda activate funasr
. ./run.sh
. ./run.sh --CUDA_VISIBLE_DEVICES="0,1" --gpu_num=2
```
The training log files are saved in `${exp_dir}/exp/${model_dir}/log/train.log.*`, which can be viewed using the following command:
@@ -26,15 +26,18 @@
... 1epoch:train:801-850batch:850num_updates: ... loss_ctc=107.890, loss_att=87.832, acc=0.029, loss_pre=1.702 ...
```
Also, users can use tensorboard to observe these training information by the following command:
```sh
tensorboard --logdir ${exp_dir}/exp/${model_dir}/tensorboard/train
```
At the end of each epoch, the evaluation metrics are calculated on the validation set, like follows:
```text
... [valid] loss_ctc=99.914, cer_ctc=1.000, loss_att=80.512, acc=0.029, cer=0.971, wer=1.000, loss_pre=1.952, loss=88.285 ...
```
Also, users can use tensorboard to observe these training information by the following command:
```sh
tensorboard --logdir ${exp_dir}/exp/${model_dir}/tensorboard/train
```
Here is an example of loss:
<img src="images/loss.png" width="200"/>
The inference results are saved in `${exp_dir}/exp/${model_dir}/decode_asr_*/$dset`. The main two files are `text.cer` and `text.cer.txt`. `text.cer` saves the comparison between the recognized text and the reference text, like follows:
```text
@@ -177,7 +180,7 @@
encoder: conformer
encoder_conf:
    output_size: 256    # dimension of attention
    attention_heads: 4  # number of heads in multi-head attention
    attention_heads: 4  # the number of heads in multi-head attention
    linear_units: 2048  # the number of units of position-wise feed forward
    num_blocks: 12      # the number of encoder blocks
    dropout_rate: 0.1
docs/academic_recipe/images/loss.png
egs/aishell/conformer/run.sh
@@ -85,14 +85,14 @@
if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then
    echo "stage 1: Feature and CMVN Generation"
    utils/compute_cmvn.sh ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config $asr_config --scale 1.0
    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
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/char/
    mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/
    echo "make a dictionary"
    echo "<blank>" > ${token_list}
@@ -130,7 +130,7 @@
                --task_name asr \
                --gpu_id $gpu_id \
                --use_preprocessor true \
                --token_type char \
                --token_type $token_type \
                --token_list $token_list \
                --data_dir ${feats_dir}/data \
                --train_set ${train_set} \
egs/aishell/data2vec_paraformer_finetune/run.sh
@@ -88,14 +88,14 @@
if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then
    echo "stage 1: Feature and CMVN Generation"
    utils/compute_cmvn.sh ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config $asr_config --scale 1.0
    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
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/char/
    mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/
    echo "make a dictionary"
    echo "<blank>" > ${token_list}
@@ -134,7 +134,7 @@
                --task_name asr \
                --gpu_id $gpu_id \
                --use_preprocessor true \
                --token_type char \
                --token_type $token_type \
                --token_list $token_list \
                --data_dir ${feats_dir}/data \
                --train_set ${train_set} \
egs/aishell/data2vec_transformer_finetune/run.sh
@@ -88,14 +88,14 @@
if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then
    echo "stage 1: Feature and CMVN Generation"
    utils/compute_cmvn.sh ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config $asr_config --scale 1.0
    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
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/char/
    mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/
    echo "make a dictionary"
    echo "<blank>" > ${token_list}
@@ -134,7 +134,7 @@
                --task_name asr \
                --gpu_id $gpu_id \
                --use_preprocessor true \
                --token_type char \
                --token_type $token_type \
                --token_list $token_list \
                --data_dir ${feats_dir}/data \
                --train_set ${train_set} \
egs/aishell/paraformer/run.sh
@@ -85,14 +85,14 @@
if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then
    echo "stage 1: Feature and CMVN Generation"
    utils/compute_cmvn.sh ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config $asr_config --scale 1.0
    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
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/char/
    mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/
   
    echo "make a dictionary"
    echo "<blank>" > ${token_list}
@@ -130,7 +130,7 @@
                --task_name asr \
                --gpu_id $gpu_id \
                --use_preprocessor true \
                --token_type char \
                --token_type $token_type \
                --token_list $token_list \
                --dataset_type small \
                --data_dir ${feats_dir}/data \
egs/aishell/paraformerbert/run.sh
@@ -89,14 +89,14 @@
if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then
    echo "stage 1: Feature and CMVN Generation"
    utils/compute_cmvn.sh ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config $asr_config --scale 1.0
    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
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/char/
    mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/
   
    echo "make a dictionary"
    echo "<blank>" > ${token_list}
@@ -141,7 +141,7 @@
                --task_name asr \
                --gpu_id $gpu_id \
                --use_preprocessor true \
                --token_type char \
                --token_type $token_type \
                --token_list $token_list \
                --data_dir ${feats_dir}/data \
                --train_set ${train_set} \
egs/aishell/transformer/run.sh
@@ -85,14 +85,14 @@
if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then
    echo "stage 1: Feature and CMVN Generation"
    utils/compute_cmvn.sh ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config $asr_config --scale 1.0
    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
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/char/
    mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/
    echo "make a dictionary"
    echo "<blank>" > ${token_list}
@@ -130,7 +130,7 @@
                --task_name asr \
                --gpu_id $gpu_id \
                --use_preprocessor true \
                --token_type char \
                --token_type $token_type \
                --token_list $token_list \
                --data_dir ${feats_dir}/data \
                --train_set ${train_set} \
egs/aishell/transformer/utils/compute_cmvn.py
@@ -27,7 +27,7 @@
        help="the path of wav scps",
    )
    parser.add_argument(
        "--config",
        "--config_file",
        type=str,
        help="the config file for computing cmvn",
    )
@@ -89,7 +89,7 @@
    #         var_stats += np.sum(np.square(mat), axis=0)
    #         total_frames += mat.shape[0]
    with open(args.config) as f:
    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)
egs/aishell/transformer/utils/compute_cmvn.sh
@@ -2,11 +2,11 @@
. ./path.sh || exit 1;
# Begin configuration section.
fbankdir=$1
fbankdir=
nj=32
cmd=./utils/run.pl
feats_dim=80
config=
config_file=
scale=1.0
echo "$0 $@"
@@ -29,7 +29,7 @@
    python utils/compute_cmvn.py \
      --dim ${feats_dim} \
      --wav_path $split_dir \
      --config $config \
      --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
egs/aishell2/conformer/run.sh
@@ -87,14 +87,14 @@
if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then
    echo "stage 1: Feature and CMVN Generation"
    utils/compute_cmvn.sh ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config $asr_config --scale 1.0
    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
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/char/
    mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/
   
    echo "make a dictionary"
    echo "<blank>" > ${token_list}
@@ -132,7 +132,7 @@
                --task_name asr \
                --gpu_id $gpu_id \
                --use_preprocessor true \
                --token_type char \
                --token_type $token_type \
                --token_list $token_list \
                --data_dir ${feats_dir}/data \
                --train_set ${train_set} \
egs/aishell2/conformer/utils
@@ -1 +1 @@
../transformer/utils/
../../aishell/transformer/utils
egs/aishell2/data2vec_pretrain/run.sh
@@ -66,7 +66,7 @@
if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then
    echo "stage 1: Feature and CMVN Generation"
    utils/compute_cmvn.sh ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config $asr_config --scale 1.0
    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
egs/aishell2/paraformer/run.sh
@@ -87,14 +87,14 @@
if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then
    echo "stage 1: Feature and CMVN Generation"
    utils/compute_cmvn.sh ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config $asr_config --scale 1.0
    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
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/char/
    mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/
    echo "make a dictionary"
    echo "<blank>" > ${token_list}
@@ -132,7 +132,7 @@
                --task_name asr \
                --gpu_id $gpu_id \
                --use_preprocessor true \
                --token_type char \
                --token_type $token_type \
                --token_list $token_list \
                --data_dir ${feats_dir}/data \
                --train_set ${train_set} \
egs/aishell2/paraformer/utils
@@ -1 +1 @@
../transformer/utils/
../../aishell/transformer/utils
egs/aishell2/paraformerbert/run.sh
@@ -90,14 +90,14 @@
if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then
    echo "stage 1: Feature and CMVN Generation"
    utils/compute_cmvn.sh ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config $asr_config --scale 1.0
    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
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/char/
    mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/
    echo "make a dictionary"
    echo "<blank>" > ${token_list}
@@ -142,7 +142,7 @@
                --task_name asr \
                --gpu_id $gpu_id \
                --use_preprocessor true \
                --token_type char \
                --token_type $token_type \
                --token_list $token_list \
                --data_dir ${feats_dir}/data \
                --train_set ${train_set} \
egs/aishell2/paraformerbert/utils
@@ -1 +1 @@
../transformer/utils/
../../aishell/transformer/utils
egs/aishell2/transformer/run.sh
@@ -87,14 +87,14 @@
if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then
    echo "stage 1: Feature and CMVN Generation"
    utils/compute_cmvn.sh ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config $asr_config --scale 1.0
    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
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/char/
    mkdir -p ${feats_dir}/data/${lang}_token_list/$token_type/
    echo "make a dictionary"
    echo "<blank>" > ${token_list}
@@ -132,7 +132,7 @@
                --task_name asr \
                --gpu_id $gpu_id \
                --use_preprocessor true \
                --token_type char \
                --token_type $token_type \
                --token_list $token_list \
                --data_dir ${feats_dir}/data \
                --train_set ${train_set} \
egs/aishell2/transformer/utils
New file
@@ -0,0 +1 @@
../../aishell/transformer/utils
egs/aishell2/transformer/utils/apply_cmvn.py
File was deleted
egs/aishell2/transformer/utils/apply_cmvn.sh
File was deleted
egs/aishell2/transformer/utils/apply_lfr_and_cmvn.py
File was deleted
egs/aishell2/transformer/utils/apply_lfr_and_cmvn.sh
File was deleted
egs/aishell2/transformer/utils/cmvn_converter.py
File was deleted
egs/aishell2/transformer/utils/combine_cmvn_file.py
File was deleted
egs/aishell2/transformer/utils/compute_cmvn.py
File was deleted
egs/aishell2/transformer/utils/compute_cmvn.sh
File was deleted
egs/aishell2/transformer/utils/compute_fbank.py
File was deleted
egs/aishell2/transformer/utils/compute_fbank.sh
File was deleted
egs/aishell2/transformer/utils/compute_wer.py
File was deleted
egs/aishell2/transformer/utils/download_model.py
File was deleted
egs/aishell2/transformer/utils/error_rate_zh
File was deleted
egs/aishell2/transformer/utils/extract_embeds.py
File was deleted
egs/aishell2/transformer/utils/filter_scp.pl
File was deleted
egs/aishell2/transformer/utils/fix_data.sh
File was deleted
egs/aishell2/transformer/utils/fix_data_feat.sh
File was deleted
egs/aishell2/transformer/utils/gen_ark_list.sh
File was deleted
egs/aishell2/transformer/utils/gen_modelscope_configuration.py
File was deleted
egs/aishell2/transformer/utils/parse_options.sh
File was deleted
egs/aishell2/transformer/utils/print_args.py
File was deleted
egs/aishell2/transformer/utils/proc_conf_oss.py
File was deleted
egs/aishell2/transformer/utils/proce_text.py
File was deleted
egs/aishell2/transformer/utils/run.pl
File was deleted
egs/aishell2/transformer/utils/shuffle_list.pl
File was deleted
egs/aishell2/transformer/utils/split_data.py
File was deleted
egs/aishell2/transformer/utils/split_scp.pl
File was deleted
egs/aishell2/transformer/utils/subset_data_dir_tr_cv.sh
File was deleted
egs/aishell2/transformer/utils/text2token.py
File was deleted
egs/aishell2/transformer/utils/text_tokenize.py
File was deleted
egs/aishell2/transformer/utils/text_tokenize.sh
File was deleted
egs/aishell2/transformer/utils/textnorm_zh.py
File was deleted
egs/aishell2/transformerLM/utils
New file
@@ -0,0 +1 @@
../../aishell/transformer/utils
egs/aishell2/transformerLM/utils/parse_options.sh
File was deleted
egs/aishell2/transformerLM/utils/run.pl
File was deleted
egs/aishell2/transformerLM/utils/split_scp.pl
File was deleted
egs/librispeech/conformer/run.sh
@@ -97,7 +97,7 @@
if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then
    echo "stage 1: Feature and CMVN Generation"
    utils/compute_cmvn.sh ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config $asr_config --scale 1.0
    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_char/${train_set}_${bpemode}${nbpe}_units.txt
egs/librispeech_100h/conformer/run.sh
@@ -93,7 +93,7 @@
if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then
    echo "stage 1: Feature and CMVN Generation"
    utils/compute_cmvn.sh ${feats_dir}/data/${train_set} --cmd "$train_cmd" --nj $nj --feats_dim ${feats_dim} --config $asr_config --scale 1.0
    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_char/${train_set}_${bpemode}${nbpe}_units.txt
@@ -120,7 +120,7 @@
# ASR Training Stage
world_size=$gpu_num  # run on one machine
if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4; then
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
egs/wenetspeech/conformer/conf/decode_asr_transformer_5beam.yaml
New file
@@ -0,0 +1,6 @@
beam_size: 5
penalty: 0.0
maxlenratio: 0.0
minlenratio: 0.0
ctc_weight: 0.5
lm_weight: 0.7
egs/wenetspeech/conformer/conf/train_asr_conformer.yaml
New file
@@ -0,0 +1,104 @@
# network architecture
# encoder related
encoder: conformer
encoder_conf:
    output_size: 512    # dimension of attention
    attention_heads: 8
    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
    rel_pos_type: latest
    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: 8
    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
# CTC realted
ctc_conf:
    ignore_nan_grad: true
# 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: 4
grad_clip: 5
patience: none
max_epoch: 30
val_scheduler_criterion:
    - valid
    - acc
best_model_criterion:
-   - valid
    - acc
    - max
keep_nbest_models: 10
optim: adam
optim_conf:
   lr: 0.0015
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_nospace
    shuffle: True
    shuffle_conf:
        shuffle_size: 2048
        sort_size: 500
    batch_conf:
        batch_type: token
        batch_size: 32000
    num_workers: 8
log_interval: 50
normalize: None
egs/wenetspeech/conformer/local/data.sh
New file
@@ -0,0 +1,102 @@
#!/usr/bin/env bash
# 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
log() {
    local fname=${BASH_SOURCE[1]##*/}
    echo -e "$(date '+%Y-%m-%dT%H:%M:%S') (${fname}:${BASH_LINENO[0]}:${FUNCNAME[1]}) $*"
}
SECONDS=0
# general configuration
nj=10
stage=2
stop_stage=100
set=L
data_dir="data"
WENETSPEECH=
train_cmd=
log "$0 $*"
. utils/parse_options.sh
if [ ! -d "${WENETSPEECH}/audio" ] && [ ! -f "${WENETSPEECH}/WenetSpeech.json" ]; then
    echo "Valid WENETSPEECH data not found in ${WENETSPEECH}."
    echo "Please follow the instruction in https://wenet-e2e.github.io/WenetSpeech/"
    echo "and re-construct the data."
    exit 1
fi
train_set=train_"$(echo "${set}" | tr "[:upper:]" "[:lower:]")"
dev_set=dev
test_sets="test_net test_meeting"
if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then
    log "data preparation"
    mkdir -p ${data_dir}
    abs_data_dir=$(readlink -f ${data_dir})
    log "making Kaldi format data directory in ${abs_data_dir}"
    local/wenetspeech_data_prep.sh \
        --train-subset ${set} \
        --stage 1 \
        ${WENETSPEECH} \
        ${abs_data_dir}
    # prepare utt2spk and spk2utt files
    for x in ${train_set} ${dev_set} ${test_sets}; do
        dir=${data_dir}/${x}
        paste -d " " <(cut -f 1 ${dir}/segments) <(cut -f 1 ${dir}/segments) | \
            sort -u > ${dir}/utt2spk
        utils/utt2spk_to_spk2utt.pl ${dir}/utt2spk > ${dir}/spk2utt
    done
fi
if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then
    log "process the long term opus audio file, may take about 3 hours"
    for x in ${train_set} ${dev_set} ${test_sets}; do
        log "process audio for ${data_dir}/${x}"
        dir=${data_dir}/${x}
        mkdir -p ${dir}/logs
        nutt=$(<${dir}/segments wc -l)
        nj=$((nj<nutt?nj:nutt))
        split_scps=""
        for n in $(seq ${nj}); do
            split_scps="${split_scps} ${dir}/logs/segments.${n}"
        done
        utils/split_scp.pl ${dir}/segments ${split_scps}
        ${train_cmd} "JOB=1:${nj}" "${dir}/logs/process_audio.JOB.log"\
            python3 local/process_opus.py \
                ${dir}/wav.scp \
                ${dir}/logs/segments.JOB   \
                ${dir}/logs/wav.JOB.scp
        # modify the `wav.scp` file and rename the `segments` file
        # rename the `segments` file to avoid the audio file formatting process in stage 3 of `asr.sh`
        mv ${dir}/wav.scp ${dir}/wav.scp.org
        mv ${dir}/segments ${dir}/segments.org
        for n in $(seq ${nj}); do
            cat ${dir}/logs/wav.${n}.scp || exit 1;
        done | sort -u > ${dir}/wav.scp
    done
fi
if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then
    log "format text file"
    for x in ${train_set} ${dev_set} ${test_sets}; do
        log "format text for ${data_dir}/${x}"
        dir=${data_dir}/${x}
        mv ${dir}/text ${dir}/text.org
        paste -d " " <(cut -f 1 ${dir}/text.org) \
            <(cut -f 2- ${dir}/text.org | local/text_normalize.pl) | \
            sort -u > ${dir}/text
        utils/fix_data_dir.sh ${dir}
    done
fi
log "Successfully finished. [elapsed=${SECONDS}s]"
egs/wenetspeech/conformer/local/extract_meta.py
New file
@@ -0,0 +1,114 @@
# Copyright 2021  Xiaomi Corporation (Author: Yongqing Wang)
#                 Mobvoi Inc(Author: Di Wu, Binbin Zhang)
# 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.
import argparse
import json
import os
import sys
def get_args():
    parser = argparse.ArgumentParser(
        description="""
      This script is used to process raw json dataset of WenetSpeech,
      where the long wav is splitinto segments and
      data of wenet format is generated.
      """
    )
    parser.add_argument("input_json", help="""Input json file of WenetSpeech""")
    parser.add_argument("output_dir", help="""Output dir for prepared data""")
    args = parser.parse_args()
    return args
def meta_analysis(input_json, output_dir):
    input_dir = os.path.dirname(input_json)
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    try:
        with open(input_json, "r") as injson:
            json_data = json.load(injson)
    except Exception:
        sys.exit(f"Failed to load input json file: {input_json}")
    else:
        if json_data["audios"] is not None:
            with open(f"{output_dir}/text", "w") as utt2text, open(
                f"{output_dir}/segments", "w"
            ) as segments, open(f"{output_dir}/utt2dur", "w") as utt2dur, open(
                f"{output_dir}/wav.scp", "w"
            ) as wavscp, open(
                f"{output_dir}/utt2subsets", "w"
            ) as utt2subsets, open(
                f"{output_dir}/reco2dur", "w"
            ) as reco2dur:
                for long_audio in json_data["audios"]:
                    try:
                        long_audio_path = os.path.realpath(
                            os.path.join(input_dir, long_audio["path"])
                        )
                        aid = long_audio["aid"]
                        segments_lists = long_audio["segments"]
                        duration = long_audio["duration"]
                        assert os.path.exists(long_audio_path)
                    except AssertionError:
                        print(
                            f"""Warning: {aid} something is wrong,
                                  maybe AssertionError, skipped"""
                        )
                        continue
                    except Exception:
                        print(
                            f"""Warning: {aid} something is wrong, maybe the
                                  error path: {long_audio_path}, skipped"""
                        )
                        continue
                    else:
                        wavscp.write(f"{aid}\t{long_audio_path}\n")
                        reco2dur.write(f"{aid}\t{duration}\n")
                        for segment_file in segments_lists:
                            try:
                                sid = segment_file["sid"]
                                start_time = segment_file["begin_time"]
                                end_time = segment_file["end_time"]
                                dur = end_time - start_time
                                text = segment_file["text"]
                                segment_subsets = segment_file["subsets"]
                            except Exception:
                                print(
                                    f"""Warning: {segment_file} something
                                          is wrong, skipped"""
                                )
                                continue
                            else:
                                utt2text.write(f"{sid}\t{text}\n")
                                segments.write(
                                    f"{sid}\t{aid}\t{start_time}\t{end_time}\n"
                                )
                                utt2dur.write(f"{sid}\t{dur}\n")
                                segment_sub_names = " ".join(segment_subsets)
                                utt2subsets.write(f"{sid}\t{segment_sub_names}\n")
def main():
    args = get_args()
    meta_analysis(args.input_json, args.output_dir)
if __name__ == "__main__":
    main()
egs/wenetspeech/conformer/local/path.sh
egs/wenetspeech/conformer/local/process_opus.py
New file
@@ -0,0 +1,88 @@
# 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
import os
import sys
import torchaudio
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)
    step = int(num_utts * 0.01)
    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:
                waveform, sample_rate = torchaudio.load(current_wav_path)
            previous_wav_path = current_wav_path
            start = int(start_time_list[i] * sample_rate)
            end = int(end_time_list[i] * sample_rate)
            target_audio = waveform[:, start:end]
            torchaudio.save(seg_wav_path, target_audio, sample_rate)
            fout.write("{} {}\n".format(utt_id, seg_wav_path))
            if i % step == 0:
                print("seg wav finished: {}%".format(int(i / step)))
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()
egs/wenetspeech/conformer/local/text_normalize.pl
New file
@@ -0,0 +1,24 @@
#!/usr/bin/env perl
use utf8;
use open qw(:std :utf8);
use warnings;
while (<STDIN>) {
    chomp;
    # remove non UTF-8 whitespace character
    if ($_ =~ / /) {$_ =~ s: ::g;}
    if ($_ =~ / /) {$_ =~ s: ::g;}
    # upper letters
    if ($_ =~ /[a-zA-Z]/) {$_ =~ uc $_;}
    # add "_" before and after each English word
    if ($_ =~ /([A-Z]+)\s+([A-Z]+)/) {$_ =~ s/([A-Z]+)\s+([A-Z]+)/$1\_$2/g;}
    if ($_ =~ /([A-Z]+)\s+([A-Z]+)/) {$_ =~ s/([A-Z]+)\s+([A-Z]+)/$1\_$2/g;}
    if ($_ =~ m/([A-Z]+)(\p{Han}+)/) {$_ =~ s/([A-Z]+)(\p{Han}+)/$1\_$2/g;}
    if ($_ =~ m/(\p{Han}+)([A-Z]+)/) {$_ =~ s/(\p{Han}+)([A-Z]+)/$1\_$2/g;}
    # remove UTF-8 whitespace charcter
    if ($_ =~ /\s+/) {$_ =~ s:\s+::g;}
    # replace "_" with a normal whitespace
    if ($_ =~ /\_/) {$_ =~ s:\_: :g;}
    print "$_\n";
}
egs/wenetspeech/conformer/local/wenetspeech_data_prep.sh
New file
@@ -0,0 +1,135 @@
#!/usr/bin/env bash
# Copyright 2021  Xiaomi Corporation (Author: Yongqing Wang)
#                 Seasalt AI, Inc (Author: Guoguo Chen)
#                 Mobvoi Inc(Author: Di Wu, Binbin Zhang)
#                 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.
set -e
set -o pipefail
stage=1
prefix=
train_subset=L
. utils/parse_options.sh || exit 1;
filter_by_id () {
  idlist=$1
  input=$2
  output=$3
  field=1
  if [ $# -eq 4 ]; then
    field=$4
  fi
  cat $input | perl -se '
    open(F, "<$idlist") || die "Could not open id-list file $idlist";
    while(<F>) {
      @A = split;
      @A>=1 || die "Invalid id-list file line $_";
      $seen{$A[0]} = 1;
    }
    while(<>) {
      @A = split;
      @A > 0 || die "Invalid file line $_";
      @A >= $field || die "Invalid file line $_";
      if ($seen{$A[$field-1]}) {
        print $_;
      }
    }' -- -idlist="$idlist" -field="$field" > $output ||\
  (echo "$0: filter_by_id() error: $input" && exit 1) || exit 1;
}
subset_data_dir () {
  utt_list=$1
  src_dir=$2
  dest_dir=$3
  mkdir -p $dest_dir || exit 1;
  # wav.scp text segments utt2dur
  filter_by_id $utt_list $src_dir/utt2dur $dest_dir/utt2dur ||\
    (echo "$0: subset_data_dir() error: $src_dir/utt2dur" && exit 1) || exit 1;
  filter_by_id $utt_list $src_dir/text $dest_dir/text ||\
    (echo "$0: subset_data_dir() error: $src_dir/text" && exit 1) || exit 1;
  filter_by_id $utt_list $src_dir/segments $dest_dir/segments ||\
    (echo "$0: subset_data_dir() error: $src_dir/segments" && exit 1) || exit 1;
  awk '{print $2}' $dest_dir/segments | sort | uniq > $dest_dir/reco
  filter_by_id $dest_dir/reco $src_dir/wav.scp $dest_dir/wav.scp ||\
    (echo "$0: subset_data_dir() error: $src_dir/wav.scp" && exit 1) || exit 1;
  rm -f $dest_dir/reco
}
if [ $# -ne 2 ]; then
  echo "Usage: $0 [options] <wenetspeech-dataset-dir> <data-dir>"
  echo " e.g.: $0 --train-subset L /disk1/audio_data/wenetspeech/ data/"
  echo ""
  echo "This script takes the WenetSpeech source directory, and prepares the"
  echo "WeNet format data directory."
  echo "  --prefix <prefix>                # Prefix for output data directory."
  echo "  --stage <stage>                  # Processing stage."
  echo "  --train-subset <L|M|S|W>     # Train subset to be created."
  exit 1
fi
wenetspeech_dir=$1
data_dir=$2
declare -A subsets
subsets=(
  [L]="train_l"
  [M]="train_m"
  [S]="train_s"
  [W]="train_w"
  [DEV]="dev"
  [TEST_NET]="test_net"
  [TEST_MEETING]="test_meeting")
prefix=${prefix:+${prefix}_}
corpus_dir=$data_dir/${prefix}corpus/
if [ $stage -le 1 ]; then
  echo "$0: Extract meta into $corpus_dir"
  # Sanity check.
  [ ! -f $wenetspeech_dir/WenetSpeech.json ] &&\
    echo "$0: Please download $wenetspeech_dir/WenetSpeech.json!" && exit 1;
  [ ! -d $wenetspeech_dir/audio ] &&\
    echo "$0: Please download $wenetspeech_dir/audio!" && exit 1;
  [ ! -d $corpus_dir ] && mkdir -p $corpus_dir
  # Files to be created:
  # wav.scp text segments utt2dur
  python3 local/extract_meta.py \
    $wenetspeech_dir/WenetSpeech.json $corpus_dir || exit 1;
fi
if [ $stage -le 2 ]; then
  echo "$0: Split data to train, dev, test_net, and test_meeting"
  [ ! -f $corpus_dir/utt2subsets ] &&\
    echo "$0: No such file $corpus_dir/utt2subsets!" && exit 1;
  for label in $train_subset DEV TEST_NET TEST_MEETING; do
    if [ ! ${subsets[$label]+set} ]; then
      echo "$0: Subset $label is not defined in WenetSpeech.json." && exit 1;
    fi
    subset=${subsets[$label]}
    [ ! -d $data_dir/${prefix}$subset ] && mkdir -p $data_dir/${prefix}$subset
    cat $corpus_dir/utt2subsets | \
       awk -v s=$label '{for (i=2;i<=NF;i++) if($i==s) print $0;}' \
       > $corpus_dir/${prefix}${subset}_utt_list|| exit 1;
    subset_data_dir $corpus_dir/${prefix}${subset}_utt_list \
      $corpus_dir $data_dir/${prefix}$subset || exit 1;
  done
fi
echo "$0: Done"
egs/wenetspeech/conformer/path.sh
New file
@@ -0,0 +1,5 @@
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
egs/wenetspeech/conformer/run.sh
New file
@@ -0,0 +1,223 @@
#!/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=3
stop_stage=5
# feature configuration
feats_dim=80
nj=64
# data
raw_data=/nfs/zhifu.gzf/wenetspeech_proc
# 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
set=L
train_set=train_l
valid_set=dev
test_sets="dev test_net test_meeting"
asr_config=conf/train_asr_conformer.yaml
model_dir="baseline_$(basename "${asr_config}" .yaml)_${lang}_${token_type}_${tag}"
inference_config=conf/decode_asr_transformer_5beam.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 "For downloading data, please refer to https://github.com/wenet-e2e/WenetSpeech."
    exit 0;
fi
if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then
    echo "stage 0: Data preparation"
    # Data preparation
    local/data.sh --set ${set} --nj $nj --data_dir $feats_dir --WENETSPEECH $raw_data --train_cmd $train_cmd
    mkdir $feats_dir/data
    mv $feats_dir/$train_set $feats_dir/data/$train_set
    for x in $test_sets; do
        mv $feats_dir/$x $feats_dir/data/
    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 0.1
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 "<blank>" > ${token_list}
    echo "<s>" >> ${token_list}
    echo "</s>" >> ${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 "<unk>" >> ${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 large \
                --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 wenetspeech \
        --output_dir $exp_dir/exp/$model_dir \
        --vocab_size $vocab_size \
        --tag $tag
fi
egs/wenetspeech/conformer/utils
New file
@@ -0,0 +1 @@
../../aishell/transformer/utils
funasr/datasets/large_datasets/dataset.py
@@ -148,6 +148,12 @@
                        if "key" not in sample_dict:
                            sample_dict["key"] = segs[0]
                        sample_dict['hw_tag'] = 1
                    elif data_type == "text_nospace":
                        text = item
                        segs = text.strip().split(maxsplit=1)
                        sample_dict[data_name] = [x for x in segs[1]]
                        if "key" not in sample_dict:
                            sample_dict["key"] = segs[0]
                    else:
                        text = item
                        segs = text.strip().split()
funasr/utils/prepare_data.py
@@ -185,7 +185,7 @@
        for i in range(nj):
            path = ""
            for file_name in file_names:
                path = path + os.path.join(split_path, str(i + 1), file_name)
                path = path + " " + os.path.join(split_path, str(i + 1), file_name)
            f_data.write(path + "\n")