在Python中生成马尔可夫转移矩阵

st1*_*297 12 markov-chains markov-models python-3.x

想象一下,我有一系列4种可能的马尔可夫状态(A,B,C,D):

X = [A, B, B, C, B, A, D, D, A, B, A, D, ....]
Run Code Online (Sandbox Code Playgroud)

如何使用Python生成马尔可夫变换矩阵?矩阵必须是4乘4,表示从每个状态移动到其他3个状态的概率.我一直在网上查看很多例子,但是在所有这些例子中,给出了矩阵,而不是基于数据计算的.我也研究了hmmlearn,但我没有读到如何让它吐出过渡矩阵.有没有我可以用于此目的的图书馆?

这是我在Python中尝试做的确切事情的R代码:https: //stats.stackexchange.com/questions/26722/calculate-transition-matrix-markov-in-r

Joh*_*man 18

这可能会给你一些想法:

transitions = ['A', 'B', 'B', 'C', 'B', 'A', 'D', 'D', 'A', 'B', 'A', 'D']

def rank(c):
    return ord(c) - ord('A')

T = [rank(c) for c in transitions]

#create matrix of zeros

M = [[0]*4 for _ in range(4)]

for (i,j) in zip(T,T[1:]):
    M[i][j] += 1

#now convert to probabilities:
for row in M:
    n = sum(row)
    if n > 0:
        row[:] = [f/sum(row) for f in row]

#print M:

for row in M:
    print(row)
Run Code Online (Sandbox Code Playgroud)

输出:

[0.0, 0.5, 0.0, 0.5]
[0.5, 0.25, 0.25, 0.0]
[0.0, 1.0, 0.0, 0.0]
[0.5, 0.0, 0.0, 0.5]
Run Code Online (Sandbox Code Playgroud)

On Edit这是一个实现上述想法的函数:

#the following code takes a list such as
#[1,1,2,6,8,5,5,7,8,8,1,1,4,5,5,0,0,0,1,1,4,4,5,1,3,3,4,5,4,1,1]
#with states labeled as successive integers starting with 0
#and returns a transition matrix, M,
#where M[i][j] is the probability of transitioning from i to j

def transition_matrix(transitions):
    n = 1+ max(transitions) #number of states

    M = [[0]*n for _ in range(n)]

    for (i,j) in zip(transitions,transitions[1:]):
        M[i][j] += 1

    #now convert to probabilities:
    for row in M:
        s = sum(row)
        if s > 0:
            row[:] = [f/s for f in row]
    return M

#test:

t = [1,1,2,6,8,5,5,7,8,8,1,1,4,5,5,0,0,0,1,1,4,4,5,1,3,3,4,5,4,1,1]
m = transition_matrix(t)
for row in m: print(' '.join('{0:.2f}'.format(x) for x in row))
Run Code Online (Sandbox Code Playgroud)

输出:

0.67 0.33 0.00 0.00 0.00 0.00 0.00 0.00 0.00
0.00 0.50 0.12 0.12 0.25 0.00 0.00 0.00 0.00
0.00 0.00 0.00 0.00 0.00 0.00 1.00 0.00 0.00
0.00 0.00 0.00 0.50 0.50 0.00 0.00 0.00 0.00
0.00 0.20 0.00 0.00 0.20 0.60 0.00 0.00 0.00
0.17 0.17 0.00 0.00 0.17 0.33 0.00 0.17 0.00
0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 1.00
0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 1.00
0.00 0.33 0.00 0.00 0.00 0.33 0.00 0.00 0.33
Run Code Online (Sandbox Code Playgroud)


Iai*_*n D 13

如果您想在 pandas 中完成这一切,这里有一种适用于非数字数据的方法:

import pandas as pd
transitions = ['A', 'B', 'B', 'C', 'B', 'A', 'D', 'D', 'A', 'B', 'A', 'D']

df = pd.DataFrame(transitions)

# create a new column with data shifted one space
df['shift'] = df[0].shift(-1)

# add a count column (for group by function)
df['count'] = 1

# groupby and then unstack, fill the zeros
trans_mat = df.groupby([0, 'shift']).count().unstack().fillna(0)

# normalise by occurences and save values to get transition matrix
trans_mat = trans_mat.div(trans_mat.sum(axis=1), axis=0).values
Run Code Online (Sandbox Code Playgroud)

它比纯 python 方法慢,但由于灵活性和避免创建自己的函数而可能是值得的。