问题
前边的文章介绍了 hmmlearn 进行简单的模型分析,其中我们只用到了一个特征,就是色子的颜色. 但是色子的颜色是离散的固定的几个数值.对于这类问题, 我们使用了hmmlearn 中的MultinomialHMM 方法,
那么对于连续的变化怎么办呢? 比如预测温度,股票?
回答
hmmlearn中 包含其他方法,比如 以下这两个方法就可以处理连续的观测状态.
| hmm.GaussianHMM | Hidden Markov Model with Gaussian emissions. |
| hmm.GMMHMM | Hidden Markov Model with Gaussian mixture emissions. |
这时候区别就是我们的发散矩阵已经不是一个矩阵了,而是对应的一个高斯分布, hmmlearn 给出的是这个分布的平均是和均方差.
比如:
我们假设有两个隐含状态A,B,
A观测到的是 1-100的数字, B会得到100-200的数字
起始状态 AB 是 20% : 80%
转移情况是 A有30% 概率转变为B, B有40%概率转变为A
生成数据
# 初始状态 判断标准,小于此值为A 大于此值为Ba_b_init_critia = 0.2# state_changestate_change = {"A": 0.3, # 此时如果是A, 那么取random, 如果小于 此值就是A 否则为B "B": 0.6 # 此时如果是B, 那么取random, 如果小于 此值就是A 否则为B }data_size = 10000whole_data = []lengths = []for i in range(data_size): dice = "A" if random.random() < a_b_init_critia else "B" data = [] sequence_length = random.randint(2, 25) for _ in range(sequence_length):# print(dice, end=" ") if dice == "A": data.append([random.randint(1, 100)]) else: data.append([random.randint(200, 300)]) dice = "A" if random.random() < state_change[dice] else "B"# print(f"反复抛{sequence_length} 次 点数是 {[i[0]+1 for i in data]} ") whole_data.append(data) lengths.append(sequence_length)whole_data = np.concatenate(whole_data)
print(f"开始学习 {datetime.datetime.now()} 共 {len(lengths)}条数据")hmm_model = hmm.GaussianHMM(n_components=2, n_iter=100000, # Maximum number of iterations to perform. tol=0.01, # Convergence threshold. EM will stop if the gain in log-likelihood is below this value. verbose = False, # When True per-iteration convergence reports are printed to sys.stderr. )hmm_model.fit(whole_data, lengths)print(f"结束学习 {datetime.datetime.now()}")print('初始概率')print(hmm_model.startprob_,'')print('状态转移矩阵')print(hmm_model.transmat_,'')print("该模型生成一个样例")data, data_hidden_state = hmm_model.sample(6)print(f"一段序列 {data}")print(f"预测隐藏状态 {hmm_model.predict(data)}")print(f"预测隐藏状态的概率 {hmm_model.predict_proba(data)}")print(f"出现这个序列的概率{np.exp(hmm_model.score(data))}")print(f".means_ {hmm_model.means_}")print(f".covars_ {hmm_model.covars_ }")
输出结果
开始学习 2020-01-16 10:17:26.915812 共 10000条数据
结束学习 2020-01-16 10:17:46.204643
初始概率
[0.20179976 0.79820024]
状态转移矩阵
[[0.30350127 0.69649873]
[0.60041775 0.39958225]]
该模型生成一个样例
一段序列
[[269.18718079]
[266.42038173]
[254.68047831]
[ 52.49296527]
[283.0950424 ]
[ 23.60572197]]
预测隐藏状态
[1 1 1 0 1 0]
预测隐藏状态的概率
[[2.04558827e-13 1.00000000e+00]
[2.35612469e-12 1.00000000e+00]
[1.12983150e-11 1.00000000e+00]
[1.00000000e+00 4.26757394e-11]
[3.66577525e-15 1.00000000e+00]
[1.00000000e+00 8.59607184e-14]]
出现这个序列的概率
4.904517997287965e-14
.means_
[[ 50.47473064]
[249.95552323]]
.covars_
[[[835.54911052]]
[[851.05270943]]]
其中在GaussianHMM 还有一个参数,就是协方差的设定 covariance_type, 默认的是 diag
spherical - 是指在每个马尔可夫隐含状态下,可观察态向量的所有特性分量使用相同的方差值。
对应协方差矩阵的非对角为0,对角值相等,即球面特性。这是最简单的高斯分布PDF。
diag - 是指在每个马尔可夫隐含状态下,可观察态向量使用对角协方差矩阵。
对应协方差矩阵非对角为0,对角值不相等。diag是hmmlearn里面的默认类型。
full - 是指在每个马尔可夫隐含状态下,可观察态向量使用完全协方差矩阵。
对应的协方差矩阵里面的元素都是不为零。
tied - 是指所有的马尔可夫隐含状态使用相同的完全协方差矩阵。
这四种PDF类型里面,spherical, diag和full代表三种不同的高斯分布概率密度函数,而tied则可以看作是GaussianHMM和GMMHMM的特有实现。其中,full是最强大的,但是需要足够多的数据来做合理的参数估计;spherical是最简单的,通常用在数据不足或者硬件平台性能有限的情况之下;而diag则是这两者一个折中。在使用的时候,需要根据可观察态向量不同特性的相关性来选择合适的类型。
REF
https://hmmlearn.readthedocs.io/en/latest/api.html#hmmlearn.hmm.GaussianHMM
https://www.zhihu.com/question/33467075/answer/90461073