【问题标题】:Optimizing Tensorflow for many small matrix-vector multiplications针对许多小型矩阵向量乘法优化 Tensorflow
【发布时间】:2021-01-27 20:51:56
【问题描述】:

要构建胶囊网络训练脚本,我需要计算许多小的矩​​阵向量乘法。 每个权重矩阵的大小最多为 20 x 20。
权重矩阵数量超过900个。

我很好奇tf.matmultf.linalg.matvec 是最好的选择。 谁能给我一个优化训练脚本的提示?

【问题讨论】:

  • 您能否提供有关您要执行的操作的更多信息?这些乘法是否相互独立?它们是连续的吗? (每个都取决于前一个的结果)。你用的是什么算法?你能概述一下你的整个算法吗?
  • 算法与arxiv.org/pdf/1710.09829v2.pdf中的过程1非常相似。具体操作为u_hat_ij = W_ij * ui。每个 u_hat_ij 都是相互独立的。
  • 如果我理解正确,我认为这只是广播的元素乘法?如果您的矩阵在 3D 张量 w 中,形状为 (900, 20, 20),向量在 2D 张量 u 中,形状为 (900, 20),我认为您只需要 u_hat = w * tf.expand_dims(u, axis=2)(会给您一个形状为 3D 的张量(900, 20, 20))。
  • 这正是我对@jdehesa 的想法!你应该把它写成答案

标签: tensorflow matrix-multiplication


【解决方案1】:

编辑:

查看您所指的notebook,您似乎有以下参数:

batch_size = 50
caps1_n_caps = 1152
caps1_n_dims = 8
caps2_n_caps = 10
caps2_n_dims = 16

然后你有一个张量w,形状为(caps1_n_caps, caps2_n_caps, caps2_n_dims, caps1_n_dims)(在笔记本中,它有一个初始尺寸,大小为1,我正在跳过)和另一个张量caps1_output,形状为(batch_size, caps1_n_caps, caps1_n_dims)。您需要将它们组合起来以生成具有形状(batch_size, caps1_n_caps, caps1_n_dims, caps2_n_dims)caps2_predicted

在笔记本中,他们将张量平铺以便使用tf.linalg.matmul 对其进行操作,但实际上您可以仅使用tf.einsum 来计算相同的结果而无需任何平铺:

import tensorflow as tf

batch_size = 50
caps1_n_caps = 1152
caps1_n_dims = 8
caps2_n_caps = 10
caps2_n_dims = 16
w = tf.zeros((caps1_n_caps, caps2_n_caps, caps2_n_dims, caps1_n_dims), dtype=tf.float32)
caps1_output = tf.zeros((batch_size, caps1_n_caps, caps1_n_dims), dtype=tf.float32)
caps2_predicted = tf.einsum('ijkl,bil->bilk', w, caps1_output)
print(caps2_predicted.shape)
# (50, 1152, 8, 16)

我不确定我是否完全理解了你想要什么,但你说你想要计算类似的东西:

ûij = Wij × ui

对于几个矩阵W和向量u的集合。假设您有 900 个矩阵和向量,矩阵大小为 20×20,向量大小为 20,您可以将它们表示为两个张量,ws,形状为(900, 20, 20),和us,形状为(900, 20)。如果你这样做,你的结果us_hat,形状为(900, 20, 20),将被简单地计算为:

us_hat = ws * tf.expand_dims(us, axis=-1)

【讨论】:

  • 很抱歉让您感到困惑。结果 u_hat 的形状为 (900, 20, 1) 或 (900, 20) 。这就是为什么我不能使用元素乘法的原因。我现在指的教程是“github.com/ageron/handson-ml/blob/master/extra_capsnets.ipynb”。 ln[24].
  • matmul(wgt: [180 30 8 8], u:[180 30 8 1]) -> u_hat: [180 30 8 1]。 (我删除了批次维度)
  • 详细的解释给我留下了深刻的印象。非常感谢。我没有故意使用 einsum,因为我预计 einsum 会自动使用 tf.tile 和 tf.matmul。我确认它有效。还有一个小问题。 einsum 和 tiling & matmul 组合之间存在非常小的差异。差距约为 1e-06。这是正常现象吗?
  • 使用 einsum 的实现也需要更小的内存。
  • @KyungminLee 关于结果的差异,这取决于,float32 大约有七个有效数字,所以如果你的值的范围在单位或十位或更大的范围内,那么它是正常的看到那些不精确。如果值在 10^-4 的范围内,那么这些误差相对而言会大得多,这不应该发生。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-11
  • 2018-11-06
  • 1970-01-01
  • 1970-01-01
  • 2019-01-03
  • 1970-01-01
相关资源
最近更新 更多