zoukankan      html  css  js  c++  java
  • 语音激活检测(VAD)--前向神经网络方法(Alex)

    这是学习时的笔记,包含相关资料链接,有的当时没有细看,记录下来在需要的时候回顾。

    有些较混乱的部分,后续会再更新。

    欢迎感兴趣的小伙伴一起讨论,跪求大神指点~


    VAD(ffnn神经网络)-Alex

    tags:voice


    Documentation(README)中说现在的NN VAD方法比GMM方法效果好的多。

    Material

    Paper

    Interesting

    神经网络

    Alex

    Description

    VOIP(voice over Internet protocol)网络电话
    
    ASR(automatic speech recognition)自动语音识别技术
    
    VAD语音激活检测
    
    SLU口语理解
        获取输入语音信号的语义表示
        
    DM对话管理
        决定系统如何回复给定的用户输入, 其模式有多种:rule-based plan-based 基于增强学习的
        
    NLG自然语言生成
        对话管理器输出的是抽象表达,我们要将其转换为句法和语义合法的自然语言,同时考虑上下文连贯性。许多自然语言生成系统是基于模板的,模板的某些成分是固定的,另一些成分需要根据对话管理器的输出结果进行填充。(省略表达,句子聚合等。除了基于模板外还有基于统计的方式进行)
        
    TTS文本生成语音
    

    Install

    pyAudio:这是一个跨平台的音频 I/O 库,使用 PyAudio 你可以在 Python 程序中播放和录制音频。

    git clone https://github.com/bastibe/PyAudio.git

    flite:在linux下通过flite命令可以使用文字转语音功能。

    wget http://www.festvox.org/flite/packed/flite-1.4/flite-1.4-release.tar.bz2

    flite -t hello  //读单词hello
    flite hello  //读文本hello.txt
    flite -voice slt -f hello.txt  //换女声语音库
    

    HTK:隐马尔可夫模型工具包,HTK的开发也主要是针对语音识别的应用及研究。

    http://htk.eng.cam.ac.uk/download.shtml

    Kaldi:是一个非常强大的语音识别工具库。目前支持GMM-HMM、SGMM-HMM、DNN-HMM等多种语音识别的模型的训练和预测。其中DNN-HMM中的神经网络还可以由配置文件自定义,DNN、CNN、TDNN、LSTM以及Bidirectional-LSTM等神经网络结构均可支持。

    $ git clone https://github.com/kaldi-asr/kaldi

    SRILM:用来构建和应用统计语言模型,主要用于语音识别,统计标注和切分,以及机器翻译,可运行在UNIX及Windows平台上。支持语言模型的估计和评测。估计是从训练数据(训练集)中得到一个模型,包括最大似然估计及相应的平滑算法;而评测则是从测试 集中计算其困惑度。

    http://www.speech.sri.com/projects/srilm/

    pjsip:是一个开源的SIP协议库。PJSIP作为基于SIP的一个多媒体通信框架提供了非常清晰的API,以及NAT穿越的功能。PJSIP具有非常好的移植性,几乎支持现今所有系统:从桌面系统、嵌入式系统到智能手机。

    git clone git@github.com:UFAL-DSG/pjsip.git

    MorphoDiTa:自然语言文本的形态学分析。

    git clone git@github.com:ufal/morphodita.git

    python读.wav文件

    # -*- coding: utf-8 -*-  
    import wave  
    import numpy   
    import pylab as pl  
      
    #打开wav文件  
    #open返回一个的是一个Wave_read类的实例,通过调用它的方法读取WAV文件的格式和数据  
    f = wave.open(r"D:1.wav","rb")  
      
    #读取格式信息  
    #一次性返回所有的WAV文件的格式信息,它返回的是一个组元(tuple):声道数, 量化位数(byte单位), 采  
    #样频率, 采样点数, 压缩类型, 压缩类型的描述。wave模块只支持非压缩的数据,因此可以忽略最后两个信息  
    params = f.getparams()  
    nchannels, sampwidth, framerate, nframes = params[:4]  
      
    #读取波形数据  
    #读取声音数据,传递一个参数指定需要读取的长度(以取样点为单位)  
    str_data  = f.readframes(nframes)  
    f.close()  
      
    #将波形数据转换成数组  
    #需要根据声道数和量化单位,将读取的二进制数据转换为一个可以计算的数组  
    wave_data = numpy.fromstring(str_data,dtype = numpy.short)  
    wave_data.shape = -1,2  
    wave_data = wave_data.T  
    time = numpy.arange(0,nframes)*(1.0/framerate)  
    len_time = len(time)/2  
    time = time[0:len_time]  
      
    ##print "time length = ",len(time)  
    ##print "wave_data[0] length = ",len(wave_data[0])  
      
    #绘制波形  
      
    pl.subplot(211)  
    pl.plot(time,wave_data[0])  
    pl.subplot(212)  
    pl.plot(time, wave_data[1],c="r")  
    pl.xlabel("time")  
    pl.show()  
    

    train model

    生成.mlf

    1. 语音标记
      alex/tools/vad_train/data_voip/*.txt
    2. 生成.mlf
    "alex/tools/htk/bin/make_mlf_train.sh"
    #!/bin/bash
    WORK_DIR=alex/tools/vad_train
    TRAIN_DATA=$WORK_DIR/data_voip
    TRAIN_SCRIPTS=alex/tools/htk/bin
    LOG_DIR=$WORK_DIR/model_voip
    TEMP_DIR=$WORK_DIR/temp
    find $TRAIN_DATA -iname '*.mfc' > $WORK_DIR/train_mfc_files.txt
    python $TRAIN_SCRIPTS/CreateMLF.py "-" $WORK_DIR/train_words.mlf $WORK_DIR/train.scp $TRAIN_DATA $TRAIN_DATA'/*.txt' > $LOG_DIR/train_missing_words.log
    
    "alex/tools/htk/bin/CreateMLF.py"
    部分修改如下:
    for fn in fns:
        with open(fn, 'r') as f:
            lines = f.readlines()
            lines = ''.join(lines)  //把原本''中的空格去掉
            words = lines.strip().split('
    ')  //原本split默认按空格切分,改为按转行符切分
    
    # 运行
    ~/path/to/VAD/alex-master$ sh alex/tools/htk/bin/make_mlf_train.sh 
    
    #生成.mlf
    #!MLF!#
    "alex/tools/vad_train/data_voip/2.txt"
    0    19296    sil
    19296    37600    speech
    37600    57248    sil
    .
    "alex/tools/vad_train/data_voip/1.txt"
    0 14400 sil
    14400 23200 speech
    23200 49984 sil
    .
    
    

    训练模型

    "path/to/VAD/alex-master/alex/tools/vad/train_vad_nn_theano.py"
    # 1.train_vad_nn_theano.py
    # load_mlf改为
        #mlf.times_to_frames()
        mlf.bits_to_frames(16000)
        mlf.trim_segments(trim_segments)
        //trim_segments现在是0,可以修改为n(1/2/3)
        //表示删除end-start(帧)<=2n部分,较短部分不进行训练
        
    # main文件地址
        train_speech.append('alex/tools/vad_train/data_voip/*.wav')
        train_speech_alignment.append('alex/tools/vad_train/train_words.mlf')
         features_file_name = "alex/tools/vad_train/model_voip/vad_sds_mfcc_mfr%d_mfl%d_mfps%d_ts%d_usec0%d_usedelta%d_useacc%d_mbo%d.npc" % 
                (max_frames, max_files, max_frames_per_segment, trim_segments,
                usec0, usedelta, useacc, mel_banks_only)
        
    # 2.htk.py
    # .mlf中的bit值转帧(注意:窗口移动值是frame_shift,与targetrate相关)
    def bits_to_frames(self, sample_rate):
    	self.frame_shift = int(sample_rate * self.targetrate / 10000000)
            for f in self.mlf:
                for i in range(len(self.mlf[f])):
                    self.mlf[f][i][0] = int(self.mlf[f][i][0] / self.frame_shift)   
                    self.mlf[f][i][1] = int(self.mlf[f][i][1] / self.frame_shift)
                ## 后面的不加会导致错误4    
                # shorten the last segment by 10 frames as there may not be enough data for a final frame
                self.mlf[f][i][1] -= 10
    
                # remove the zero or negative length segments that could be created by the previous step
                if self.mlf[f][i][0] >= self.mlf[f][i][1]:
                    del self.mlf[f][i]
    
    # 3.log错误
     Traceback
     File "./alex/tools/vad/train_vad_nn_theano.py", line 316, in train_nn
        e.train(method = method, learning_rate=learning_rate*learning_rate_decay/(learning_rate_decay+epoch))
      File "/path/to/VAD/alex-master/alex/ml/tffnn.py", line 302, in train
        log_lik = self.f_train_ret_loss(mini_x, mini_y, learning_rate)
    
     TypeError: ('Bad input argument to theano function with name "/path/to/VAD/alex-master/alex/ml/tffnn.py:131"  at index 2(0-based)', 'TensorType(float32, scalar) cannot store accurately value 0.019801980198, it would be represented as 0.0198019798845. If you do not mind this precision loss, you can: 1) explicitly convert your data to a numpy array of dtype float32, or 2) set "allow_input_downcast=True" when calling "function".', 0.019801980198019802)
    
    # 修改tffnn.py
    self.f_train_ret_loss = function([x, true_y, learning_rate], loss, updates = updates, allow_input_downcast=True)
    
    # 4. htk.py 最后frame不足512个语音节点问题
    ValueError: operands could not be broadcast together with shapes (512,) (465,)
    # 修改(失败)
    MLFMFCCOnlineAlignedArray(MLFFeaturesAlignedArray):
    def __init__(+ framesize=512)
    self.framesize=framesize
    
    def get_frame(self, file_name, frame_id):
        if len(frame) == self.framesize:
            try:
                mfcc_params = self.mfcc_front_end.param(frame)
            except ValueError:
                print file_name, frame_id, len(frame)
                raise
    	else:
    	    pass
    	return mfcc_params
    //进行mfcc_front_end.param前先判断frame是否足帧,不足帧舍弃
    UnboundLocalError: local variable 'mfcc_params' referenced before assignment
    # 错误,当len(frame) != framesize时执行else后的pass,此时没有mfcc_params变量
    # pass改成exit()则会导致执行exit()时整个程序停止。所以放弃该改动方法。
    # 修改办法见代码2
    
    ## 运行
    $ cd /path/to/VAD/alex-master
    $ python alex/tools/vad/train_vad_nn_theano.py
    
    1. 为什么len(mfcc[0])=26
    2. 语音en和cs分别指什么————指English 和 Chinese

    使用模型进行检测

    "path/to/VAD/alex-master/alex/components/vad/__init__.py"
    #!/usr/bin/env python
    # coding: utf-8
    
    import sys
    sys.path.append("/path/to/VAD/alex-master")
    
    import wave
    import numpy as np
    from alex.components.vad.ffnn import FFNNVADGeneral, FFNNVAD
    from alex.utils.htk import Features
    
    def main():
    
    	f = wave.open(r"/path/to/VAD/sound/12.wav","rb")  
           
    	soundParams = f.getparams()  
    	nchannels, sampwidth, framerate, nframes = soundParams[:4]  
    
    	str_data  = f.readframes(nframes)  
    	f.close()  
        # wave_data = np.fromstring(str_data,dtype = np.short)  
        # ffnn.py文件中调用的是原始语音,是c语言数据格式,所以不用这一步。
        # ffnn.py中的struct.unpack进行数据格式转换,由c转换成python
        
    	vad = FFNNVADGeneral('/path/to/VAD/alex-master/alex/tools/vad_train/model_voip/vad_nnt_546_hu32_hl1_hla0_pf10_nf10_acf_1.0_mfr20000_mfl20000_mfps0_ts0_usec00_usedelta0_useacc0_mbo1_bs1000.tffnn', 
    			filter_length=2, sample_rate=16000, framesize=512, frameshift=160,
    			usehamming=True, preemcoef=0.97, numchans=26, ceplifter=22, numceps=12, 
    			enormalise=True, zmeansource=True, usepower=True, usec0=False, 
    			usecmn=False, usedelta=False, useacc=False, n_last_frames=10, 
    			n_prev_frames=10, lofreq=125, hifreq=3800, mel_banks_only=True)
    
    	result = vad.decide(str_data)
    	
    if __name__ == "__main__":
    	main()
    
    # 运行
    $ cd path/to/VAD/alex-master
    $ python alex/components/vad/__init__.py >alex/components/vad/output/output*.txt
    
    # 图形化
    $ gnuplot
    $ plot "/path/to/VAD/alex-master/alex/components/vad/output/output*.txt" using 4:6 title "*.wav:time-prob" with line
    

    (若非特别声明,文章是Vanessa的个人笔记,转载请注明出处。文章如有侵权内容,请联系我,我会及时删除)

  • 相关阅读:
    成长篇之代码灵异事件
    idea快捷键
    java环境配置常用链接
    MySQL分区
    English 动词篇
    仿stl+函数模板
    java 数组复制
    拓扑排序(Topological Sorting)
    2017蓝桥杯第十题(k倍区间)
    翻译NYOJ
  • 原文地址:https://www.cnblogs.com/Vanessa-Feng/p/7452016.html
Copyright © 2011-2022 走看看