【问题标题】:How to generate a random sequence given a probability matrix of transitions?如何在给定转换概率矩阵的情况下生成随机序列?
【发布时间】:2019-12-24 11:51:31
【问题描述】:

以下脚本为给定列表生成概率矩阵:

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)

输出

[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]

我现在想做相反的事情,按照概率矩阵制作一个新的 A B C D 转移列表。
我怎样才能做到这一点?

【问题讨论】:

  • 您的预期输出是什么?应该如何实现?
  • 我认为这个想法是生成一个新的随机序列,其中给定当前字母A,下一个是概率为0的A,概率为0.5的B,概率为0的C,概率为0.5的D。因此,使用矩阵的权重。第一个字母应该是什么还不是很清楚。可能只是 A,也可能是与原始序列具有相同权重的随机数?
  • @TimStack,正是 Johan 所说的。第一个字母可以是随机的。所以一个给定长度的随机序列,比如说 10 个字母,遵循 brobability 矩阵,就像 Johan 解释的那样。
  • @JohanC,没错!
  • 我理解您正在构建马尔可夫模型是否正确?

标签: python matrix probability markov-chains


【解决方案1】:

随机库的choices 函数可能会有所帮助。由于问题没有说明如何选择第一个字母,所以这里选择它的概率与原始列表的内容相同。

从 Python 3.6 开始,random.choices 接受带权重的参数。对它们进行规范化并不是绝对必要的。

import random

letter = random.choice(transitions)  # take a starting letter with the same weights as the original list
new_list = [letter]
for _ in range(len(transitions) - 1):
    letter = chr(random.choices(range(4), weights=M[rank(letter)])[0] + ord('A'))
    new_list.append(letter)
print(new_list)

完整的代码可以在某种程度上推广到任何类型的节点,而不仅仅是连续的字母:

from _collections import defaultdict
import random

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

nodes = sorted(set(transitions))  # a list of all letters used
M = defaultdict(int)  # dictionary counting the occurrences for each transition i,j)

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

# dictionary with for each node a list of frequencies for the transition to a next node
T = {i: [M[(i, j)] for j in nodes] for i in nodes}

# node = random.choice(transitions) # chose the first node randomly with the same probability as the original list
node = random.choice(nodes) # chose the first node randomly, each node with equal probability
new_list = [node]
for _ in range(9):
    node = random.choices(nodes, T[node])[0]
    new_list.append(node)

print(new_list)

示例输出:['D', 'A', 'D', 'A', 'D', 'D', 'A', 'D', 'A', 'B']

【讨论】:

    【解决方案2】:

    在我看来,您正在尝试创建马尔可夫模型。 作为一名生物信息学学生,我碰巧对(隐藏)马尔可夫模型有一些经验,因此我会使用嵌套字典来简化矩阵的使用。请注意,我已经导入了numpy.random 函数。

    希望这会有所帮助!

    import numpy.random as rnd
    
    alphabet = ['A', 'B', 'C', 'D']
    transitions = ['A', 'B', 'B', 'C', 'B', 'A', 'D', 'D', 'A', 'B', 'A', 'D']
    
    # Create probability matrix filled with zeroes
    # Matrix consists of nested libraries
    prob_matrix = {}
    for i in alphabet:
        prob_matrix[i] = {}
        for j in alphabet:
            prob_matrix[i][j] = 0.0
    
    def rank(c):
       return ord(c) - ord('A')
    
    # fill matrix with numbers based on transitions list
    T = [rank(c) for c in transitions]
    for (i,j) in zip(T,T[1:]):
        prob_matrix[alphabet[i]][alphabet[j]] += 1
    
    # convert to probabilities
    for row in prob_matrix:
       total = sum([prob_matrix[row][column] for column in prob_matrix[row]])
       if total > 0:
           for column in prob_matrix[row]:
               prob_matrix[row][column] /= total
    
    # generate first random sequence letter
    outputseq = rnd.choice(alphabet, None)
    
    # generate rest of string based on probability matrix
    for i in range(11):
        probabilities = [prob_matrix[outputseq[-1]][j] for j in alphabet]
        outputseq += rnd.choice(alphabet, None, False, probabilities)
    
    # output generated sequence
    print(outputseq)
    

    【讨论】:

    • 非常感谢!有没有办法让我的“字母表”变成非字母表?假设使用字母 B、F、A、L、T?当我现在更改我的字母时,我在 '''prob_matrix[alphabet[i]][alphabet[j]] += 1''' 行出现错误。
    • @Lina transitions 列表必须包含与 alphabet 列表相同的字符集。你确定是这种情况吗?
    • 是的,都是这样。如果我添加一个“E”然后一个“F”就可以了,但是如果我想通过示例添加一个 L,它会给我一个错误消息,所以我想也许列表必须是字母表中的连续字母?跨度>
    • 代码中断是因为您最初填充矩阵的方式。你需要想出另一种方法,我不知道你的要求是什么。
    猜你喜欢
    • 2015-10-22
    • 2019-02-01
    • 2016-01-06
    • 1970-01-01
    • 2020-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多