在这种情况下如何使用切片符号?

How to use slice notation in this case?

我正在解决一个问题,其中我使用两个大矩阵 A 和 B。矩阵 A 由 1 和 0 组成,矩阵 B 由 [0,...,10].[=12= 范围内的整数组成]

在某些时候,我必须更新 A 的组件,如果组件为 1,则它保持为 1。如果组件为 0,则它可以以概率 p 保持为 0 或以概率更改为 1 1-p。参数 p 是矩阵 B 相同分量的函数,即,我有一个概率列表,如果我更新 A[i,j],则 p 等于向量概率

我可以使用以下代码进行更新:

import numpy as np
for i in range(n):
      for j in range(n):
        if A[i,j]==0:
            pass
        else:
            A[i,j]=np.random.choice([0,1],p=[probabilities[B[i,j]],1-probabilities[B[i,j]]])

        

我认为应该有一种使用切片表示法更新矩阵 A 的更快方法。有什么建议吗? 看到这个问题等同于,给定一个向量 'a' 和一个具有正项的矩阵 'B',得到一个矩阵 C 其中 C[i,j]=a[B[i,j]]

一般答案

您可以通过生成具有连续概率的随机值,然后将生成的值与该分布的逆累积概率函数进行比较来实现此目的。

要实用

让我们使用 [0, 1) 范围内的均匀随机变量 X,那么 X < a 是 a 的概率。假设 AB 具有相同的形状

您可以为此使用 numpy.where(确保您的概率变量是一个 numpy 数组)

A[:,:] = np.where(A == 0, np.where(np.random.rand(*A.shape) < probabilities[B], 1, 0), A);

如果您想避免为 A 非零的位置计算随机值,那么您需要更复杂的索引。

A[A == 0] = np.where(np.random.rand(*A[A == 0].shape) < probabilities[B[A == 0]], 1, 0);

在 0-1 范围内制造许多 p

In [36]: p=np.arange(1000)/1000

您的 choice 使用 - 和 sum 来获得总体统计数据:

In [37]: sum([np.random.choice([0,1],p=[p[i],1-p[i]]) for i in range(p.shape[0])])
Out[37]: 485

和一个统计上相似的随机数组,但没有理解:

In [38]: (np.random.rand(p.shape[0])>p).astype(int).sum()
Out[38]: 496

欢迎您进行其他测试来验证它们的等效性。

如果probabilities是一个取整BB[mask]的函数,我们应该可以做到:

mask = A==0
n = mask.ravel().sum() # the number of true elements
A[mask] = (np.random.rand(n)>probabilities(B[mask])).astype(int)

要对此进行测试:

In [39]: A = np.random.randint(0,2, (4,5))
In [40]: A
Out[40]: 
array([[1, 1, 0, 0, 0],
       [1, 1, 1, 1, 1],
       [1, 1, 0, 0, 1],
       [1, 1, 1, 1, 0]])
In [41]: mask = A==0
In [42]: A[mask]
Out[42]: array([0, 0, 0, 0, 0, 0])
In [43]: B = np.arange(1,21).reshape(4,5)
In [44]: def foo(B):       # scale the B values to probabilites
    ...:     return B/20
    ...: 
In [45]: foo(B)
Out[45]: 
array([[0.05, 0.1 , 0.15, 0.2 , 0.25],
       [0.3 , 0.35, 0.4 , 0.45, 0.5 ],
       [0.55, 0.6 , 0.65, 0.7 , 0.75],
       [0.8 , 0.85, 0.9 , 0.95, 1.  ]])
In [46]: n = mask.ravel().sum()
In [47]: n
Out[47]: 6

In [51]: (np.random.rand(n)>foo(B[mask])).astype(int)
Out[51]: array([1, 1, 0, 1, 1, 0])
In [52]: A[mask] = (np.random.rand(n)>foo(B[mask])).astype(int)
In [53]: A
Out[53]: 
array([[1, 1, 1, 1, 1],
       [1, 1, 1, 1, 1],
       [1, 1, 0, 1, 1],
       [1, 1, 1, 1, 0]])

In [54]: foo(B[mask])
Out[54]: array([0.15, 0.2 , 0.25, 0.65, 0.7 , 1.  ])