# -*- coding: UTF-8 -*- ''' 此脚本用于实现viterbi算法 ''' import numpy as np from sklearn.utils.extmath import safe_sparse_dot def viterbi(obs, init_prob, trans_prob, emit_prob): ''' viterbi算法 参数 ---- obs : {np.array 或者scipy.sparse.csr_matrix},维度为(样本数,特征数), 数据的特征矩阵 initProb : {np.array或者scipy.sparse.csr_matrix},维度为(状态数), 表示各状态的初始分布 transProb : {np.array或者scipy.sparse.csr_matrix},维度为(状态数,状态数), 状态间的转移矩阵 emitProb : {np.array或者scipy.sparse.csr_matrix},维度为(状态数,特征数), 各状态下,特征的条件概率 返回 ---- score : {np.array},维度为(样本数,状态数),viterbi算法中间概率 path : {np.array},维度为(样本数),最终结果表示每个样本的隐藏状态 ''' sample_num, state_num = obs.shape[0], init_prob.shape[0] backp = np.empty((sample_num, state_num), dtype=np.intp) score = safe_sparse_dot(obs, emit_prob.T) for i in range(state_num): score[0, i] += init_prob[i] for i in range(1, sample_num): for j in range(state_num): max_ind = 0 max_val = -np.inf for k in range(state_num): candidate = score[i - 1, k] + trans_prob[k, j] + score[i, j] if candidate > max_val: max_ind = k max_val = candidate score[i, j] = max_val backp[i, j] = max_ind path = np.empty(sample_num, dtype=np.intp) path[sample_num - 1] = score[sample_num - 1, :].argmax() for i in range(sample_num - 2, -1, -1): path[i] = backp[i + 1, path[i + 1]] return score, path