基于方差/ Stddev矩阵的高斯噪声破坏张量

时间:2018-03-23 14:21:13

标签: python tensorflow normal-distribution noise

我有一个CNN输出掩码( logits shape = [batch, x, y, classes] )和一个矩阵( sigma )为每个logit分配高斯噪声的stddev(即 sigma.shape = [x, y, classes] )。 我想基于它的相应sigma用高斯噪声来破坏每个logit。在tensorflow中,我只找到了一个适用于标量的高斯:tf.random_normal

因此我使用循环,分别“计算”每个logit的噪声(mean = logit[b, x, y, c]stddev = sigma[x, y, c])并使用tf.stack来取回我的4-D Tensor。但是:对于 [1, 1024, 1024, 2] -Tensor,这已经需要很长时间(达到“未完成”的程度),这是有道理的,我想因为它必须创建并堆叠> 100万个张量对象。 无论如何,我很确定这不是要走的路......

但是我应该怎么做呢? 是否有tf.random_normal允许更高维度的工作?

我知道tf.random_normal可以使用(任意)shape返回更具维度的Tensor,但这对我不起作用,因为它将相同的stddev应用于每个元素(均值为'n}因为我可以产生0均值噪声和tf.add())。

如果它以任何方式相关:我现在可以忍受的妥协(为了加快速度)将仅使用基于像素的stddev生成噪声(不是在类上),即* {{1} } *。但这只消除了一个循环而不是主要问题(x * y)。

这里是“循环”方法的代码。我测试了它的小值(sigma.shape = [x, y]。我知道我可以省略[1, 8, 8, 2] - 循环,但这不是“肉”成本,x * y计算是真正的问题

for b

1 个答案:

答案 0 :(得分:0)

所以我实际上找到了一个很好的解决方法,使用正态分布N(0, 1) 乘以 σ(西格玛)的情况与正态分布相同< strong> stddev σ(sigma)N(0, σ**2)

N(0,σ**2) = N(0,1)⋅σ

因此你可以这样做:

# sigma can be of shape of logits or needs to be broadcastable
sigma = tf.Placeholder(shape=tf.shape(logits), dtype=logits.dtype)
def corrupt_logits(logits, sigma):
    # generate a normal distribution N(0,1) of desired shape (4D in my case)
    gaussian = tf.random_normal(tf.shape(logits), mean=0.0, stddev=1.0, dtype=logits.dtype)
    # turn into normal distribution N(0,σ**2) by multiplying with σ
    # since sigma is a 4D tensor of tf.shape(logits), it can "assign" an individual σ to each logit
    noise = tf.multiply(gaussian, sigma)
    # add zero-mean/stddev-σ noise to logits
    return tf.add(logits, noise)

这比使用for循环更好,并支持各种变体,因为如果sigma对于某个维度是相同的(例如,对于每个x,y只有不同),它会自动在其他维度上广播(例如batch_size,classes)。