python - 遵循某种概率分布,为给定大小的位串生成转移概率矩阵

标签 python numpy probability distribution

我想创建一个 8x8 矩阵,它提供位通信中的错误概率。该矩阵如下所示:enter image description here

列代表观察到的数量,行代表测量的数量。一个元素p[i,j]相当于条件概率p(j|i) 。例如,元素 p[0,1]给出观察字符串 001 的概率当实际值为000时,即,它测量 p(001|000) .

问题:如何在 Python 中创建这样一个矩阵

  1. 位翻转次数越多,等效条件概率就越小(例如 p(100|000)<p(110|000) ?
  2. 如何启用“不对称”。即 p(001|000)< p(000|001) 的概率。也就是说,与从 0 到 1 的转换相比,偏向于以更高的概率从 1 转换到 0。

当然,每行的概率之和必须等于 1。

总而言之,我想在 Python 中创建一个函数,该函数将整数 n 作为输入。 (矩阵的大小,或等效地,其中 2^n 是位串的长度)并输出具有上述指定规则的概率转移矩阵。

困难在于如何实现概率分布来填充单元格。

创建 8x8 数组并填充对角线很简单:

P = np.zeros((8,8))
for i in range(8):
    for j in range(8):
        if i==j:
            P[i,j]=1

同样,用固定数字填充给定行或给定列也很简单。但是,我不知道(如何开始)按照上述规则填充这样的矩阵,甚至不知道如何准确地定义元素必须遵循的分布。

最佳答案

事实证明,无需 numpyscipy 即可轻松完成此操作。我使用 pandas 进行精美的打印。

逻辑是,对于每一位,您都有可能翻转(p01p10)或保持不变(p00p11)。将一个位串转换为另一个位串需要乘以每个 n 位的适当概率。

例如:P(010|001) = P(0->0) * P(1->0) * P(0->1) = p00 * p10 * p01

对于每个发送观察组合都会重复此过程。

您可以使用 nested ternary assignment 将下面的两级 if 语句进一步减少为一行。 ,但我认为这是简洁和可读的一个很好的平衡:

import pandas as pd


def p(sent, observed, p01, p10):
    """Return the probability of 'sent' being received as 'observed'
    given p01 (the probability a bit flips from a 0->1) and p10 (the
    probability a bit flips from 1->0).
    """
    p00 = 1 - p01
    p11 = 1 - p10
    r = 1
    for i, _ in enumerate(sent):
        if sent[i] == "0":
            r *= p00 if observed[i] == "0" else p01
        else:
            r *= p10 if observed[i] == "0" else p11
    return r

def generate_error_matrix(n, p01, p10):
    """Print a matrix of the transitions of all permutations of bit
    errors for a given bit length.

    Parameters:
        n - the number of bits
        p01 - probability of a bit flipping from 0 to 1
        p10 - probability of a bit flipping from 1 to 0
    """
    labels = [f"{i:0{n}b}" for i in range(0, 2**n)]
    result = pd.DataFrame(index=labels, columns=labels)
    for rowIndex, row in result.iterrows():
        for columnIndex, _ in row.items():
            result.at[rowIndex, columnIndex] = p(rowIndex, columnIndex, p01, p10)
    return result

这是一个示例:

print(generate_error_matrix(n=3, p01=0.2, p10=0.1))
       000    001    010    011    100    101    110    111
000  0.512  0.128  0.128  0.032  0.128  0.032  0.032  0.008
001  0.064  0.576  0.016  0.144  0.016  0.144  0.004  0.036
010  0.064  0.016  0.576  0.144  0.016  0.004  0.144  0.036
011  0.008  0.072  0.072  0.648  0.002  0.018  0.018  0.162
100  0.064  0.016  0.016  0.004  0.576  0.144  0.144  0.036
101  0.008  0.072  0.002  0.018  0.072  0.648  0.018  0.162
110  0.008  0.002  0.072  0.018  0.072  0.018  0.648  0.162
111  0.001  0.009  0.009  0.081  0.009  0.081  0.081  0.729

以及一些边缘情况:

零总是翻转为一,一永远不会翻转为零:

print(generate_error_matrix(n=3, p01=1, p10=0))
    000 001 010 011 100 101 110 111
000   0   0   0   0   0   0   0   1
001   0   0   0   0   0   0   0   1
010   0   0   0   0   0   0   0   1
011   0   0   0   0   0   0   0   1
100   0   0   0   0   0   0   0   1
101   0   0   0   0   0   0   0   1
110   0   0   0   0   0   0   0   1
111   0   0   0   0   0   0   0   1

1 总是翻转到 0,0 永远不会翻转到 1:

print(generate_error_matrix(n=3, p01=0, p10=1))
    000 001 010 011 100 101 110 111
000   1   0   0   0   0   0   0   0
001   1   0   0   0   0   0   0   0
010   1   0   0   0   0   0   0   0
011   1   0   0   0   0   0   0   0
100   1   0   0   0   0   0   0   0
101   1   0   0   0   0   0   0   0
110   1   0   0   0   0   0   0   0
111   1   0   0   0   0   0   0   0

位总是翻转:

print(generate_error_matrix(n=3, p01=1, p10=1))
    000 001 010 011 100 101 110 111
000   0   0   0   0   0   0   0   1
001   0   0   0   0   0   0   1   0
010   0   0   0   0   0   1   0   0
011   0   0   0   0   1   0   0   0
100   0   0   0   1   0   0   0   0
101   0   0   1   0   0   0   0   0
110   0   1   0   0   0   0   0   0
111   1   0   0   0   0   0   0   0

无论方向如何,每个位都有 50% 的机会翻转:

print(generate_error_matrix(n=3, p01=0.5, p10=0.5))
       000    001    010    011    100    101    110    111
000  0.125  0.125  0.125  0.125  0.125  0.125  0.125  0.125
001  0.125  0.125  0.125  0.125  0.125  0.125  0.125  0.125
010  0.125  0.125  0.125  0.125  0.125  0.125  0.125  0.125
011  0.125  0.125  0.125  0.125  0.125  0.125  0.125  0.125
100  0.125  0.125  0.125  0.125  0.125  0.125  0.125  0.125
101  0.125  0.125  0.125  0.125  0.125  0.125  0.125  0.125
110  0.125  0.125  0.125  0.125  0.125  0.125  0.125  0.125
111  0.125  0.125  0.125  0.125  0.125  0.125  0.125  0.125

关于python - 遵循某种概率分布,为给定大小的位串生成转移概率矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72434166/

相关文章:

python - 将 "Infinite" float 转换为整数

python - 使用 python 向 docx 文件添加 header

numpy - 拆分数字并分配给 numpy 数组中的行中的元素

python - numpy:替换 recarray 中的值

algorithm - 通过回溯求解唯一路径的快速算法

python - 如何使用 opencv python 填充多边形

python - subprocess.Popen 系统属性 arg 中的空格

python - 从 matplotlib 中的直方图数据绘制折线图

statistics - 重尾分布 - 威 bool

machine-learning - 尝试理解线性回归中的期望值