通过hmmlearn学习使用HMM隐马尔科夫模型

一.了解隐马尔科夫模型(HMM)
具体可参考https://www.zhihu.com/question/20962240,讲得很通俗易懂。
本文使用的是hmmlearn模块,可以使用pip install hmmlearn安装。

二.HMM主要解决的三个问题。
假设隐藏状态序列和观测状态序列分别使用Z和X表示,则解决的3个问题可表示为:
1.解码问题:已知模型参数和X,估计最可能的Z;维特比算法
2.概率问题:已知模型参数和X,估计X出现的概率;向前-向后算法
3.学习问题:仅给出X和隐藏层个数,估计模型参数。 B-W算法,通常是经过一定数量的训练以后,得到模型,然后解决问题1和2。
注意:
对于估计模型参数,其实质是给出隐藏层和可观测层之间的转换模型,而用我下面举的例子,并不能反推出model.startprob_开始转移矩阵,也不能推出隐藏层的混淆矩阵model.transmat_,而且估计出的隐藏层和可观测层的转换矩阵行列顺序不固定,也就是说不能估算出Rainy->[0.1, 0.4, 0.5],有时为Sunny->[0.1, 0.4, 0.5]。

三.HMM常用的三种模型
1.GaussianHMM 观测状态连续型且符合高斯分布
2.GMMHMM 观测状态连续型且符合混合高斯分布
3.MultinomialHMM 观测状态离散型

四.MultinomialHMM使用实例

#coding=utf-8
'''
Created on 2017-12-4

本例为天气和行为的关系
'''
import numpy as np
import matplotlib.pyplot as plt
# hmmlearn可以在安装numpy以后,再使用pip install hmmlearn安装
from hmmlearn import hmm

states = ["Rainy", "Sunny"]##隐藏状态
n_states = len(states)##隐藏状态长度

observations = ["walk", "shop", "clean"]##可观察的状态
n_observations = len(observations)##可观察序列的长度

start_probability = np.array([0.6, 0.4])##开始转移概率,即开始是Rainy和Sunny的概率
##隐藏间天气转移混淆矩阵,即Rainy和Sunny之间的转换关系,例如[0,0]表示今天Rainy,明天Rainy的概率
transition_probability = np.array([
  [0.7, 0.3],
  [0.4, 0.6]
])
##隐藏状态天气和可视行为混淆矩阵,例如[0,0]表示今天Rainy,walk行为的概率为0.1
emission_probability = np.array([
  [0.1, 0.4, 0.5],
  [0.6, 0.3, 0.1]
])

#构建了一个MultinomialHMM模型,这模型包括开始的转移概率,隐藏间天气转换混淆矩阵(transmat),隐藏状态天气和可视行为混淆矩阵emissionprob,对模型参数初始化
model = hmm.MultinomialHMM(n_components=n_states)
model.startprob_= start_probability
model.transmat_ = transition_probability
model.emissionprob_ = emission_probability

#给出一个可见序列
bob_Actions = np.array([[2, 0, 1, 1, 2, 0]]).T

# 解决问题1,解码问题,已知模型参数和X,估计最可能的Z; 维特比算法 
logprob, weathers = model.decode(bob_Actions, algorithm="viterbi")
print "Bob Actions:", ", ".join(map(lambda x: observations[x], bob_Actions))
print "weathers:", ", ".join(map(lambda x: states[x], weathers))
print logprob#该参数反映模型拟合的好坏,数值越大越好
# 解决问题2,概率问题,已知模型参数和X,估计X出现的概率, 向前-向后算法 
score = model.score(bob_Actions, lengths=None)
#最后输出结果
print score
# 结果为-6.892170869,其实真正的概率是以自然数e为底数ln(P) = -6.892170869,所以概率P = 0.00101570648021
# import math
# print math.exp(-6.892170869)

# 解决问题3,学习问题,仅给出X,估计模型参数,鲍姆-韦尔奇算法,其实就是基于EM算法的求解
# 解决这个问题需要X的有一定的数据量,然后通过model.fit(X, lengths=None)来进行训练然后自己生成一个模型
# 并不需要设置model.startprob_,model.transmat_,model.emissionprob_
# 例如:
# import numpy as np
# from hmmlearn import hmm
#  
# states = ["Rainy", "Sunny"]##隐藏状态
# n_states = len(states)##隐藏状态长度
#  
# observations = ["walk", "shop", "clean"]##可观察的状态
# n_observations = len(observations)##可观察序列的长度
#  
# model = hmm.MultinomialHMM(n_components=n_states, n_iter=1000, tol=0.01)
#  
# X = np.array([[2, 0, 1, 1, 2, 0],[0, 0, 1, 1, 2, 0],[2, 1, 2, 1, 2, 0]])
# model.fit(X)
# print model.startprob_
# print model.transmat_
# print model.emissionprob_
## [[  1.11111111e-01   2.22222222e-01   6.66666667e-01]
##  [  5.55555556e-01   4.44444444e-01   6.27814351e-28]]
# print model.score(X)
# model.fit(X)
# print model.startprob_
# print model.transmat_
# print model.emissionprob_
# 和第一次fit(X)得到的行顺序不一样
## [[  5.55555556e-01   4.44444444e-01   9.29759770e-28]
##  [  1.11111111e-01   2.22222222e-01   6.66666667e-01]]
# print model.score(X)
# model.fit(X)
# print model.startprob_
# print model.transmat_
# print model.emissionprob_
# print model.score(X)
# # 可以进行多次fit,然后拿评分最高的模型,就可以预测了
# print model.predict(bob_Actions, lengths=None)
# # 预测最可能的隐藏状态
# # 例如:
# # [0 1 0 0 0 1]
# print model.predict_proba(bob_Actions, lengths=None)# 预测各个隐藏状态的概率
# # 例如:
# # [[ 0.82770645  0.17229355]
# #  [ 0.27361913  0.72638087]
# #  [ 0.58700959  0.41299041]
# #  [ 0.69861348  0.30138652]
# #  [ 0.81799813  0.18200187]
# #  [ 0.24723966  0.75276034]]
# # 在生成的模型中,可以随机生成随机生成一个模型的Z和X
# X,Z = model.sample(n_samples=5, random_state=None)
# print "Bob Actions:", ", ".join(map(lambda x: observations[x], X))
# print "weathers:", ", ".join(map(lambda x: states[x], Z))


# # 保存模型
# import pickle
# output = open('D:\\xxx\\data1111.pkl', 'wb')
# s = pickle.dump(model, output)
# output.close()
# # 调用模型
# input = open('D:\\xxx\\data.pkl', 'rb')
# model = pickle.load(model)
# input.close()
# model.predict(X)

五.隐马可夫模型参数设置,属性设置,模型函数(参考于http://blog.youkuaiyun.com/zhydw317/article/details/78418750?locationNum=1&fps=1)

模型参数:
n_components : 隐藏状态数目
covariance_type: 协方差矩阵的类型
min_covar : 最小方差,防止过拟合
startprob_prior : 初始概率向量
transmat_prior : 转移状态矩阵
means_prior, means_weight : 均值
covars_prior, covars_weight : 协方差
algorithm : 所用算法
random_state : 随机数种子
n_iter : 最大迭代次数
tol : 停机阈值
verbose : 是否打印日志以观察是否已收敛
params : 决定哪些参数在迭代中更新
init_params : 决定哪些参数在迭代前先初始化

模型属性:
n_features:n维高斯分布
monitor_:收敛监测
transmat_:转移矩阵
startprob_:初始向量
means_:均值
covars_:方差

模型常用函数调用:
decode(X, lengths=None, algorithm=None),返回最可能的隐藏状态
sample(n_samples=1, random_state=None), 随机生成一个模型的Z和X
fit(X, lengths=None) ,估计模型参数
predict(X, lengths=None) ,预测最可能的隐藏状态
predict_proba(X, lengths=None) ,预测各状态的概率
score(X, lengths=None) ,当前模型下出现X的概率

六.隐马可夫模型常用领域
1.语音识别,使用的就是第一问题,解码问题
2.股票预测,使用的问题2,预测概率问题
3.XSS攻击检测,使用的问题2,预测概率问题
对于XSS攻击,首先我们需要对数据进行泛化,比如:
[a-zA-Z]泛化为A
[0-9]泛化为N
[-_]泛化为C
其他字符泛化为T
其中ANCT为可观测离散值,则对于URL中有字符串uid=admin123,则有:
admin123->AAAAANNN,而uid=%3Cscript->TNAAAAAAA。
假设我们只训练白样本,生成模型,则当识别一个白样本时score值就很高,然后拿去识别XSS,带有XSS黑样本的score值就会很低。

### 隐马尔科夫模型和贝叶斯网络学习方法 #### 隐马尔科夫模型 (HMM) 隐马尔科夫模型是一种特殊的概率图模型,适用于处理时间序列数据。该模型中的状态不可见,即隐藏的状态之间存在转换关系,并且每个状态下会发出观测值。 对于隐马尔科夫模型学习主要涉及三个经典问题: - **评估问题**:给定模型参数 λ=(A, B, π),以及观察序列 O={o_1,o_2,...,o_T} ,如何高效计算在模型λ下观察序列O的概率 P(O|λ)[^2]。 - **解码问题**:已知模型参数 λ 和观察序列 O 的情况下,寻找最有可能产生此观察序列的一系列隐藏状态 S* 。通常采用维特比算法来解决这个问题[^3]。 - **学习问题**:当只有观察序列而未知确切的 HMM 参数时,怎样调整这些参数以使所得到的新模型能够更好地解释给出的数据集。常用的方法是 Baum-Welch 算法(EM 算法的一个变体),它可以在不需知道具体转移路径的情况下估计出最优参数组合。 ```python from hmmlearn import hmm import numpy as np # 创建一个高斯分布的HMM实例 model = hmm.GaussianHMM(n_components=3, covariance_type="diag") # 训练模型 X = [[0.5], [1.0], [-1.0], [2.0], [3.0]] lengths = [len(X)] model.fit(X, lengths) # 输出训练后的参数 print("Transition matrix:") print(model.transmat_) print("\nMeans and vars of each hidden state:") for i in range(model.n_components): print(f"{i}: {model.means_[i]} {np.diag(model.covars_[i])}") ``` #### 贝叶斯网络 (BN) 贝叶斯网络由一组节点及其之间的有向边组成,用来表示变量间的条件独立性和依赖结构。学习贝叶斯网络分为两部分——结构学习与参数学习。 - **结构学习**旨在发现最适合描述数据间关联模式的图形化表达方式。这可以通过搜索最佳拓扑结构实现,也可以基于统计测试或评分函数来进行优化[^4]。 - **参数学习**是在确定好网络结构之后的任务,目的是估算各节点在其父节点取不同值条件下发生的可能性大小。如果样本充足,则可以直接利用极大似然估计;反之则可能需要用到更复杂的贝叶斯推断技术[^1]。 ```python import pgmpy.estimators as estimators from pgmpy.models import BayesianModel data = pd.DataFrame(np.random.randint(0, 2, size=(1000, 4)), columns=list('ABCD')) estimator = estimators.BayesianEstimator(model=model, data=data) cpd_A = estimator.get_parameters(['A'])[0] print(cpd_A) ```
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值