简介
- 本文实现了一个基于HMM-GMM的独立词识别模型,数据集有限,训练数据为独立词,为10类。训练样本100个,测试样本10个,测试集上能够达到90%的识别率。
- 直接下载项目到本地,运行
.py
文件就可以得到下面的结果,成功执行:
训练集:
识别得到结果:
['1', '10', '2', '3', '4', '5', '6', '7', '8', '10', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '5', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '10', '1', '10', '2', '4', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '10', '1', '10', '2', '3', '4', '5', '6', '7', '8', '10', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9']
原始标签类别:
['1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9']
识别率: 0.94
测试集:
识别得到结果:
['1', '10', '2', '3', '4', '5', '6', '7', '8', '3']
原始标签类别:
['1', '10', '2', '3', '4', '5', '6', '7', '8', '9']
识别率: 0.9
基础准备
原理部分需要了解hmm-gmm在语音识别中的工作原理是什么,特别要理解一个hmm-gmm模型对应一个孤立词这个概念,弄清楚非常重要。
不过你即使不算很明白其中的含义,也可以成功的执行项目,可以在原理和代码中反复思考传统模型的实现原理。
这部分网上讲的很多,这里不再赘述。
python建模
数据预处理
首先,进行数据预处理,输入为训练集路径或者测试集路径wavpath
:
# -----------------------------------------------------------------------------------------------------
'''
&usage: 准备所需数据
'''
# -----------------------------------------------------------------------------------------------------
# 生成wavdict,key=wavid,value=wavfile
def gen_wavlist(wavpath):
wavdict = {}
labeldict = {}
for (dirpath, dirnames, filenames) in os.walk(wavpath):
for filename in filenames:
if filename.endswith('.wav'):
filepath = os.sep.join([dirpath, filename])
fileid = filename.strip('.wav')
wavdict[fileid] = filepath
# 获取文件的类别
label = fileid.split('_')[1]
labeldict[fileid] = label
return wavdict, labeldict
查看wavdict和labeldict的数据内容,以test为例,其中音频的类别为文件名后面的数字:
wavdict, labeldict = gen_wavlist('test_data')
print(wavdict, labeldict)
输出文件路径和标注类别:
wavdict:
{'1_1': 'test_data\\1_1.wav', '1_10': 'test_data\\1_10.wav', '1_2': 'test_data\\1_2.wav', '1_3': 'test_data\\1_3.wav', '1_4': 'test_data\\1_4.wav', '1_5': 'test_data\\1_5.wav', '1_6': 'test_data\\1_6.wav', '1_7': 'test_data\\1_7.wav', '1_8': 'test_data\\1_8.wav', '1_9': 'test_data\\1_9.wav'}
labeldict:
{'1_1': '1', '1_10': '10', '1_2': '2', '1_3': '3', '1_4': '4', '1_5': '5', '1_6': '6', '1_7': '7', '1_8': '8', '1_9': '9'}
特征提取
我们直接调包python_speech_features
实现mfcc,偷懒做法,这样看起来代码比较简洁,如果需要深入了解算法可以自己coding实现。
# pip install python_speech_features ,不行的话百度一下
from python_speech_features import mfcc
# 特征提取,feat = compute_mfcc(wadict[wavid])
def compute_mfcc(file):
fs, audio = wavfile.read(file)
# 这里我故意fs/2,有些类似减小step,不建议这样做,投机取巧做法
mfcc_feat = mfcc(audio, samplerate=(fs/2), numcep=26)
return mfcc_feat
搭建孤立词模型
我们利用hmmlearn
工具包搭建hmm-gmm,可以提前了解一下hmmlearn的使用方法。
- 首先,需要初始化10个独立的hmm-gmm模型,分别对应十个独立词,主要是初始化一个hmm-gmm模型的集合
self.models
:
class Model():
def __init__(self, CATEGORY=None, n_comp=3, n_mix = 3, cov_type='diag', n_iter=1000):
super(Model, self).__init__()
self.CATEGORY = CATEGORY
self.category = len(CATEGORY)
self.n_comp = n_comp
self.n_mix = n_mix
self.cov_type = cov_type
self.n_iter = n_iter
# 关键步骤,初始化models,返回特定参数的模型的列表
self.models = []
for k in range(self.category):
model = hmm.GMMHMM(n_components=self.n_comp, n_mix = self.n_mix,
covariance_type=self.cov_type, n_iter=self.n_iter)
self.models.append(model)
各个参数的意义:
CATEGORY: 所有标签的列表
n_comp: 每个孤立词中的状态数
n_mix: 每个状态包含的混合高斯数量
cov_type: 协方差矩阵的类型
n_iter: 训练迭代次数
- 然后,用同一种类的数据训练特定的模型。
# 模型训练
def train(self, wavdict=None, labeldict=None):
for k in range(10):
subdata = []
model = self.models[k]
for x in wavdict:
if labeldict[x] == self.CATEGORY[k]:
mfcc_feat = compute_mfcc(wavdict[x])
model.fit(mfcc_feat)
- 最后,对待测试的数据分别用十个模型打分,选出得分最高的为识别结果。
# 使用特定的测试集合进行测试
def test(self, wavdict=None, labeldict=None):
result = []
for k in range(self.category):
subre = []
label = []
model = self.models[k]
for x in wavdict:
mfcc_feat = compute_mfcc(wavdict[x])
# 生成每个数据在当前模型下的得分情况
re = model.score(mfcc_feat)
subre.append(re)
label.append(labeldict[x])
# 汇总得分情况
result.append(subre)
# 选取得分最高的种类
result = np.vstack(result).argmax(axis=0)
# 返回种类的类别标签
result = [self.CATEGORY[label] for label in result]
print('识别得到结果:\n',result)
print('原始标签类别:\n',label)
# 检查识别率,为:正确识别的个数/总数
totalnum = len(label)
correctnum = 0
for i in range(totalnum):
if result[i] == label[i]:
correctnum += 1
print('识别率:', correctnum/totalnum)
- 你也可以保存和载入模型
# 利用external joblib保存生成的hmm模型
def save(self, path="models.pkl"):
joblib.dump(self.models, path)
# 利用external joblib载入保存的hmm模型
def load(self, path="models.pkl"):
self.models = joblib.load(path)
模型的训练和测试
利用上面搭建的模块对模型进行训练和测试,完整项目包括数据在hmm-gmm声学模型,下载下来可以直接运行,如果对你有帮助的话,有账户求star啊。
# 准备训练所需数据
CATEGORY = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
wavdict, labeldict = gen_wavlist('training_data')
testdict, testlabel = gen_wavlist('test_data')
print(testdict, testlabel)
# 进行训练和测试
models = Model(CATEGORY=CATEGORY)
models.train(wavdict=wavdict, labeldict=labeldict)
models.save()
models.load()
models.test(wavdict=wavdict, labeldict=labeldict)
models.test(wavdict=testdict, labeldict=testlabel)
识别结果:
训练集:
识别得到结果:
['1', '10', '2', '3', '4', '5', '6', '7', '8', '10', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '5', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '10', '1', '10', '2', '4', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '10', '1', '10', '2', '3', '4', '5', '6', '7', '8', '10', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9']
原始标签类别:
['1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9']
识别率: 0.94
测试集:
识别得到结果:
['1', '10', '2', '3', '4', '5', '6', '7', '8', '3']
原始标签类别:
['1', '10', '2', '3', '4', '5', '6', '7', '8', '9']
识别率: 0.9
hmmlearn安装报错
该工具包安装很可能报错。
可以尝试去https://www.lfd.uci.edu/~gohlke/pythonlibs/#hmmlearn下载对应你电脑版本的文件,我的是64位,python36。
然后cd到你下载的文件的目录下,执行:
pip install hmmlearn‑0.2.1‑cp36‑cp36m‑win_amd64.whl
就可以安装成功了。
一些想法
- 由于基于python的hmm-gmm语音识别模型较少,网上竟然没找到好使的代码,无奈下只能自己查资料写了一个小样。
- 目前该项目只是一个demo,数据也较少,后续希望能够增加一些连续语音识别模型,搞成一个传统模型的语音识别系统。
- 有兴趣的老哥可以查看我的另一个基于深度学习的中文识别系统ch_speech_recognition。
整理不易,转载请注明出处https://blog.csdn.net/chinatelecom08。
该项目github地址:https://github.com/audier/my_hmm_gmm_speech_recognition