为什么需要样本

神经网络模型的训练本质上是根据结果寻找最优解的过程,在这个过程中我们需要输入大量的样本以及正确的答案,帮助网络结构内部矫正自己的参数。

样本如何获取

speech_commands_v0.01下载地址,这里整理了数种常用的语音指令供我们使用,每种语音指令下大约有2300条语音数据,包括多种音色,不同背景噪声,具有普遍性。
sample.png

为什么要筛选数据

后面我用来训练的数据是16KHZ采样率,时间长度为1S的音频,但是上述类别文件夹下的音频数据可能存在8K,或者音频长度不是完整的1S,因此我想将不符合要求的数据筛出去,保留合适的数据,并以npy的格式保存在硬盘中方便后续读取。为此我做了以下工作:

  • 将类别文件夹下面的音频文件重命名,这样我可以方便的通过python读取
  • 读取wav文件,筛选出符合要求的音频,读取为numpy数组并将其保存在固定文件夹下
  • 通过修改audio_name = "xxx",运行脚本并且将所有的类别保存
  • 脚本如下read_audio.py:

    import wave
    import numpy as np
    
    audio_name = "five"
    len = 16000
    save_index = 1
    print("start.")
    for index in range(1,2300):
      audio_str = "../audio/"+audio_name+"/audio_"+audio_name+"_ ("+str(index)+").wav"
      wav_file = wave.open(audio_str,"rb")
      params = wav_file.getparams()
      nchannels, sampwidth, framerate, nframes = params[:4]
      if len == nframes:
          str_audio_data = wav_file.readframes(nframes)
          wave_data = np.frombuffer(str_audio_data,dtype=np.short)
          np.save("../audio/np_"+audio_name+"/"+str(save_index)+".npy", wave_data)
          save_index +=1
      wav_file.close()
    print("end.")

    为什么要提取音频特征

    我们当前的音频数据为时长为1S,采样率为16KHz的音频数据,也就是1×16000的一个矩阵,但是无论是对于人还是对于计算机来说,从这样的一串数组中发现特征是比较困难的,因此聪明的人类为了提取音频特征,根据人耳的声学原理,研究出了Mel频率倒谱系数(MeI-Freguency CeptraI Coefficients)简称为MFCC,它可以将一段音频数组转化为二维特征图,主要进行了以下步骤:
    mfcc.png

当然,关于MFCC的详细运行方式解释我不想过多阐述,你可以在其他网站搜索到,这里有一个我认为写得不错的博客,我在gitee上白嫖到了python版本与C++版本,你可以在我的工程项目中查看其源码。并且为了在嵌入式上运行,我根据C++版本重写了C版本,计算结果完全一致。总结而言,为了提取音频特征,我做了以下工作:

  • 使用python脚本读取上一步中的npy文件,提取他的mfcc特征,重新保存在硬盘中
  • 提取特征后,原来1×16000的音频数据转为10×49的特征图
  • 通过修改audio_name = "xxx",运行脚本并且将所有的类别保存
  • 脚本如下read_audio_mfcc.py:

    import numpy as np
    from mfcc import KWS_MFCC #mfcc.py需要和本脚本在同一目录下
    
    audio_name = "background"
    all_num = 2001   #索引到2000
    for index in range(1,all_num):
      audio_np_str = "../audio/np_"+audio_name+"/"+audio_name+"_ ("+str(index)+").npy"
      temp_data = np.load(audio_np_str)
      kws = KWS_MFCC(temp_data)
      mfccFeatures = kws.extract_features()
      u8MfccFeatures = kws.extract_uint8_features()
      audio_np_mfcc_str = "../audio/np_"+audio_name+"_mfcc/"+str(index)+".npy"
      np.save(audio_np_mfcc_str, mfccFeatures)
      audio_np_mfcc_str = "../audio/np_"+audio_name+"_mfcc/"+"u8_"+str(index)+".npy"
      np.save(audio_np_mfcc_str, u8MfccFeatures)
      print(index)

    我的代码比较凌乱,但是如果你能明白其原理,可以重写脚本并且整理出自己的样本数据,下一章节我将阐述如何建立的卷积神经网络框架,训练模型并且测试,将最终模型转换为onnx格式的模型并测试。

文章目录