当前位置:   article > 正文

python+keras实现语音识别_基于keras和python的语音识别

基于keras和python的语音识别

市面上语音识别技术原理已经有很多很多了,然而很多程序员兄弟们想研究的时候却看的头大,一堆的什么转mfcc,然后获取音素啥的,对于非专业音频研究者或非科班出生的程序员来说,完全跟天书一样。

最近在研究相关的实现,并且学习了keras和tensorflow等。用keras做了几个项目之后,开始着手研究语音识别的功能,在网上下载了一下语音的训练文件,语料和代码已上传到了:链接:https://pan.baidu.com/s/11u_f53bF2JoXloIszj9-Sg?pwd=xaf6
提取码:xaf6
目录如下,文件夹名就是里面的语音的标签,语音由很多不同年龄性别的人发音收集而来。

拿到一个语音文件之后需要先转mfcc,这个操作很简单,不需要什么高深的内功。用python写一段函数专门用来获取语音文件的fmcc值。

  1. def get_wav_mfcc(wav_path):
  2. f = wave.open(wav_path,'rb')
  3. params = f.getparams()
  4. # print("params:",params)
  5. nchannels, sampwidth, framerate, nframes = params[:4]
  6. strData = f.readframes(nframes)#读取音频,字符串格式
  7. waveData = np.fromstring(strData,dtype=np.int16)#将字符串转化为int
  8. waveData = waveData*1.0/(max(abs(waveData)))#wave幅值归一化
  9. waveData = np.reshape(waveData,[nframes,nchannels]).T
  10. f.close()
  11. ### 对音频数据进行长度大小的切割,保证每一个的长度都是一样的
  12. #【因为训练文件全部是1秒钟长度,16000帧的,所以这里需要把每个语音文件的长度处理成一样的】
  13. data = list(np.array(waveData[0]))
  14. # print(len(data))
  15. while len(data)>16000:
  16. del data[len(waveData[0])-1]
  17. del data[0]
  18. # print(len(data))
  19. while len(data)<16000:
  20. data.append(0)
  21. # print(len(data))
  22. data=np.array(data)
  23. # 平方之后,开平方,取正数,值的范围在 0-1 之间
  24. data = data ** 2
  25. data = data ** 0.5
  26. return data

参数为单个文件在磁盘的位置,mfcc是一堆的正数和负数组成的数组:

 

 为了在训练的时候避免损失函数应为负数导致输出结果相差太大,需要把原始的mfcc全部转为正数,直接平方后在开方就是正值了。

 我们可以把每个音频的mfcc值当做对应的特征向量,然后进行训练,我这里为了测试速度,取了seven 和 stop 两个语音类别来进行训练和识别,每个大概2700多个文件。并且分别从两个文件夹中剪切出来100个当做测试集,并每样拿出5个当做后面的试验集。

test1 中放置的是 100个 seven 语音,test2 中放置的是100个 stop 语音,trunk中放的是5个seven 和5个stop 语音。

如图1开头的都是seven , 2开头的都是stop 。

训练之前需要先读取数据创建数据集和标签集:

  1. # 加载数据集 和 标签[并返回标签集的处理结果]
  2. def create_datasets():
  3. wavs=[]
  4. labels=[] # labels 和 testlabels 这里面存的值都是对应标签的下标,下标对应的名字在 labsInd 和 testlabsInd 中
  5. testwavs=[]
  6. testlabels=[]
  7. labsInd=[] ## 训练集标签的名字 0:seven 1stop
  8. testlabsInd=[] ## 测试集标签的名字 0:seven 1stop
  9. # 现在为了测试方便和快速直接写死,后面需要改成自动扫描文件夹和标签的形式
  10. #加载seven训练集
  11. path="D:\\wav\\seven\\"
  12. files = os.listdir(path)
  13. for i in files:
  14. # print(i)
  15. waveData = get_wav_mfcc(path+i)
  16. # print(waveData)
  17. wavs.append(waveData)
  18. if ("seven" in labsInd)==False:
  19. labsInd.append("seven")
  20. labels.append(labsInd.index("seven"))
  21. #加载stop训练集
  22. path="D:\\wav\\stop\\"
  23. files = os.listdir(path)
  24. for i in files:
  25. # print(i)
  26. waveData = get_wav_mfcc(path+i)
  27. wavs.append(waveData)
  28. if ("stop" in labsInd)==False:
  29. labsInd.append("stop")
  30. labels.append(labsInd.index("stop"))
  31. #加载seven测试集
  32. path="D:\\wav\\test1\\"
  33. files = os.listdir(path)
  34. for i in files:
  35. # print(i)
  36. waveData = get_wav_mfcc(path+i)
  37. testwavs.append(waveData)
  38. if ("seven" in testlabsInd)==False:
  39. testlabsInd.append("seven")
  40. testlabels.append(testlabsInd.index("seven"))
  41. #加载stop测试集
  42. path="D:\\wav\\test2\\"
  43. files = os.listdir(path)
  44. for i in files:
  45. # print(i)
  46. waveData = get_wav_mfcc(path+i)
  47. testwavs.append(waveData)
  48. if ("stop" in testlabsInd)==False:
  49. testlabsInd.append("stop")
  50. testlabels.append(testlabsInd.index("stop"))
  51. wavs=np.array(wavs)
  52. labels=np.array(labels)
  53. testwavs=np.array(testwavs)
  54. testlabels=np.array(testlabels)
  55. return (wavs,labels),(testwavs,testlabels),(labsInd,testlabsInd)

 拿到数据集之后就可以开始进行神经网络的训练了,keras提供了很多封装好的可以直接使用的神经网络,我们先建立神经网络模型

  1. # 构建一个4层的模型
  2. model = Sequential()
  3. model.add(Dense(512, activation='relu',input_shape=(16000,))) # 音频为16000帧的数据,这里的维度就是16000,激活函数直接用常用的relu
  4. model.add(Dense(256, activation='relu'))
  5. model.add(Dense(64, activation='relu'))
  6. model.add(Dense(2, activation='softmax')) # 因为只有两个类别的语音,最后输出应该就是2个分类的结果
  7. # [编译模型] 配置模型,损失函数采用交叉熵,优化采用Adadelta,将识别准确率作为模型评估
  8. model.compile(loss=keras.losses.categorical_crossentropy, optimizer=keras.optimizers.Adadelta(), metrics=['accuracy'])
  9. # validation_data为验证集
  10. model.fit(wavs, labels, batch_size=124, epochs=5, verbose=1, validation_data=(testwavs, testlabels)) ## 进行5轮训练,每个批次124
  11. # 开始评估模型效果 # verbose=0为不输出日志信息
  12. score = model.evaluate(testwavs, testlabels, verbose=0)
  13. print('Test loss:', score[0])
  14. print('Test accuracy:', score[1]) # 准确度

训练之后的结果:

两个类型的文件一个4500多个,我本机使用CPU训练大概用时20多秒。
最后显示结果准确率为0.9050.也就是90.5%的准确率,这里可以加大数据集的数量和调参来加大准确率。

最后保存模型到文件:

model.save('asr_model_weights.h5') # 保存训练模型

保存之后会在文件夹中生成一个文件【95M】:

先在训练的模型已经有了,我们开始使用trunk中的文件进行试验:

先加载之前训练的模型:

model = load_model('asr_model_weights.h5') # 加载训练模型

 然后获得当前需要试验的文件的mfcc。并且将数据封装成和训练时一样的维度。并且使用模型的predict函数输出结果:

  1. wavs=[]
  2. wavs.append(get_wav_mfcc("D:\\wav\\trunk\\2c.wav")) # 使用某一个文件
  3. X=np.array(wavs)
  4. print(X.shape)
  5. result=model.predict(X[0:1])[0] # 识别出第一张图的结果,多张图的时候,把后面的[0] 去掉,返回的就是多张图结果
  6. print("识别结果",result)

结果输出:

可以看出结果是一个2个数的数组,里面返回的对应类别相似度,也就是说哪一个下标的值最大,就跟那个下标对应的标签最相似。

之前训练的时候,标签的集是:[seven , stop]

所以如图下标1的值达到了89.9%的相似度。

  1. # 因为在训练的时候,标签集的名字 为: 0:seven 1stop 01 是下标
  2. name = ["seven","stop"] # 创建一个跟训练时一样的标签集
  3. ind=0 # 结果中最大的一个数
  4. for i in range(len(result)):
  5. if result[i] > result[ind]:
  6. ind=1
  7. print("识别的语音结果是:",name[ind])

我们把试验文件换成 1b.wav

wavs.append(get_wav_mfcc("D:\\wav\\trunk\\1b.wav"))

 结果输出:

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号