tensorflow - 使用 Tensorflow 后端了解 Keras 中的 batch_dot()

标签 tensorflow keras matrix-multiplication

我试图理解这段代码(来自 here ),它使用两个张量之间的矩阵乘法实现点积注意。具体来说,来自 Keras 后端的 batch_dot() 函数用于两个具有可变第一维的张量之间。与指定第一维时相比,batch_dot() 在这种情况下的表现似乎有所不同。

MWE:

固定第一维,按预期工作

q = K.ones(shape=(36,8,24))
k = K.ones(shape=(36,8,24))
print(K.batch_dot(q,k,axes=[1,1]))

返回
Tensor("MatMul_8:0", shape=(?, 36, 24, 24), dtype=float32)

和,
print(K.batch_dot(q,k,axes=[2,2]))

返回
Tensor("MatMul_9:0", shape=(?, 36, 8, 8), dtype=float32)

但是,定义 q 和 k 如下:
q = Input(shape=(36,8,24))
k = Input(shape=(36,8,24))
print(q)
print(k)

(可变第一维)
Tensor("input_24:0", shape=(?, 36, 8, 24), dtype=float32)
Tensor("input_25:0", shape=(?, 36, 8, 24), dtype=float32)

batch_dot() 操作的输出维度出乎意料:
K.batch_dot(q,k,axes=[1,1])
<tf.Tensor 'MatMul_11:0' shape=(?, 36, 24, 24) dtype=float32>
K.batch_dot(q,k,axes=[2,2])
<tf.Tensor 'MatMul_12:0' shape=(?, 36, 24, 24) dtype=float32>

根据documentation , 对 axes 的参数指定在操作过程中删除的维度,但是我无法将此定义连接到上面的输出。第一个维度(值 ?)是否被计算为 axes 的参数?

最佳答案

Does the first dimension (with value ?) get counted for the arguments of axes?



是的,它被计算在内。

事实是 Input 中的第一个维度在上面的例子中,层是批量大小,而在 K.ones() 它不是。因此,输入的轴 [3, 3] 等于 K.ones() 中的轴 [2, 2] .在您的代码中,以下两个 batch_dot 是相等的:
q = tf.keras.layers.Input(shape=(36, 8, 24)) # shape =(?, 36,8,24)
k = tf.keras.layers.Input(shape=(36, 8, 24)) # shape =(?, 36,8,24)
print(tf.keras.backend.batch_dot(q, k, axes=[3, 3]))

q = tf.keras.backend.ones(shape=(36, 8, 24))
k = tf.keras.backend.ones(shape=(36, 8, 24))
print(tf.keras.backend.batch_dot(q, k, axes=[2, 2]))

请注意,在 K.ones() ,如果形状是符号的,我们不能返回一个变量,而是返回一个动态形状的张量。这是什么意思?请参阅以下示例以更好地理解:
a = tf.keras.layers.Input(shape=(30,))
c = tf.keras.backend.ones(shape=tf.shape(a))
print(c) # shape=(?, 30)
d = tf.keras.backend.ones(shape=(30, 40))
print(d) # shape=(30,40)

Output dimensions from batch_dot() operation is unexpected


K.batch_dot(q,k,axes=[1,1])
<tf.Tensor 'MatMul_11:0' shape=(?, 36, 24, 24) dtype=float32>
K.batch_dot(q,k,axes=[2,2])
<tf.Tensor 'MatMul_12:0' shape=(?, 36, 24, 24) dtype=float32>

为什么在轴不同的情况下会发生这种情况?

要回答这个问题,我们应该了解batch_dot的底层实现。 .如果输入张量的秩不是 2,那么我们的 batch_dot表现为 tf.matmul 输入张量之一是共轭转置的操作。结果,当我们的输入张量的等级为 3 并且我们将轴设置为 0 或 1 时,它们计算的内容相同,但是当将轴设置为 2 时,它计算的内容有所不同:
a = np.array([[[1, 2, 3],
               [3, 2, 1]]])  # rank 3

b = np.array([[[1, 3, 3],
               [2, 2, 0]]])  # rank 3

a = tf.constant(a, dtype=tf.float32)
b = tf.constant(b, dtype=tf.float32)

c = tf.matmul(a, b, adjoint_a=True, adjoint_b=False)  # when axes is [0,0] or [1,1]
d = tf.matmul(a, b, adjoint_a=False, adjoint_b=True)  # when axes is [2,2]
print(c.shape)  # shape=(1,3,3)
print(d.shape)  # shape=(1,2,2)

在您的示例中发生了同样的事情:
a = np.array([[[1, 2, 3],
               [3, 2, 1]]])

b = np.array([[[1, 3, 3],
               [2, 2, 0]]])

q = tf.placeholder(dtype=tf.float32, shape=(None, 2, 3))  
k = tf.placeholder(dtype=tf.float32, shape=(None, 2, 3))  
res1 = tf.keras.backend.batch_dot(q, k, axes=0)
res2 = tf.keras.backend.batch_dot(q, k, axes=1)
res3 = tf.keras.backend.batch_dot(q, k, axes=2)
with tf.Session() as sess:
    feed_dic = {q: a, k: b}
    print(sess.run(res1, feed_dict=feed_dic))
    print(20 * '-')
    print(sess.run(res2, feed_dict=feed_dic))
    print(20 * '-')
    print(sess.run(res3, feed_dict=feed_dic))

关于tensorflow - 使用 Tensorflow 后端了解 Keras 中的 batch_dot(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54057742/

相关文章:

python - 'tensorflow.python.framework.ops.EagerTensor' 对象没有属性 '_in_graph_mode'

deep-learning - Keras 和 GPU 使用

python - 如何计算非常大的 scipy 稀疏矩阵之间的点积

python - 为什么在 tensorflow 中使用多 GPU 时 GPU 内存使用情况有很大不同?

tensorflow - 无法创建cudnn句柄:CUDNN_STATUS_INTERNAL_ERROR

python - 无法正确定义 LSTM 的输入以建模多对一场景

python - Keras 中 CPU 和 GPU 的混合使用

python - 如何修复 "ModuleNotFoundError: No module named ' keras.layers.advanced_activations'“

c - 矩阵乘法控制

c - 分配乘法表的问题