要解决从指定列表范围的数字列表/数字数组中选择随机数的一般情况,我们将使用一个技巧来创建一个统一的rand数组,添加由间隔长度指定的偏移量,然后执行
argsort。实现看起来像这样-
def random_num_per_grp(L): # For each element in L pick a random number within range specified by it r1 = np.random.rand(np.sum(L)) + np.repeat(np.arange(len(L)),L) offset = np.r_[0,np.cumsum(L[:-1])] return r1.argsort()[offset] - offset
样品盒-
In [217]: L = [5,4,2]In [218]: random_num_per_grp(L) # i.e. select one per [0-5,0-4,0-2]Out[218]: array([2, 0, 1])
因此,输出将具有与输入中相同数量的元素,
L而第一个输出元素将位于in中
[0,5),第二个元素
[0,4)等等。
在这里解决我们的问题
为了解决这里的问题,我们将使用修改后的版本(特别是在函数的末尾删除偏移量删除部分,就像这样-
def random_num_per_grp_cumsumed(L): # For each element in L pick a random number within range specified by it # The final output would be a cumsumed one for use with indexing, etc. r1 = np.random.rand(np.sum(L)) + np.repeat(np.arange(len(L)),L) offset = np.r_[0,np.cumsum(L[:-1])] return r1.argsort()[offset]
方法1
一种解决方案可以像这样使用它-
def argmax_per_row_randtie(a): max_mask = a==a.max(1,keepdims=1) m,n = a.shape all_argmax_idx = np.flatnonzero(max_mask) offset = np.arange(m)*n return all_argmax_idx[random_num_per_grp_cumsumed(max_mask.sum(1))] - offset
验证
让我们用大量的运行来测试给定的样本,并计算每一行每个索引的出现次数
In [235]: aOut[235]: array([[1, 3, 3], [4, 5, 6], [7, 8, 1]])In [225]: all_out = np.array([argmax_per_row_randtie(a) for i in range(10000)])# The first element (row=0) should have similar probabilities for 1 and 2In [236]: (all_out[:,0]==1).mean()Out[236]: 0.504In [237]: (all_out[:,0]==2).mean()Out[237]: 0.496# The second element (row=1) should only have 2In [238]: (all_out[:,1]==2).mean()Out[238]: 1.0# The third element (row=2) should only have 1In [239]: (all_out[:,2]==1).mean()Out[239]: 1.0
方法2:masking
用于表现
我们可以利用
masking并因此避免
flatnonzero像通常使用布尔数组那样获得性能的意图。此外,我们将概括性地覆盖行(轴= 1)和列(轴=
0),以便为我们自己修改,例如-
def argmax_randtie_masking_generic(a, axis=1): max_mask = a==a.max(axis=axis,keepdims=True) m,n = a.shape L = max_mask.sum(axis=axis) set_mask = np.zeros(L.sum(), dtype=bool) select_idx = random_num_per_grp_cumsumed(L) set_mask[select_idx] = True if axis==0: max_mask.T[max_mask.T] = set_mask else: max_mask[max_mask] = set_mask return max_mask.argmax(axis=axis)
在样品运行
axis=0和
axis=1-
In [423]: aOut[423]: array([[1, 3, 3], [4, 5, 6], [7, 8, 1]])In [424]: argmax_randtie_masking_generic(a, axis=1)Out[424]: array([1, 2, 1])In [425]: argmax_randtie_masking_generic(a, axis=1)Out[425]: array([2, 2, 1])In [426]: a[1,1] = 8In [427]: aOut[427]: array([[1, 3, 3], [4, 8, 6], [7, 8, 1]])In [428]: argmax_randtie_masking_generic(a, axis=0)Out[428]: array([2, 1, 1])In [429]: argmax_randtie_masking_generic(a, axis=0)Out[429]: array([2, 1, 1])In [430]: argmax_randtie_masking_generic(a, axis=0)Out[430]: array([2, 2, 1])
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)