【问题标题】:What's the meaning of the result of two tensors with different shapes subtracting from each other?两个不同形状的张量相减的结果是什么意思?
【发布时间】:2018-10-09 22:01:56
【问题描述】:

我有一个形状为 [batch_size, num_kernels, kernel_dim] 的张量。然后我从中导出两个张量,一个形状为[batch_size, num_kernels, kernel_dim, 1],另一个形状为[1, num_kernels, kernel_dim, batch_size],然后从第一个中减去第二个,得到[batch_size, num_kernels, kernel_dim, batch_size]的形状(通过numpy、tensorflow等)。这是怎么回事?每个维度的含义是什么?例如,num_kernel 是否仍然表示内核数作为原始张量,为什么?

更新:

这就是我的问题出现的地方。它基本上描述了 Tim Salimans 等人在论文“Improved Techniques for Training GANs”中介绍的 minibatch 判别。

我不明白为什么 tensorflow 中的代码成功地计算了上面描述的过程。更具体地说,我想知道第 2 步和第 3 步如何匹配代码。

【问题讨论】:

  • 维度并没有真正的意义,至少不是脱离上下文。结果中第一个batch_size 对应于第一个数组的第一个维度。第二个batch_size 对应于第二个数组的最后一个维度。但是是你赋予了那个维度一些意义或身份。可能是您通过转置原始数组得出第二个数组,也可能您做了其他事情,它的大小为batch_size 只是巧合。
  • 嗨,@hpaulj。我的意思是使其大小为batch_size。假设得到的张量是t,我不确定tf.transpose(tf.reduce_sum(t, 0), [2, 0, 1] )是否等于`tf.reduce_sum(t, 3)
  • 我在我的答案中添加了对这些总和替代方案的测试。

标签: python numpy tensor


【解决方案1】:

真的没有比the docs里的解释更好的办法了,不过我可以试着总结一下。

将一个数组拟合到另一个数组以便您可以在它们之间进行矢量化操作的过程称为“广播”。广播逐个维度进行,从右侧开始。对于每个维度:

  • 如果两个数组在该维度上具有相同的大小……嗯,那很明显。
  • 如果一个数组在该维度上的大小为 1,则会重复。
  • 如果其中一个数组的维度已用完,则将其视为在每个剩余维度中为 1。

例如,如果你想做x + y,其中x是一个20x10的二维数组:

  • 如果y也是20x10,则将y的每一行添加到x中的对应行。并且,对于每个这样的行,它将y 行中的每一列添加到x 行中的相应列。所以,结果是 20x10。
  • 如果 y 是 1x10,它会将来自 y 的单行添加到来自 x 的 20 行中的每一行,并返回 20x10 的结果。
  • 如果y 是20x1,它会将y 的每一行添加到x 的行中,方法是将每个y 行中的单个列添加到x 行中的每一列。同样,20x10。
  • 如果y 是1x1,它会将y 的单行添加到x 的每一行,方法是将y 行中的单列添加到x 行中的每一列。就像向x 添加一个标量一样。同样,20x10。
  • 如果y是10x1,这是一个值错误——1列可以广播到10列,但10行不能广播到20行。
  • 如果 y 是长度为 10 的一维数组,它会将 y 添加到来自 x 的 20 行中的每一行,并返回 20x10 的结果 - 就像 y 是 1x10 一样。
  • 如果y为30x20x10,则将y的30个20x10行中的每一行变为整个20x10x,所以结果为30x20x10。
  • 如果y是30x1x1,则将y的30个1x1行中的每一行添加到整个20x10 x中,所以结果是30x20x10。
  • 如果y 是 30x5x1,这是一个错误——可以广播 1 以匹配 10,并且可以广播来自 x 的缺失维度以匹配 30,但无法广播 5匹配 20。

【讨论】:

  • 谢谢你的回答,我已经知道这些规则了。但是,我不确定生成的张量的维度是否与原来的含义相同。问题中给出了一个例子,另一个例子是如果结果张量中的两个batch_sizes 都表示批量大小
【解决方案2】:

同一个数组的两个版本相减的简单情况是:

In [208]: x = np.arange(10)
In [209]: x[None,:]-x[:,None]     
Out[209]: 
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [-1,  0,  1,  2,  3,  4,  5,  6,  7,  8],
       [-2, -1,  0,  1,  2,  3,  4,  5,  6,  7],
       [-3, -2, -1,  0,  1,  2,  3,  4,  5,  6],
       [-4, -3, -2, -1,  0,  1,  2,  3,  4,  5],
       [-5, -4, -3, -2, -1,  0,  1,  2,  3,  4],
       [-6, -5, -4, -3, -2, -1,  0,  1,  2,  3],
       [-7, -6, -5, -4, -3, -2, -1,  0,  1,  2],
       [-8, -7, -6, -5, -4, -3, -2, -1,  0,  1],
       [-9, -8, -7, -6, -5, -4, -3, -2, -1,  0]])

[209] 是 (1,10) 减去 (10,1) 产生 (10,10) 的情况。实际上是成对的差异。

因此,您的情况可能是批次之间的成对差异。如果您使用,这可能会更清楚(对人类而言):

[1,          batch_size, num_kernels, kernel_dim]
[batch_size, 1,          num_kernels, kernel_dim]
[batch_size, batch_size, num_kernels, kernel_dim]

要测试您的评论,请从不同的维度开始:

In [210]: x = np.arange(2*3*4*5).reshape(2,3,4,5)
In [211]: np.sum(x,0).shape
Out[211]: (3, 4, 5)
In [212]: np.transpose(np.sum(x,0),[2,0,1]).shape
Out[212]: (5, 3, 4)

In [214]: np.sum(x,3).shape
Out[214]: (2, 3, 4)

形状不匹配,因此总和也不匹配(通常)。

【讨论】:

  • 嗨@hpaulj,感谢您的回答。我看到你在更新中使用了不同的batch_size,这就是为什么形状不匹配恕我直言。但是,我在 numpy 中做了类似的测试,确实观察到了两个不同的结果。我只是不明白他们为什么不同。我更新了我的问题,向您展示我的问题出现在哪里。
【解决方案3】:

如果我错了,不要怪我。

假设您有两个二维矩阵XY,形状分别为(x, n)(y, n),并且您想计算L1 距离。你可能想做类似的事情

np.abs(X[:, None, :] - Y).sum(-1)

np.abs(np.expand_dims(X, -1) - np.expand_dims(Y.transpose(1, 0), 0)).sum(1)

它们使用不同的广播方法产生相同的结果:

  1. 第一个,我觉得比较简单,这样计算,

    (x, 1, n) - (y, n) => (x, y, n) => (x, y)

  2. 第二个,我相信它只是你发布的代码的一个简单版本,这样计算,

    (x, n, 1) - (1, y, n) => (x, n, y) => (x, y)

这里的关键是:对于像这样的pairwise差异,为了产生形状(x, y)的结果,您需要添加一个额外的维度并进行一些广播。

对于您的情况,xy 都是 batch_size。如果您问它们的含义,我会说“第一个batch_size 表示来自,第二个batch_size 表示diffs[0, ..., 1] 只是距离从批次中的第一个样品到批次中的第二个样品。”

【讨论】:

    【解决方案4】:

    最难理解的应该是

    diffs = tf.expand_dims(x, 3) - tf.expand_dims(tf.transpose(x, [1, 2, 0]), 0)
    

    如果我们修复第一个维度,事情就会很清楚,即(为了清楚起见,这里我使用 numpy 表示法并使用yz 来表示转换后的x

    diffs[k] = y[i, :, :, 1] - z[1, :, :, :]
    

    我们有y[i, m, n] = [x[i, m, n]]z[1, m, n, j]=x[j, m, n]。现在我们广播yz,我们将有y[i, m, n, j]=x[i, m, n] 用于任何jz[i, m, n, j]=x[j, m, n] 用于任何i。对于固定的i 和'j',如果我们从y 中减去z,我们等价地从x[j, m, n] 中减去x[i, m, n],这正好是(M_{i, b}-M_{j, b}在第 2 步中

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 2021-12-26
      • 2012-11-02
      相关资源
      最近更新 更多