01.16 python 日常笔记 -- hmmlearn 连续性观测状态的实现

问题

前边的文章介绍了 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

生成数据

<code>#  初始状态 判断标准,小于此值为A 大于此值为B
a_b_init_critia = 0.2

# state_change
state_change = {"A": 0.3, # 此时如果是A, 那么取random, 如果小于 此值就是A 否则为B
"B": 0.6 # 此时如果是B, 那么取random, 如果小于 此值就是A 否则为B
}

data_size = 10000
whole_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)
/<code>
<code>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_,'\\n')
print('状态转移矩阵')
print(hmm_model.transmat_,'\\n')
print("该模型生成一个样例")

data, data_hidden_state = hmm_model.sample(6)
print(f"一段序列 \\n{data}")
print(f"预测隐藏状态 \\n{hmm_model.predict(data)}")
print(f"预测隐藏状态的概率 \\n{hmm_model.predict_proba(data)}")
print(f"出现这个序列的概率\\n{np.exp(hmm_model.score(data))}")
print(f".means_\\n {hmm_model.means_}")
print(f".covars_ \\n {hmm_model.covars_ }")
/<code>

输出结果

开始学习 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 - 是指在每个马尔可夫隐含状态下,可观察态向量的所有特性分量使用相同的方差值。

python 日常笔记 -- hmmlearn 连续性观测状态的实现

对应协方差矩阵的非对角为0,对角值相等,即球面特性。这是最简单的高斯分布PDF。

diag - 是指在每个马尔可夫隐含状态下,可观察态向量使用对角协方差矩阵。

python 日常笔记 -- hmmlearn 连续性观测状态的实现

对应协方差矩阵非对角为0,对角值不相等。diag是hmmlearn里面的默认类型。

full - 是指在每个马尔可夫隐含状态下,可观察态向量使用完全协方差矩阵。

python 日常笔记 -- hmmlearn 连续性观测状态的实现

对应的协方差矩阵里面的元素都是不为零。

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


分享到:


相關文章: