本文代码运行环境:
- windows10
- python3.6
- jupyter notebook
- tensorflow 1.x
- keras 2.x
问题描述
keras的Dense层的输入通常是一个二维的矩阵(batch_size, n_input), 但其实, 你的输入的秩可以是大于2的, 比如下面的代码是正确的:
1 | from keras import layers |
而权重的形状是这样的:
1 | dense.kernel |
我们可以看到, 输出output
的形状是(batch_size, 2, 4)
, 为什么会是这样的? 我查阅了keras中的文档, 文档中说:if the input to the layer has a rank greater than 2, then it is flattened prior to the initial dot product with kernel
, 但是, 实际情况不是这样的, 如果被flatten以后, 输出应该是这样的:
1 | input1 = layers.Input((2,3)) |
而权重的形状是这样的:
1 | dense.kernel |
Dense的算法就是dot
很显然, 文档说的有问题, 代码并不是这样的运行的。所以我查阅了Keras的源码, 我发现Dense前向传播的计算方法是在这里:
1 | def call(self, inputs): |
所以, 我们要看一下keras中dot
的行为:
1 | from keras import backend as K |
1 | import tensorflow as tf |
1 | import numpy as np |
x: [[[3 3 7]
[2 4 7]]
[[2 1 2]
[1 1 4]]]
y: [[3 2 1 1]
[1 1 2 4]
[4 3 1 4]]
xy: [[[40. 30. 16. 43.]
[38. 29. 17. 46.]]
[[15. 11. 6. 14.]
[20. 15. 7. 21.]]]
这个结果和我们直接用np.dot
的方法结果是一样的。
1 | np.dot(x_data, y_data) |
array([[[40, 30, 16, 43],
[38, 29, 17, 46]],
[[15, 11, 6, 14],
[20, 15, 7, 21]]])
1 | np.dot(x_data, y_data[:, 1]) |
array([[30, 29],
[11, 15]])
总结
其实两个tensor之间的点乘大家应该懂了, keras官方文档有问题导致对它的理解又产生了疑惑。如果三维的tensor不容易理解的话, 可以去掉batch_size这个维度来看:
1 |
|
正常情况下, x只是个向量:
array([28, 26, 16])
1 | print('特殊情况下, x只是个矩阵:') |
特殊情况下, x只是个矩阵:
array([[28, 26, 16],
[40, 36, 23]])
一句话总结的话, Dense的输入为一个矩阵的时候, 相当于它的每一个行向量分别进入Dense层进行计算, 然后把计算得到的向量拼接成矩阵。有问题来我网站提问:mlln.cn , 转载请注明出处。
注意
本文由jupyter notebook转换而来, 您可以在这里下载notebook
统计咨询请加QQ 2726725926, 微信 mllncn, SPSS统计咨询是收费的
微博上@mlln-cn可以向我免费题问
请记住我的网址: mlln.cn 或者 jupyter.cn