用随机数替换条件下的numpy数组值
Posted
技术标签:
【中文标题】用随机数替换条件下的numpy数组值【英文标题】:Replace numpy array value on condition with random number 【发布时间】:2017-07-19 22:26:59 【问题描述】:我需要根据条件用随机数替换 numpy 数组中的一些值。
我有一个函数可以在 50% 的时间内添加随机值:
def add_noise(noise_factor=0.5):
chance = random.randint(1,100)
threshold_prob = noise_factor * 100.
if chance <= threshold_prob:
noise = float(np.random.randint(1,100))
else:
noise = 0.
return(noise)
但是当我调用 numpy 函数时,它会将所有匹配值替换为生成的随机数:
np.place(X, X==0., add_noise(0.5))
这样做的问题是 add_noise() 只运行一次,它将所有 0. 值替换为噪声值。
我要做的是“迭代” numpy 数组中的每个元素,检查条件(是否 ==0。),我想每次都通过 add_noise() 生成噪声值。
我可以通过遍历每一行和每一列的 for 循环来做到这一点,但有人知道更有效的方法吗?
【问题讨论】:
发布的解决方案是否适合您? 是的,矢量化方法很好。谢谢。 【参考方案1】:你可以对你的函数进行矢量化,这样可以很容易地应用于每个元素,而且我想效率也很高。
import random
import numpy as np
def add_noise(x):
if not x:
if random.random() <= 0.5:
noise = float(np.random.randint(1,100))
return noise
else:
return 0
else:
return x
x = np.zeros(shape=(10, 10))
n = np.vectorize(add_noise)
x = n(x)
【讨论】:
【参考方案2】:这是一种矢量化方法 -
noise_factor = 0.5 # Input param
# Get mask of zero places and the count of it. Also compute threshold
mask = X==0
c = np.count_nonzero(mask)
threshold_prob = noise_factor * 100.
# Generate noise numbers for count number of times.
# This is where vectorization comes into the play.
nums = np.random.randint(1,100, c)
# Finally piece of the vectorization comes through replacing that IF-ELSE
# with np,where that does the same op of choosing but in a vectorized way
vals = np.where(nums <= threshold_prob, np.random.randint(1,100, c) , 0)
# Assign back into X
X[mask] = vals
额外的好处是我们将0s
的mask
重新用于add_noise
操作,也用于分配回X
。这取代了np.place
的使用,是一种效率标准。
进一步提升性能
我们可以在计算 nums
和 vals
的步骤中进一步优化,这些步骤使用两个随机数生成步骤,而是这样做一次并在第二步重复使用,就像这样 -
nums = np.random.randint(1,100, (2,c))
vals = np.where(nums[0] <= threshold_prob, nums[1] , 0)
【讨论】:
【参考方案3】:如果我理解正确,您想根据两个条件将 numpy 数组的值更改为随机值。
-
值应该为零
一些随机的机会因素
对于这两个条件,您可以创建两个掩码并将它们与np.logical_and
组合。并且您可以使用np.random
方法获取随机数数组。
import numpy as np
def add_perhaps_noise_if_zero(x, threshold=0.5):
mask_1 = x == 0.0
mask_2 = np.random.random(x.shape) <= threshold
mask_combined = np.logical_and(mask_1, mask_2)
x[mask_combined] += np.random.random(x.shape)[mask_combined]
return x
x = np.zeros((5,5))
for i in range(5):
print(x)
x = add_perhaps_noise_if_zero(x)
【讨论】:
以上是关于用随机数替换条件下的numpy数组值的主要内容,如果未能解决你的问题,请参考以下文章