【问题标题】:Building N-th order Markovian transition matrix from a given sequence从给定序列构建 N 阶马尔可夫转移矩阵
【发布时间】:2019-09-22 11:35:22
【问题描述】:

我正在尝试创建一个函数,该函数可以将给定的输入序列转换为请求顺序的转换矩阵。我找到了一阶马尔可夫转移矩阵的实现。

现在,我希望能够提出一个可以计算二阶和三阶转换矩阵的解决方案。

一阶矩阵实现示例:

import numpy as np

# sequence with 3 states -> 0, 1, 2

a = [0, 1, 0, 0, 0, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 1, 2, 2, 2, 0, 0, 2]


def transition_matrix_first_order(seq):
    M = np.full((3, 3), fill_value = 1/3, dtype= np.float64)
    for (i,j) in zip(seq, seq[1:]):
        M[i, j] += 1

    M = M / M.sum(axis = 1, keepdims = True)

    return M

print(transition_matrix_first_order(a))

这给了我这个:

[[0.61111111 0.19444444 0.19444444]
 [0.38888889 0.38888889 0.22222222]
 [0.22222222 0.22222222 0.55555556]]

当制作一个二阶矩阵时,它应该有unique_state_count ** order 行和unique_state_count 列。在上面的示例中,我有 3 个唯一状态,因此矩阵将具有 9x3 结构。 理想的功能样本: cal_tr_matrix(seq, unique_state_count, order)

【问题讨论】:

  • 好吧,当您增加矩阵时,您应该简单地考虑最后一个先前的索引。我还会从for 循环中删除M = M/M.sum(..),因为这看起来不正确。
  • 对不起,我会编辑它。从笔记本复制粘贴时我犯了一个错误:)

标签: python numpy probability markov-chains


【解决方案1】:

我认为您对马尔可夫链及其转换矩阵有一点误解。

首先,很遗憾,您的函数生成的估计转换矩阵不正确。为什么?让我们刷新一下。

具有N不同状态的离散时间的离散马尔可夫链具有大小为N x N的转移矩阵P,其中(i,j)元素为P(X_1=j|X_0=i),即从状态@转移的概率987654325@ 在单个时间步中声明 j

现在,顺序为n 的转移矩阵,表示为P^{n},再次是一个大小为N x N 的矩阵,其中(i,j)元素为P(X_n=j|X_0=i),即从状态i 转移的概率在n 时间步中声明j

一个奇妙的结果是:P^{n} = P^n,即采用n 单步转移矩阵的幂得到n-step 转移矩阵。

现在回顾一下,所需要的只是从给定的序列中估计 P,然后估计 P^{n} 可以只使用已经估计的 P 并取 n 的次方矩阵。那么如何估计矩阵P呢?好吧,如果我们将N_{ij} 表示从状态i 转换到状态j 的观察次数,N_{i*} 表示处于状态i 的观察次数,然后P_{ij} = N_{ij} / N_{i*}

这里是 Python 的总体情况:

import numpy as np

def transition_matrix(arr, n=1):
    """"
    Computes the transition matrix from Markov chain sequence of order `n`.

    :param arr: Discrete Markov chain state sequence in discrete time with states in 0, ..., N
    :param n: Transition order
    """

    M = np.zeros(shape=(max(arr) + 1, max(arr) + 1))
    for (i, j) in zip(arr, arr[1:]):
        M[i, j] += 1

    T = (M.T / M.sum(axis=1)).T

    return np.linalg.matrix_power(T, n)

transition_matrix(arr=a, n=1)

>>> array([[0.63636364, 0.18181818, 0.18181818],
>>>       [0.4       , 0.4       , 0.2       ],
>>>       [0.2       , 0.2       , 0.6       ]])

transition_matrix(arr=a, n=2)

>>> array([[0.51404959, 0.22479339, 0.26115702],
>>>       [0.45454545, 0.27272727, 0.27272727],
>>>       [0.32727273, 0.23636364, 0.43636364]])

transition_matrix(arr=a, n=3)

>>> array([[0.46927122, 0.23561232, 0.29511645],
>>>       [0.45289256, 0.24628099, 0.30082645],
>>>       [0.39008264, 0.24132231, 0.36859504]])

有趣的是,当您将顺序 n 设置为一个相当高的数字时,P 矩阵的越来越高的幂似乎会收敛到一些非常具体的值。这被称为马尔可夫链的平稳/不变分布,它很好地表明了链在很长一段时间/转换中的行为方式。另外:

P = transition_matrix(a, 1)
P111 = transition_matrix(a, 111)
print(P)
print(P111.dot(P))

编辑:现在根据您的评论调整解决方案,我建议使用更高维度的矩阵来获得更高的订单,而不是增加行数。一种方法是这样的:

def cal_tr_matrix(arr, order):

    _shape = (max(arr) + 1,) * (order + 1)
    M = np.zeros(_shape)

    for _ind in zip(*[arr[_x:] for _x in range(order + 1)]):
        M[_ind] += 1
    return M

res1 = cal_tr_matrix(a, 1)
res2 = cal_tr_matrix(a, 2)

现在元素res1[i, j] 表示发生了多少次转换 i->j,而元素res2[i, j, k] 表示发生了多少次转换 i->j->k。

【讨论】:

  • 您好,理查德,感谢您的意见。一阶转移矩阵是指状态 i 后跟 j 的次数。在我的示例中,我正在构建一个 3x3 矩阵,它显示状态 0 后面跟着状态 0 的次数等等。我所说的二阶矩阵的意思是,现在我想知道 0 - 0 后面跟着多少次0 , 0 -0 后跟 1 .... 2-1 后跟 0 等等。我的行将是这个序列长度为 2 的排列,列将是状态本身。也许我在问题中使用了不同的符号,我不是专业的数学家
猜你喜欢
  • 1970-01-01
  • 2021-04-12
  • 1970-01-01
  • 2018-04-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-08
  • 2015-12-20
  • 2023-03-14
相关资源
最近更新 更多