天天看點

機器學習經典算法之(十三) 隐馬爾可夫模型

        一、隐馬爾可夫模型簡介:

        隐馬爾可夫模型(Hidden MarkovModel,HMM)是統計模型,它用來描述一個含有隐含未知參數的馬爾可夫過程。其難點是從可觀察的參數中确定該過程的隐含參數。然後利用這些參數來作進一步的分析,例如模式識别。

        隐馬爾可夫模型是馬爾可夫鍊的一種,它的狀态不能直接觀察到,但能通過觀測向量序列觀察到,每個觀測向量都是通過某些機率密度分布表現為各種狀态,每一個觀測向量是由一個具有相應機率密度分布的狀态序列産生。是以,隐馬爾可夫模型是一個雙重随機過程----具有一定狀态數的隐馬爾可夫鍊和顯示随機函數集。自20世紀80年代以來,HMM被應用于語音識别,取得重大成功。到了90年代,HMM還被引入計算機文字識别和移動通信核心技術“多使用者的檢測”。HMM在生物資訊科學、故障診斷等領域也開始得到應用

        隐馬爾可夫模型(HMM)可以用五個元素來描述,包括2個狀态集合和3個機率矩陣:

        1. 隐含狀态S

        這些狀态之間滿足馬爾可夫性質,是馬爾可夫模型中實際所隐含的狀态。這些狀态通常無法通過直接觀測而得到。(例如S1、S2、S3等等)

        2. 可觀測狀态O

        在模型中與隐含狀态相關聯,可通過直接觀測而得到。(例如O1、O2、O3等等,可觀測狀态的數目不一定要和隐含狀态的數目一緻。)

        3. 初始狀态機率矩陣π

        表示隐含狀态在初始時刻t=1的機率矩陣,(例如t=1時,P(S1)=p1、P(S2)=P2、P(S3)=p3,則初始狀态機率矩陣π=[ p1,p2, p3 ].

        4. 隐含狀态轉移機率矩陣 A

        描述了HMM模型中各個狀态之間的轉移機率。

        其中Aij = P( Sj | Si ),1≤i,j≤N.

        表示在 t 時刻、狀态為 Si 的條件下,在 t+1時刻狀态是 Sj 的機率。

        5. 觀測狀态轉移機率矩陣 B或者有時稱為:發射機率,某種隐含狀态産生某種觀測現象的機率。令N代表隐含狀态數目,M代表可觀測狀态數目,則:

        Bij = P( Oi| Sj ), 1≤i≤M,1≤j≤N.

表示在 t 時刻、隐含狀态是 Sj 條件下,觀察狀态為 Oi 的機率。

        總結:一般的,可以用λ=(A,B,π)三元組來簡潔的表示一個隐馬爾可夫模型。隐馬爾可夫模型實際上是标準馬爾可夫模型的擴充,添加了可觀測狀态集合和這些狀态與隐含狀态之間的機率關系。

        二、解決的三類基本問題:

        1. 評估問題。

        給定觀測序列 O=O1O2O3…Ot和模型參數λ=(A,B,π),怎樣有效計算某一觀測序列的機率,進而可對該HMM做出相關評估。例如,已有一些模型參數各異的HMM,給定觀測序列O=O1O2O3…Ot,我們想知道哪個HMM模型最可能生成該觀測序列。通常我們利用forward算法分别計算每個HMM産生給定觀測序列O的機率,然後從中選出最優的HMM模型。

        這類評估的問題的一個經典例子是語音識别。在描述語言識别的隐馬爾科夫模型中,每個單詞生成一個對應的HMM,每個觀測序列由一個單詞的語音構成,單詞的識别是通過評估進而選出最有可能産生觀測序列所代表的讀音的HMM而實作的。

        2.解碼問題

        給定觀測序列 O=O1O2O3…Ot和模型參數λ=(A,B,π),怎樣尋找某種意義上最優的隐狀态序列。在這類問題中,我們感興趣的是馬爾科夫模型中隐含狀态,這些狀态不能直接觀測但卻更具有價值,通常利用Viterbi算法來尋找。

        這類問題的一個實際例子是中文分詞,即把一個句子如何劃分其構成才合适。例如,句子“開發中國家”是劃分成“發展-中-國家”,還是“發展-中國-家”。這個問題可以用隐馬爾科夫模型來解決。句子的分詞方法可以看成是隐含狀态,而句子則可以看成是給定的可觀測狀态,進而通過建HMM來尋找出最可能正确的分詞方法。

        3. 學習問題。

        如果HMM的模型參數λ=(A,B,π)未知,如何調整這些參數以使觀測序列O=O1O2O3…Ot的機率盡可能的大。通常使用Baum-Welch算法以及ReversedViterbi算法解決。

         三、HMM的語音識别應用舉例。

import os

import numpy as np

from scipy.io import wavfile

from python_speech_features import mfcc

# import sys

# sys.path.append(r'C:\Users\Administrator\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\hmmlearn-0.2.0')  #加入路徑,添加目錄

import hmmlearn

from hmmlearn import *

# Class to handle all HMM related processing

class HMMTrainer(object):

    def __init__(self, model_name='GaussianHMM', n_components=4, cov_type='diag', n_iter=1000):

        self.model_name = model_name

        self.n_components = n_components

        self.cov_type = cov_type

        self.n_iter = n_iter

        self.models = []

        if self.model_name == 'GaussianHMM':

            self.model = hmm.GaussianHMM(n_components=self.n_components, 

                    covariance_type=self.cov_type, n_iter=self.n_iter)

        else:

            raise TypeError('Invalid model type')

    # X is a 2D numpy array where each row is 13D

    def train(self, X):

        np.seterr(all='ignore')

        self.models.append(self.model.fit(X))

    # Run the model on input data

    def get_score(self, input_data):

        return self.model.score(input_data)

if __name__=='__main__':

    input_folder = "d:\\learning\\speech-reconginzer"

    hmm_models = []

    # Parse the input directory

    for dirname in os.listdir(input_folder):

        # Get the name of the subfolder 

        subfolder = os.path.join(input_folder, dirname)

        if not os.path.isdir(subfolder): 

            continue

        # Extract the label

        label = subfolder[subfolder.rfind('/') + 1:]

        # Initialize variables

        X = np.array([])

        y_words = []

        # Iterate through the audio files (leaving 1 file for testing in each class)

        for filename in [x for x in os.listdir(subfolder) if x.endswith('.wav')][:-1]:

            # Read the input file

            filepath = os.path.join(subfolder, filename)

            sampling_freq, audio = wavfile.read(filepath)

            # Extract MFCC features

            mfcc_features = mfcc(audio, sampling_freq)

            # Append to the variable X

            if len(X) == 0:

                X = mfcc_features

            else:

                X = np.append(X, mfcc_features, axis=0)            

            # Append the label

            y_words.append(label)

        # print 'X.shape =', X.shape

        # Train and save HMM model

        hmm_trainer = HMMTrainer()

        hmm_trainer.train(X)

        hmm_models.append((hmm_trainer, label))

        hmm_trainer = None

    # Test files

    input_files = [

            'data/pineapple/pineapple15.wav',

            'data/orange/orange15.wav',

            'data/apple/apple15.wav',

            'data/kiwi/kiwi15.wav'

            ]

    # Classify input data

    for input_file in input_files:

        # Read input file

        sampling_freq, audio = wavfile.read(input_file)

        print("input_file",input_file)

        # Extract MFCC features

        mfcc_features = mfcc(audio, sampling_freq)

        # Define variables

        max_score = None

        output_label = None

        # Iterate through all HMM models and pick 

        # the one with the highest score

        for item in hmm_models:

            hmm_model, label = item

            score = hmm_model.get_score(mfcc_features)

            if score > max_score:

                max_score = score

                output_label = label

     部分内容摘自百度百科,大家加油!