赞
踩
在读《Python深度学习》这本书的时候,学习到张量点积这一块。二维以内的张量(向量和矩阵)的点积完全和矩阵乘法相同,因此理解起来没什么困难。但是当张量维度更高的时候呢?原文是这么说的:
- 更一般地说,你可以对更高维的张量做点积,只要其形状匹配遵循与前面2D张量相同的原则:
- (a,b,c,d) . (d,) -> (a,b,c)
- (a,b,c,d) . (d,e) -> (a,b,c,e)
那么,当被点积的张量维度高于二维呢?
- (a,b,c,d) . (e,f,g,h) 点积运算合法的关键:d = g, 左侧张量的最后一个维度与
- 右侧张量的倒数第二个维度相等。
- (a,b,c,d) . (e,f,g,h) -> (a,b,c,e,f,h)
我们可以使用python生成我们想要的特定维度的随机张量,以此来进行测试:
- >>> a = np.random.random((3,4,7,5))
- >>> b = np.random.random((2,6,5,8))
- >>> c = np.dot(a,b)
- >>> np.shape(c)
- (3, 4, 7, 2, 6, 8)
- >>> a = np.random.random((4,7,5))
- >>> b = np.random.random((2,6,8,5,3))
- >>> c = np.dot(a,b)
- >>> np.shape(c)
- (4, 7, 2, 6, 8, 3)
- >>> b = np.random.random((2,6,5,4,3))
- >>> c = np.dot(a,b)
- Traceback (most recent call last):
- File "<pyshell#23>", line 1, in <module>
- c = np.dot(a,b)
- File "<__array_function__ internals>", line 5, in dot
- ValueError: shapes (4,7,5) and (2,6,5,4,3) not aligned:
- 5 (dim 2) != 4 (dim 3)
可以看到,上面代码在a和b两个张量的维度不符合点积条件时,给出了错误信息,说a的最后一个轴(dim, 维度)与b的倒数第二个轴不匹配。
以(2,3) . (4,3,5) -> (2,4,5) 为例。直观上看,因为我更熟悉矩阵乘法,而且也习以为常地将(4,3,5)张量看成是4个3×5矩阵组合在一起的张量,所以会认为(2,3).(4,3,5) 最后的结果应该是(4,2,5),但实际上,这样看在某种程度上是正确的,但不完全正确。不完全正确是说,虽然以这种思路得到的数据是相同的,但是数据组织的方式完全不同,也就是说,张量到底是(4,2,5)维度还是(2,4,5)维度,这是有很大的差别的。
对于三维的张量来说,可以把它直观理解为是一个长方体,这样,就可以理解我为什么说在某种程度上是正确的:把长方体翻转一下,不就从(2,4,5)变成(4,2,5)了吗?
下面的代码是c = dot(a,b)运算的结果,按照我更熟悉的思路,a与b相乘得到的应该是2×5的矩阵,结果应该是4个2×5矩阵组成的张量。但是,结果告诉我们,c是2个4×5矩阵组成的张量。
- >>> a
- array([[1, 2, 3],
- [4, 5, 6]])
- >>> b
- array([[[1, 2, 3, 4, 5],
- [2, 3, 4, 5, 1],
- [3, 4, 5, 1, 2]],
-
- [[1, 2, 3, 4, 5],
- [3, 4, 5, 1, 2],
- [3, 4, 5, 1, 2]],
-
- [[1, 2, 3, 4, 5],
- [2, 3, 4, 5, 1],
- [4, 5, 1, 2, 3]],
-
- [[1, 2, 3, 4, 5],
- [2, 3, 1, 4, 5],
- [3, 5, 1, 4, 2]]])
- >>> c
- array([[[14, 20, 26, 17, 13],
- [16, 22, 28, 9, 15],
- [17, 23, 14, 20, 16],
- [14, 23, 8, 24, 21]],
-
- [[32, 47, 62, 47, 37],
- [37, 52, 67, 27, 42],
- [38, 53, 38, 53, 43],
- [32, 53, 23, 60, 57]]])
我们把c的两个矩阵的第一行取出来,组成一个新的2×5矩阵,不难发现,这个矩阵就是a与b张量的第一个矩阵的点积。a与b张量内的4个矩阵分别点积,组成了最后c中(2,4,5)的4这个维度。
- p = array([[1, 2, 3],[4, 5, 6]])
- q = array([[1, 2, 3, 4, 5],[2, 3, 4, 5, 1],[3, 4, 5, 1, 2]])
- np.dot(p,q) = ([[14, 20, 26, 17, 13],[32, 47, 62, 47, 37]])
至于为什么张量点积的规则是这样,只能说按规范来吧...
完全抛弃矩阵的概念,把张量点积全部归纳到向量点积去思考。两个拥有相同维度的向量(注意向量的维度是指向量的长度,作为向量作为张量的维度是1)的点积就是一个确定的标量,这也是张量点积中,两个相同的维度同时消失的根本原因。
可以把(e,f,d,h)当成是拥有e*f*h个d×1列向量的张量,同理(a,b,c,d)是拥有a*b*c个1×d行向量的张量,于是,张量的点积就可以看成是:1×d行向量与e*f*h个d×1列向量分别点积,得到e*f*h个标量,也即e个f×h矩阵。然后,由于总共有a*b*c个1×d行向量参与点积,所以,最后得到的结果是a*b*c*e个f×h矩阵,也就是 (a,b,c,e,f,h) 维度的张量。
这就是我对(a,b,c,d) . (e,f,d,h) -> (a,b,c,e,f,h) 的理解。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。