【问题标题】:Corrupting Tensor with Gaussian Noise based on a Variance / Stddev Matrix基于方差/标准差矩阵的高斯噪声破坏张量
【发布时间】:2018-09-02 06:09:43
【问题描述】:

我有一个 CNN 输出掩码 (logits, shape = [batch, x, y, classes]) 和一个矩阵 (sigma) stddev 用于每个 logit 的高斯噪声(即 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 张量。但是:对于 [1, 1024, 1024, 2] -Tensor,这已经花费了很长时间(达到“未完成”的程度),这是有道理的,我想因为它必须创建和堆叠 > 100 万张量对象。 无论如何,我很确定这不是要走的路……

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

我知道tf.random_normal 可以返回一个带有(任意)shape 的更多维张量,但这对我不起作用,因为它将相同的 stddev 应用于每个元素(平均值无关紧要,因为我可能会产生 0-mean 噪声和tf.add())。

如果它以任何方式相关:我现在可以接受的一个折衷方案(以加快速度)是使用 stddev 仅基于像素(不是类)产生噪声,即 *sigma.shape = [x, y]* .但这仅带走了一个循环,而不是主要问题(x*y)。

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

logits = self.output_mask   # e.g. shape: [1, 1024, 1024, 2]
sigma = tf.ones(shape=[1024, 1024, 2], dtype=logits.dtype)  # dummy values, will be a learned parameter later

corrupted_logits_b = []
for b in range(logits.shape[0]):
    corrupted_logits_x = []
    for x in range(logits.shape[1]):
        corrupted_logits_y = []
        for y in range(logits.shape[2]):
            corrupted_logits_c = []
            for c in range(logits.shape[3]):
                # this is where the noise is computed
                # (added to the logit since mean = logit)
                corrupted_logit = tf.random_normal(tf.shape(logits[b, x, y, c]), 
                                                            mean=logits[b, x, y, c], 
                                                            stddev=sigma_val[x, y, c])
                # "values"/logit-tensors are appended to lists and
                # ... and stacked to form higher-dim tensors
                corrupted_logits_c.append(corrupted_logit)
            corrupted_logits_y.append(tf.stack(corrupted_logits_c, axis=-1))
        corrupted_logits_x.append(tf.stack(corrupted_logits_y))
    corrupted_logits_b.append(tf.stack(corrupted_logits_x))
corrupted_logits = tf.stack(corrupted_logits_b, axis=-1)

【问题讨论】:

    标签: python tensorflow normal-distribution noise


    【解决方案1】:

    所以我实际上找到了一个很好的解决方法,使用正态分布N(0, 1) 乘以 σ (sigma) 与正态分布相同 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、类)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-15
      • 2019-08-02
      • 2014-05-06
      • 2018-07-12
      • 2017-08-19
      • 2012-07-02
      • 2017-02-09
      • 2016-02-07
      相关资源
      最近更新 更多