在这种情况下如何使用切片符号?
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 的概率。假设 A
和 B
具有相同的形状
您可以为此使用 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
是一个取整B
或B[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. ])
我正在解决一个问题,其中我使用两个大矩阵 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 的概率。假设 A
和 B
具有相同的形状
您可以为此使用 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
是一个取整B
或B[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. ])