美文网首页
一个语音识别例子记录

一个语音识别例子记录

作者: 习惯了千姿百态 | 来源:发表于2018-12-23 22:13 被阅读0次

    1.生成四个文件

    1.1生成utt.scp文件 [utt-id] [wav-path]

    将所有的.wav文件的路径写入文件中

    find /CDShare/Data/guangzhou/King-Tem-051/Data/iOS/Wav/ -iname '*.wav' > wav.scp.temp
    

    将路径中/Session0去掉,为了后面方便生成wav_id

    sed -i 's/\/Session0//g' wav.scp.temp 
    

    将所有wav文件的id写入文件

    cat  wav.scp.temp | awk -F '/' '{printf("%s_%s\n",$(NF-1),$NF)}' | sed 's/.wav//' | sed 's/Speaker/Speaker_/' > wav_id
    

    先删除wav.scp.tmp文件,因为之前删除了Session0.然后重新生成wav.scp.tmp文件

    将utt-id和wav-path合并到一个文件

    paste -d' ' wav_id wav.scp.temp> wav.scp
    

    1.2生成text文件 [utt-id] [text-context]

    将原始的txt文件拷贝一份到工作目录

    cp /CDShare/Data/guangzhou/King-Tem-051/Data/iOS/Script/* script/
    

    将编码转成utf_8
    script同级目录建立文件夹script_utf8

    for x in script/*;
    do y=`echo $x |sed 's/script/script_utf8/'`;
    iconv -f UTF-16LE -t UTF-8 $x > $y;done
    

    为每个txt文件生成text-id
    generate_text_id.sh

    #!/bin/bash
    file=$1
    speaker_id=`basename $file`
    #echo $speaker_id
    string=`echo $speaker_id | sed 's/.txt//' | sed 's/Speaker/Speaker_/'`
    awk -v spk=$string 'NR%2!=0 {printf("%s_%s\n",spk,$1)}' $file> /tmp/${speaker_id}_text_id
    awk 'NR%2==0' $file  >/tmp/${speaker_id}_text
    paste -d ' ' /tmp/${speaker_id}_text_id /tmp/${speaker_id}_text > /tmp/${speaker_id}.tmp
    sed 's/\t//g' /tmp/${speaker_id}.tmp | sed 's/\xEF\xBB\xBF//'>/tmp/${speaker_id}
    rm /tmp/*.tmp
    rm /tmp/*_text
    exit 0
    
    for x in script_utf8/*.txt;do ./generate_text_id.sh $x; done
    

    将所有的文件合并

    cat /tmp/Speaker*.txt > text
    

    1.3生成utt2spk [utt-id] [spk-id]

    cut -d' ' -f 1 text | awk -F '_' '{printf($0 " "$1 "_" $2 "\n")}'>utt2spk
    

    1.4生成spk2utt [spk-id] [utt-id]

    链接kaldi

    ln -s ~/kaldi/
    

    连接kaldi的工具

    ln -s ~/kaldi/egs/wsj/s5/steps/ steps
    ln -s ~/kaldi/egs/wsj/s5/utils/ utils
    

    通过kaldi的工具将utt2spk生成spk2utt

    ./utils/utt2spk_to_spk2utt.pl utt2spk >spk2utt
    

    2.data/lang

    生成lexicon
    [character/word] [pronunciation]
    例子:
    早晨 z ao ch en
    天气 t ian q i
    先获取word-list

    2.1去掉标点

    2.2分词

    找出所有的噪声表示:

    cat text | grep -e '<.*>' | awk '{for(x=2;x<=NF;x++){printf("%s\n",$x)}}' | grep -e '<.*>' | sort -u
    
    <FIL/>
    <FIL/>
    <NON/>
    <NON/>
    <NPS/>
    <NPS/>
    <SPK/>
    <SPK/>
    <STA/>
    
    <FIL/>
    <FIL/>^M
    <NON/>
    <NON/>^M
    <NPS/>
    <NPS/>^M
    <SPK/>
    <SPK/>^M
    <STA/>       
    

    编码格式有问题,用dos2unix转换格式

    dos2unix text
    

    发现text中存在空行,需要找出空行,然后删除:
    找空行,把空行前面的utt-id输出来:

     cat text | gawk '/[A-Za-z0-9_]*\s+$/'>bad_sens.txt
    

    删除空行:

    grep -w -vf bad_sens.txt text>tmp_txt
    

    接下来对tmp_txt进行分词:

    remove_punc.py

    # coding: utf-8
    from zhon.hanzi import punctuation
    from mmseg import seg_txt
    import re
    import sys
    for line in sys.stdin:
       #除去换行
        line=line.strip('\n')
        #去掉标点
        no_puncs=re.sub(ur'[%s]+'% punctuation,'',line.decode('utf-8'))
        no_puncs=no_puncs.encode('utf-8')
        #分词
        #将字符串按照空格转成list
        content=no_puncs.split()
        #第一个元素是utt-id
        out_line=content[0]
        #print utt_id
        #对剩下的部分进行分词
        for i in range(1,len(content)):
            #遇到各种噪声的处理
            if content[i] =="<FIL/>" or content[i]=="<NON/>" or content[i]=="<NPS/>" or content[i]=="<SPK/>" or content[i]=="<STA/>":
                out_line+=" "+content[i]
                continue
            else:#对不是噪声的部分进行分词处理
                for j in seg_txt(content[i]):
                    out_line+=" "+j
        print out_line
    

    将分词的结果存放在文件final_txt

    cat tmp_txt |python remove_punc.py >final_txt
    

    生成word.list(把每一行句子(分词后的)的每一列输出,然后去重)

    cat final_txt|awk '{for(i=2;i<=NF;i++){printf("%s\n",$i)}}'|sort -u>word.list
    

    修复处理过程中删除了一些空行,导致之前的几个文件不对应

    ./utils/data/fix_data_dir.sh data/
    

    text,utt2spk,spk2utt,wav.scp放在data/all目录下

    ./utils/data/fix_data_dir.sh data/ #修复文件行数不一致的工具
    
    ./utils/data/subset_data_dir.sh data/all 1000 data/test #从data/all中抽取1000条数据,放在test中
    

    构造测试集
    原始的数据放在data/all下,测试集放在data/test下面

    ./utils/data/subset_data_dir.sh --speakers  data/all/ 1000 data/test
    

    构造训练集
    首先获得test中的speak_id,然后在all/text中进行取反

    cut -d ' ' -f1 data/test/spk2utt>speak_id.txt
    
     grep -F -v -f speak_id.txt data/all/text> data/train/text
    

    然后把原始的三个文件复制到train下面,进行修复即可

    给训练集生成词汇表:

    awk '{for(i=2;i<=NF;i++){print $i}}' data/train/text |grep -v '<.*>' |grep -v '[a-zA-Z]'|sort -u >data/local/words.txt
    

    下载字典:

     awk 'NR==144' kaldi/egs/hkust/s5/local/hkust_prepare_dict.sh
    

    wget -P cedict http://www.mdbg.net/chindict/export/cedict/cedict_1_0_ts_utf-8_mdbg.txt.gz

    解压:
    gunzip XXXX

    获取词典
    modify_raw_dict.sh

    #!/bin/bash
    input=$1
    
    cat $input| grep -v '#' | awk -F '/' '{print $1}' |\
     perl -e '
      while (<STDIN>) {
        @A = split(" ", $_);
        print $A[1];
        for($n = 2; $n < @A; $n++) {
          $A[$n] =~ s:\[?([a-zA-Z0-9\:]+)\]?:$1:;
          $tmp = uc($A[$n]);
          print " $tmp";
        }
        print "\n";
      }
     ' | sort -k1 || exit 1;
    exit 0;                     
    
    ./modify_raw_dict.sh data/local/cedict/cedict_1_0_ts_utf-8_mdbg.txt >data/local/zhongwen.dict
    

    其实这个字典是有问题的,一般的词语是没有问题的,但是词典里面存在这种情况:



    如果不做修改的话,words里面很多的词无法匹配获得读音,因为words里面已经不存在标点了,所以现在的任务是把这些长的词语按照标点符号分开。
    pre_dict.py

    # coding: utf-8
    import sys
    
    for line in sys.stdin:
        line=line.strip('\n')
        if "," in line:
            content=line.split(' , ')
            c1=content[0].split(',')
            l=len(c1)-1
            c2=c1[l]
            index=c2.index(' ')
            print c1[0]+" "+c2[index+1:]
            for i in range(1,l):
                print c1[i]+" "+content[i]
            print c2[:index]+" "+content[l]
        elif "、" in line:
            content=line.split(' , ')
            c1=content[0].split(',')
            l=len(c1)-1
            c2=c1[l]
            index=c2.index(' ')
            print c1[0]+" "+c2[index+1:]
            for i in range(1,l):
                print c1[i]+" "+content[i]
            print c2[:index]+" "+content[l]
    
        else:
            print line
    
    cat zhongwen.dic |python pre_dict.py 
    

    把之前的words.txt中的词在词典中找到

    awk 'NR==FNR {dict[$0];next}($1 in dict)' data/local/words.txt data/local/zhongwen.dict >in_words.txt
    

    把words.txt不在词典的要找到

    awk 'NR==FNR {dict[$1];next} !($1 in dict)' data/local/zhongwen.dict data/local/words.txt >out_words.txt
    

    会发现一个问题,in_words和out_words的总数大于之前的words.txt,这是因为在获取in_words的时候,是把words当字典,然后扫描zhongwen.dict,zhongwen.dict中的某一条在words中就输出,正是由于zhongwen.dict中存在多音字和声调的问题,比如“啊”这个字在zhongwen.dict中就有四条记录,对应四个读音声调



    image.png

    其实此时的in_words.txt就是lexicon
    生成nonsilence_phones.txt

    awk '{for(i=2;i<=NF;i++){print $i}}' lexicon |sort -u>data/local/dict/nonsilence_phones.txt
    

    生成lang

    建立四个文件
    silence_phones.txt

    echo 'SIL' >> data/local/dict/silence_phones.txt 
    

    nonsilence_phones.txt
    extra_questions.txt

    touch data/local/dict/extra_questions.txt
    

    optional_silence.txt

    echo 'SIL' >> data/local/dict/optional_silence.txt
    

    lexicon.txt

    paste -d ' ' noise_list data/local/dict/silence_phones.txt >>data/local/dict/lexicon 
    sort -u data/local/dict/lexicon >data/local/dict/lexicon.txt
    echo '!SIL SIL' >>data/local/dict/lexicon.txt
    

    运行:

    ./utils/prepare_lang.sh ~/Desktop/part3/data/local/dict/ '!SIL' ~/Desktop/part3/data/lang_tmp data/lang
    

    提取mfcc
    工具 steps/make_mfcc.sh

    计算mfcc
    compute-mfcc-feats
    .scp文件只存放文件的路径,.ark文件存放文件的真实数据
    eg:

    compute-mfcc-feats scp:wwav.scp ark:1.ark
    

    得到目标文件1.ark是一个二进制文件

    compute-mfcc-feats scp:wwav.scp ark,t:1.ark
    

    得到的目标文件1.ark是一个文本文件存放的是矩阵
    计算这个矩阵的维度:

    feat-to-dim ark:1.ark -
    

    mfcc是啥???

    并行提取train/test MFCC特征,CMVN

    make_mfcc.sh使用例子
    首先从test中选择100句

    utils/data/subset_data_dir.sh data/test 100 data/foo
    

    建立exp文件夹,存放输出的log文件

    mkdir -p exp
    

    建立.conf文件

    vim conf/mfcc.conf
    内容:
    --use-energy=false
    

    提取mfcc

    ./steps/make_mfcc.sh --mfcc-config conf/mfcc.conf data/foo exp/extract_mfcc mfcc
    

    提取的mfcc就放在mfcc文件夹中


    .scp文件可以直接打开查看,但是.ark文件是二进制文件,无法打开,可以进行以下转换,转成txt格式
    copy-feats ark: raw_mfcc_foo.1.ark

    //25:53

    训练语言模型,ngram工具:srilm

    ~/kaldi/egs/hkust/s5/local/hkust_train_lms.sh
    

    训练语言模型的一个例子:

     cut -d' ' -f2- data/train/text >data/train/text_no_uttid #只能是文本,不能有utt_id
    ngram-count -text data/train/text_no_uttid -order 3 -lm data/local/lm
    

    训练monophone

    未完待续。。。。

    相关文章

      网友评论

          本文标题:一个语音识别例子记录

          本文链接:https://www.haomeiwen.com/subject/quaikqtx.html