Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python GaussianHMM中的序列译码_Python_Hidden Markov Models_Markov Chains_Markov Models_Hmmlearn - Fatal编程技术网

Python GaussianHMM中的序列译码

Python GaussianHMM中的序列译码,python,hidden-markov-models,markov-chains,markov-models,hmmlearn,Python,Hidden Markov Models,Markov Chains,Markov Models,Hmmlearn,我在玩一个股票市场预测问题的隐马尔可夫模型。“我的数据矩阵”包含针对特定安全性的各种功能: 01-01-2001, .025, .012, .01 01-02-2001, -.005, -.023, .02 我拟合了一个简单的GaussianHMM: from hmmlearn import GaussianHMM mdl = GaussianHMM(n_components=3,covariance_type='diag',n_iter=1000) mdl.fit(train[:,1:])

我在玩一个股票市场预测问题的隐马尔可夫模型。“我的数据矩阵”包含针对特定安全性的各种功能:

01-01-2001, .025, .012, .01
01-02-2001, -.005, -.023, .02
我拟合了一个简单的GaussianHMM:

from hmmlearn import GaussianHMM
mdl = GaussianHMM(n_components=3,covariance_type='diag',n_iter=1000)
mdl.fit(train[:,1:])
利用模型(λ),我可以对观测向量进行解码,以找到与观测向量对应的最可能的隐藏状态序列:

print mdl.decode(test[0:5,1:])
(72.75, array([2, 1, 2, 0, 0]))
上面,我已经解码了观测向量Ot=(O1,O2,…,Od)的隐藏状态序列,它包含测试集中的前五个实例。我想估计测试集中第六个实例的隐藏状态。其思想是迭代第六个实例的一组离散的可能特征值,并选择观测序列Ot+1,其最大似然argmax=P(O1,O2,…,Od+1 |λ)。一旦我们观察到Od+1的真实特征值,我们可以将序列(长度为5)移动一次,然后重新进行:

    l = 5
    for i in xrange(len(test)-l):
        values = []
        for a in arange(-0.05,0.05,.01):
            for b in arange(-0.05,0.05,.01):
                for c in arange(-0.05,0.05,.01):
                    values.append(mdl.decode(vstack((test[i:i+l,1:],array([a,b,c])))))
     print max(enumerate(values),key=lambda x: x[1])
问题在于,当我解码观测向量Ot+1时,具有最高似然性的预测几乎总是相同的(例如,具有最高似然性的估计值总是具有Od+1等于[0.04 0.04 0.04]的特征值,并且是隐藏状态[0]):


我完全有可能误解了
mdl.decode
的目的,从而错误地使用了它。如果是这种情况,我怎样才能最好地迭代Od+1的可能值,然后最大化P(O1,O2,…,Od+1 |λ)?

您的实际值有界

[-0.05,0.05)

当我最初构建一个样本数据集来研究您的问题时,我在
[0,1]
中绘制了随机浮点数。当我这样做时,我也得到了与您观察到的结果相同的结果-对于第六个条目,对于每个序列,总是
(a,b,c)
的最大值,并且总是相同的预测类。但是考虑到我的数据分布(均匀分布在
0
1
之间)比第六个条目的网格搜索值(介于
-.05
.05
之间)具有更大的中心趋势,HMM总是选择最高值的三元组
(.04,.04,.04)
,因为这最接近于它所训练的分布的主要密度

当我重新构建数据集时,在第六个条目(
[-0.05,0.05)
允许的相同可能值范围内,从均匀分布中提取数据,输出变化更大:
O_t+1
选择和类预测都显示了序列间的合理差异。从示例数据来看,似乎您至少有正值和负值,但您可以尝试绘制每个特征的分布,并查看可能的范围ry值都是可信的

这是一些示例数据和评估代码。每当出现新的最佳
(a、b、c)
序列时,或者当第六次观测的预测发生变化时(只是为了表明它们并不完全相同),它都会打印出一条消息.每个6元素序列的最高可能性以及预测和最佳第6个数据点存储在
best\u per\u span

首先,构建一个示例数据集:

import numpy as np
import pandas as pd

dates = pd.date_range(start="01-01-2001", end="31-12-2001", freq='D')
n_obs = len(dates)
n_feat = 3
values = np.random.uniform(-.05, .05, size=n_obs*n_feat).reshape((n_obs,n_feat))
df = pd.DataFrame(values, index=dates)

df.head()
                   0         1         2
2001-01-01  0.020891 -0.048750 -0.027131
2001-01-02  0.013571 -0.011283  0.041322
2001-01-03 -0.008102  0.034088 -0.029202
2001-01-04 -0.019666 -0.005705 -0.003531
2001-01-05 -0.000238 -0.039251  0.029307
现在分为训练集和测试集:

train_pct = 0.7
train_size = round(train_pct*n_obs)
train_ix = np.random.choice(range(n_obs), size=train_size, replace=False)
train_dates = df.index[train_ix]

train = df.loc[train_dates]
test = df.loc[~df.index.isin(train_dates)]

train.shape # (255, 3)
test.shape # (110, 3)
在训练数据上拟合3状态HMM:

# hmm throws a lot of deprecation warnings, we'll suppress them.
import warnings
with warnings.catch_warnings():
    warnings.filterwarnings("ignore",category=DeprecationWarning)
    # in the most recent hmmlearn we can't import GaussianHMM directly anymore.
    from hmmlearn import hmm

mdl = hmm.GaussianHMM(n_components=3, covariance_type='diag', n_iter=1000)
mdl.fit(train)
现在网格搜索最佳第6次(
t+1
)观察:

# length of O_t
span = 5

# final store of optimal configurations per O_t+1 sequence
best_per_span = []

# update these to demonstrate heterogenous outcomes
current_abc = None
current_pred = None

for start in range(len(test)-span):
    flag = False
    end = start + span
    first_five = test.iloc[start:end].values
    output = []
    for a in np.arange(-0.05,0.05,.01):
        for b in np.arange(-0.05,0.05,.01):
            for c in np.arange(-0.05,0.05,.01):
                sixth = np.array([a, b, c])[:, np.newaxis].T
                all_six = np.append(first_five, sixth, axis=0)
                output.append((mdl.decode(all_six), (a,b,c)))

    best = max(output, key=lambda x: x[0][0])

    best_dict = {"start":start,
                 "end":end,
                 "sixth":best[1],
                 "preds":best[0][1],
                 "lik":best[0][0]}  
    best_per_span.append(best_dict)

    # below here is all reporting
    if best_dict["sixth"] != current_abc:
        current_abc = best_dict["sixth"]
        flag = True
        print("New abc for range {}:{} = {}".format(start, end, current_abc))

    if best_dict["preds"][-1] != current_pred:
        current_pred = best_dict["preds"][-1]
        flag = True
        print("New pred for 6th position: {}".format(current_pred))

    if flag:
        print("Test sequence StartIx: {}, EndIx: {}".format(start, end))
        print("Best 6th value: {}".format(best_dict["sixth"]))
        print("Predicted hidden state sequence: {}".format(best_dict["preds"]))
        print("Likelihood: {}\n".format(best_dict["nLL"]))
循环运行时报告输出的示例:

New abc for range 3:8 = [-0.01, 0.01, 0.0]
New pred for 6th position: 1
Test sequence StartIx: 3, EndIx: 8
Best 6th value: [-0.01, 0.01, 0.0]
Predicted hidden state sequence: [0 2 2 1 0 1]
Likelihood: 35.30144407374163

New abc for range 18:23 = [-0.01, -0.01, -0.01]
New pred for 6th position: 2
Test sequence StartIx: 18, EndIx: 23
Best 6th value: [-0.01, -0.01, -0.01]
Predicted hidden state sequence: [0 0 0 1 2 2]
Likelihood: 34.31813078939214
每span最佳值的输出示例

[{'end': 5,
  'lik': 33.791537281734904,
  'preds': array([0, 2, 0, 1, 2, 2]),
  'sixth': [-0.01, -0.01, -0.01],
  'start': 0},
 {'end': 6,
  'lik': 33.28967307589143,
  'preds': array([0, 0, 1, 2, 2, 2]),
  'sixth': [-0.01, -0.01, -0.01],
  'start': 1},
 {'end': 7,
  'lik': 34.446813870838156,
  'preds': array([0, 1, 2, 2, 2, 2]),
  'sixth': [-0.01, -0.01, -0.01],
  'start': 2}]

除了报告元素之外,这对您最初的方法来说并不是一个重大的改变,但它似乎确实如预期的那样工作,不会每次都达到最大值。

您是否可以放置完整的代码,而不仅仅是片段。这将使问题更加清楚。如果您在每次迭代中不断重置
,您最后的
print
语句将只引用上一个循环中的
值。JafferWilson:可以。@andrew_reece:我认为这是预期的行为。“I”表示5次观察序列测试[I:I+l]的开始。其思想是迭代第六次(未观察到)的一组离散的可能特征值实例[a,b,c],解码包含第六个实例的估计值的新序列,并选择概率最高的作为最终序列。一旦完成,我们重置对象的值,将序列位置移动1,并估计下一个观测集。也许我只需要使用前向-后向算法完成此操作。。。
[{'end': 5,
  'lik': 33.791537281734904,
  'preds': array([0, 2, 0, 1, 2, 2]),
  'sixth': [-0.01, -0.01, -0.01],
  'start': 0},
 {'end': 6,
  'lik': 33.28967307589143,
  'preds': array([0, 0, 1, 2, 2, 2]),
  'sixth': [-0.01, -0.01, -0.01],
  'start': 1},
 {'end': 7,
  'lik': 34.446813870838156,
  'preds': array([0, 1, 2, 2, 2, 2]),
  'sixth': [-0.01, -0.01, -0.01],
  'start': 2}]