2017-02-28 90 views
2

我需要用一個隨機數替換一個numpy數組中的某些值。用條件隨機數替換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循環遍歷每一行和每列,但有人知道更有效的方式嗎?

+0

發佈的解決方案是否適合您? – Divakar

+0

是的,矢量化的方法很好。謝謝。 –

回答

1

這裏有一個量化的方法 -

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 

額外的好處是,我們的0smaskadd_noise操作,還用於分配回X重新使用。這取代了np.place的使用並且意味着效率標準。

進一步的性能提升

我們能夠在計算numsvals,通過這樣使用隨機數生成的兩個步驟的步驟進一步優化,與其一次,並重新使用在第二步中,像這樣 -

nums = np.random.randint(1,100, (2,c)) 
vals = np.where(nums[0] <= threshold_prob, nums[1] , 0) 
0

你可以矢量化你的函數,這使得它很容易適用於每一個元素,而且我認爲它也很有效率。

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) 
0

如果我理解正確,您想要根據兩個條件將numpy數組的值更改爲隨機值。

  1. 值應爲零
  2. 一些隨機的機會因素

對於您可以創建兩個口罩,並與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)