Python 如何以矢量化的方式向numpy二维矩阵添加掩蔽噪声?

Python 如何以矢量化的方式向numpy二维矩阵添加掩蔽噪声?,python,numpy,vectorization,Python,Numpy,Vectorization,我有一个numpy二维阵列X,形状(n个样本,n个特征)。我想对每个样本(即每行)应用掩蔽噪声。基本上,对于每一行条目,我想随机选择全部n_特征元素的一部分frac,并将它们设置为0 到目前为止,我已经对循环的内部进行了矢量化,但无法摆脱外部I循环 我目前的代码如下 def add_noise(X, frac): X_noise = X.copy() n_samples = X.shape[0] n_features = X.shape[1] for i in

我有一个numpy二维阵列
X
,形状
(n个样本,n个特征)
。我想对每个样本(即每行)应用掩蔽噪声。基本上,对于每一行条目,我想随机选择全部
n_特征
元素的一部分
frac
,并将它们设置为
0

到目前为止,我已经对循环的内部进行了矢量化,但无法摆脱外部
I
循环

我目前的代码如下

def add_noise(X, frac):
    X_noise = X.copy()

    n_samples = X.shape[0]
    n_features = X.shape[1]

    for i in range(n_samples):
        mask = np.random.randint(0, n_features, int(frac * n_features))
        X_noise[i][mask] = 0

    return X_noise
下面是一个例子

test_arr = np.arange(1, 11)
test_arr = np.array([test_arr, test_arr])
print(test_arr)
print(add_noise(test_arr, 0.3))

[[ 1  2  3  4  5  6  7  8  9 10]
 [ 1  2  3  4  5  6  7  8  9 10]]
[[ 1  0  3  4  5  6  0  8  9  0]   # 0.3 * num_features = 3 random elements
 [ 0  2  3  4  5  6  7  0  0 10]]  # for each row set to 0

如何摆脱外部循环?

没有什么可以阻止您使用生成完整的索引矩阵,每行一个元素:

k = int(frac * n_features)
indices = np.random.randint(0, n_features, size=(n_samples, k))
X_noise[np.arange(n_samples)[:, None], indices] = 0
索引
np.arange(n_samples)[:,None]
使范围广播到shape
n_samples,k
。这种方法的优点是不需要带遮罩的中间步骤

这种方法存在两个潜在问题:

  • k=int(分形*n_特征)
    不一定是与您要查找的实际分数最接近的整数。更像是
    k=math.round(frac*n\u特性)
  • np.random.randint
    替换样本。这意味着您偶尔会在索引中的同一行上遇到冲突。如果你同意的话,没关系。如果没有,您可以使用进行取样,而无需更换。问题是,然后必须逐个循环每一行
  • 在我看来,一种更“诚实”的方法是生成一系列随机数,并简单地在
    frac
    处对它们设置阈值,这样您的总体噪声接近
    frac
    ,但每行中的噪声都是随机的。这些数字可以通过以下方式生成:

    X_噪声[np.random.sample(size=X_噪声.shape)
    尝试创建0和1的映射,并将测试数组与映射相乘:

    zero_map = np.round(np.random.rand(*test_arr.shape) * (1-frac))
    test_arr = test_arr * zero_map
    

    可以使用numpy函数沿_轴应用_

    def add_noise(X, frac):
        X_noise = X.copy()
    
        n_samples = X.shape[0]
        n_features = X.shape[1]
    
        mask = np.concatenate((np.ones((n_samples,int(frac * n_features)), dtype=np.bool),
                               np.zeros((n_samples, n_features - int(frac * n_features)), dtype=np.bool)),
                               axis=1)
        np.apply_along_axis(np.random.shuffle,1,mask)
        X_noise[mask] = 0
        return X_noise
    

    您是否需要控制
    n\u功能
    dimension?@norok2您能详细说明一下吗?如果您的意思是将元素数设置为0,那么是。否,我的意思是,如果您需要为每个
    n_特征使用不同的
    frac
    值,则所有样本的
    frac
    值都相同。确定。然后注意,如果在
    randint()
    中重复某些索引,代码也可能失败。您可能想改用
    np.random.choice()
    或者直接使用掩码:
    test\u arr[~mask]=0
    是否可以使用
    np.random.choice(…)
    [0,num_features)
    ?然后方法将几乎保持不变。@pmcarpan。此时,您必须执行以下操作
    def add_noise(X, frac):
        X_noise = X.copy()
    
        n_samples = X.shape[0]
        n_features = X.shape[1]
    
        mask = np.concatenate((np.ones((n_samples,int(frac * n_features)), dtype=np.bool),
                               np.zeros((n_samples, n_features - int(frac * n_features)), dtype=np.bool)),
                               axis=1)
        np.apply_along_axis(np.random.shuffle,1,mask)
        X_noise[mask] = 0
        return X_noise