我有一个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
答案 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)。