我正在尝试使用“MultinomialHMM”模块(scikit-learn 库的一部分)构建一个具有 2 个状态和 3 个可能观察值的玩具隐马尔可夫模型。我的问题是,即使状态的观测概率加起来大于 1 或小于 1,模块也会接受(并生成预测)。示例:
import numpy
from sklearn import hmm
startprob = numpy.array([0.5, 0.5])
transition_matrix = numpy.array([[0.5, 0.5], [0.5, 0.5]])
model = hmm.MultinomialHMM(2, startprob, transition_matrix)
model.emissionprob_ = numpy.array([[0, 0, 0.2], [0.6, 0.4, 0]])
请注意,状态 0 发出的信号的概率为 [0,0,0.2](加起来为 0.2)。当要求生成观察样本时,模块不会提示:
model.sample(10)
(array([1, 0, 0, 0, 0, 2, 1, 0, 0, 0], dtype=int64), array([1, 1, 0, 1, 1, 0, 1, 0, 0, 0]))
我还可以指定总和大于 1 的排放概率,并且模型会毫无怨言地生成预测。
这是期望的行为吗?概率是否以某种方式标准化?如果是这样,怎么办?
最佳答案
首先,sklearn
中已弃用 HMM
。您需要查看https://github.com/hmmlearn/hmmlearn ,这是Python中的隐马尔可夫模型,具有类似scikit-learn的API
顺便说一句,你问的问题似乎是一个错误。当您设置emissionprob_
时,将调用_set_emissionprob
。这会尝试通过调用 normalize(emissionprob)
来重新标准化:
if not np.alltrue(emissionprob):
normalize(emissionprob)
但是,这段代码有两个问题:
- 没有正确设置轴。
- 尽管文件这么说,但还没有到位。
如此修改为
if not np.alltrue(emissionprob):
normalize(emissionprob, 1) # added axis term
和
def normalize(A, axis=None):
A += EPS
Asum = A.sum(axis)
if axis and A.ndim > 1:
# Make sure we don't divide by zero.
Asum[Asum == 0] = 1
shape = list(A.shape)
shape[axis] = 1
Asum.shape = shape
A /= Asum # this is true in-place, it was `return A / Asum` <<= here
关于python - Scikit 的隐马尔可夫模型接受加起来不等于 1 的观察概率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23520101/