keras:一个用python编写的神经网络API,能够以tensorflow、cntk、theano作为后端运行。
一、模型训练:
训练文件已上传到了百度云盘:https://pan.baidu.com/s/1Au85kI_oeDjode2hWumUvQ
文件夹名就是里面的语音的标签,语音由很多不同年龄性别的人发音收集而来
取了seven , stop和happy 三个语音类别来进行训练和识别,每个大概2700多个文件。并且分别从三个文件夹中剪切出来100个当做测试集,并每样拿出1个当做后面的试验集
'''
使用案例,训练两个类型的语音,然后测试,对CPU和内存要求不高。内存使用在 1G 左右
'''
import wave
import matplotlib.pyplot as plt
import numpy as np
import os
import keras
from keras.models import Sequential
from keras.layers import Dense
# 加载数据集 和 标签[并返回标签集的处理结果]
def create_datasets():
wavs=[]
labels=[] # labels 和 testlabels 这里面存的值都是对应标签的下标,下标对应的名字在labsInd中
testwavs=[]
testlabels=[]
labsInd=[] ## 训练集标签的名字 0:seven 1:stop 2:happy
testlabsInd=[] ## 测试集标签的名字 0:seven 1:stop 2: happy
path="D:\\wav\\seven\\"
files = os.listdir(path)
for i in files:
# print(i)
waveData = get_wav_mfcc(path+i)
# print(waveData)
wavs.append(waveData)
if ("seven" in labsInd)==False:
labsInd.append("seven")
labels.append(labsInd.index("seven"))
path="D:\\wav\\stop\\"
files = os.listdir(path)
for i in files:
# print(i)
waveData = get_wav_mfcc(path+i)
wavs.append(waveData)
if ("stop" in labsInd)==False:
labsInd.append("stop")
labels.append(labsInd.index("stop"))
path="D:\\wav\\happy\\"
files = os.listdir(path)
for i in files:
# print(i)
waveData = get_wav_mfcc(path+i)
wavs.append(waveData)
if ("happy" in labsInd)==False:
labsInd.append("happy")
labels.append(labsInd.index("happy"))
# 现在为了测试方便和快速直接写死,后面需要改成自动扫描文件夹和标签的形式
path="D:\\wav\\test1\\"
files = os.listdir(path)
for i in files:
# print(i)
waveData = get_wav_mfcc(path+i)
testwavs.append(waveData)
if ("seven" in testlabsInd)==False:
testlabsInd.append("seven")
testlabels.append(testlabsInd.index("seven"))
path="D:\\wav\\test2\\"
files = os.listdir(path)
for i in files:
# print(i)
waveData = get_wav_mfcc(path+i)
testwavs.append(waveData)
if ("stop" in testlabsInd)==False:
testlabsInd.append("stop")
testlabels.append(testlabsInd.index("stop"))
path="D:\\wav\\test3\\"
files = os.listdir(path)
for i in files:
# print(i)
waveData = get_wav_mfcc(path+i)
testwavs.append(waveData)
if ("happy" in testlabsInd)==False:
testlabsInd.append("happy")
testlabels.append(testlabsInd.index("happy"))
wavs=np.array(wavs)
labels=np.array(labels)
testwavs=np.array(testwavs)
testlabels=np.array(testlabels)
return (wavs,labels),(testwavs,testlabels),(labsInd,testlabsInd)
def get_wav_mfcc(wav_path):
f = wave.open(wav_path,'rb')
params = f.getparams()
# print("params:",params)
nchannels, sampwidth, framerate, nframes = params[:4]
strData = f.readframes(nframes)#读取音频,字符串格式
waveData = np.fromstring(strData,dtype=np.int16)#将字符串转化为int
waveData = waveData*1.0/(max(abs(waveData)))#wave幅值归一化
waveData = np.reshape(waveData,[nframes,nchannels]).T
f.close()
# print(waveData)
# plt.rcParams['savefig.dpi'] = 300 #图片像素
# plt.rcParams['figure.dpi'] = 300 #分辨率
# plt.specgram(waveData[0],Fs = framerate, scale_by_freq = True, sides = 'default')
# plt.ylabel('Frequency(Hz)')
# plt.xlabel('Time(s)')
# plt.title('wa')
# plt.show()
### 对音频数据进行长度大小的切割,保证每一个的长度都是一样的【因为训练文件全部是1秒钟长度,16000帧的,所以这里需要把每个语音文件的长度处理成一样的】
data = list(np.array(waveData[0]))
# print(len(data))
while len(data)>16000:
del data[len(waveData[0])-1]
del data[0]
# print(len(data))
while len(data)<16000:
data.append(0)
# print(len(data))
data=np.array(data)
# 平方之后,开平方,取正数,值的范围在 0-1 之间
data = data ** 2
data = data ** 0.5
return data
if __name__ == '__main__':
(wavs,labels),(testwavs,testlabels),(labsInd,testlabsInd) = create_datasets()
print(wavs.shape," ",labels.shape)
print(testwavs.shape," ",testlabels.shape)
print(labsInd," ",testlabsInd)
# 标签转换为独热码
labels = keras.utils.to_categorical(labels, 3)
testlabels = keras.utils.to_categorical(testlabels, 3)
print(labels[0]) ## 类似 [1. 0. 0]
print(testlabels[0]) ## 类似 [0. 0. 0]
print(wavs.shape," ",labels.shape)
print(testwavs.shape," ",testlabels.shape)
# 构建sequential顺序模型,由多个网络层线性堆叠的栈。使用其API可以构建任意的神经网络图。
model = Sequential()
#可以简单地使用 .add() 来堆叠模型,Dense(768) 是一个具有 768 个隐藏神经元的全连接层。
model.add(Dense(768, activation='relu',input_shape=(16000,)))
model.add(Dense(384, activation='relu'))
model.add(Dense(96, activation='relu'))
model.add(Dense(3, activation='softmax'))
# [编译模型] 配置模型,损失函数采用交叉熵,优化采用Adadelta,将识别准确率作为模型评估
#如果需要,你还可以进一步地配置你的优化器。Keras的核心原则是使事情变得相当简单,同时又允许用户在需要的时候能够进行完全的控制(终极的控制是源代码的易扩展性)
model.compile(loss=keras.losses.categorical_crossentropy, optimizer=keras.optimizers.Adadelta(), metrics=['accuracy'])
# validation_data为验证集
# 批量地在训练数据上进行迭代,以 124 个样本为一个 batch 进行迭代
model.fit(wavs, labels, batch_size=124, epochs=5, verbose=1, validation_data=(testwavs, testlabels))
# 开始评估模型效果 # verbose=0为不输出日志信息
score = model.evaluate(testwavs, testlabels, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1]) # 准确度
model.save('asr_model_weights.h5') # 保存训练模型
二、测试:
import wave
import numpy as np
import os
from keras.models import load_model
def get_wav_mfcc(wav_path):
f = wave.open(wav_path,'rb')
params = f.getparams()
# print("params:",params)
nchannels, sampwidth, framerate, nframes = params[:4]
strData = f.readframes(nframes)#读取音频,字符串格式
waveData = np.fromstring(strData,dtype=np.int16)#将字符串转化为int
waveData = waveData*1.0/(max(abs(waveData)))#wave幅值归一化
waveData = np.reshape(waveData,[nframes,nchannels]).T
f.close()
### 对音频数据进行长度大小的切割,保证每一个的长度都是一样的【因为训练文件全部是1秒钟长度,16000帧的,所以这里需要把每个语音文件的长度处理成一样的】
data = list(np.array(waveData[0]))
# print(len(data))
while len(data)>16000:
del data[len(waveData[0])-1]
del data[0]
# print(len(data))
while len(data)<16000:
data.append(0)
# print(len(data))
data=np.array(data)
# 平方之后,开平方,取正数,值的范围在 0-1 之间
data = data ** 2
data = data ** 0.5
return data
if __name__ == '__main__':
# 构建模型
model = load_model('asr_model_weights.h5') # 加载训练模型
wavs=[]
wavs.append(get_wav_mfcc("D:\\wav\\trunk\\1_0.wav"))
X=np.array(wavs)
print(X.shape)
result=model.predict(X[0:1])[0] # 识别出第一张图的结果,多张图的时候,把后面的[0] 去掉,返回的就是多张图结果
print("识别结果",result)
# 因为在训练的时候,标签集的名字 为: 0:seven 1:stop 2:happy 0,1,2 是下标
name = ["seven","stop","happy"] # 创建一个跟训练时一样的标签集
ind=0 # 结果中最大的一个数
for i in range(len(result)):
print(i)
if result[i] > result[ind]:
ind=i
print("识别的语音结果是:",name[ind])
识别结果:
源码下载:
https://github.com/BenShuai/kerasTfPoj.git
参考:
https://blog.csdn.net/sunshuai_coder/article/details/83658625