簡介
- 本文實現了一個基於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