Python深度学习——5分钟快速学习张量运算
【摘要】 大家好,我是丁小杰。回到正题,上文我们简述什么是张量,今天就来看看张量的几种运算方法和特点。对于深度神经网络出现的所有变换,都可以简化为一些张量运算。前面的文章中我们通过叠加 Dense 层来构建网络。keras.layers.Dense(512, activation='relu')这个层可以理解为一个函数,输入一个 2D 张量,输出另一个 2D 张量。函数表示如下(其中 W:2D 张量,...
大家好,我是丁小杰。
回到正题,上文我们简述什么是张量,今天就来看看张量的几种运算方法和特点。
对于深度神经网络出现的所有变换,都可以简化为一些张量运算。
前面的文章中我们通过叠加 Dense 层来构建网络。
keras.layers.Dense(512, activation='relu')
这个层可以理解为一个函数,输入一个 2D 张量,输出另一个 2D 张量。函数表示如下(其中 W:2D 张量,b:向量)。
这里就有三个张量运算:
- 输入张量和张量 W 之间的点积(dot)
- 2D 张量与向量 b 之间的加法
- relu 运算。relu(x) 是 max(x, 0)
下面我们分别看看这些运算如何实现。
逐元素运算
上面的是三个运算都是逐元素运算,即该运算独立地应用于张量中的每个元素。我们先用 numpy 来实现relu运算和张量加法。
>>> import numpy as np
>>> x = np.array([[1, -2, 3],
[4, -5, 6]])
>>> y = np.array([[1, -2, 3],
[4, -5, 6]])
>>> z = x + y
>>> z
array([[ 2, -4, 6],
[ 8, -10, 12]])
>>> np.maximum(z, 0)
array([[ 2, 0, 6],
[ 8, 0, 12]])
我们可以自己简单实现一下上面的逐元素relu运算。
>>> def simple_relu(x):
x = x.copy()
for i in range(x.shape[0]):
for j in range(x.shape[1]):
x[i, j] = max(x[i, j], 0)
return x
>>> simple_relu(z)
array([[ 2, 0, 6],
[ 8, 0, 12]])
虽然效果看起来一样,速度确实天差地别,Numpy 内置函数都已经过优化,这些函数将大量运算交给 BLAS(基础线性代数子程序)实现。BLAS 是低层次的、高度并行的、高效的张量操作程序,通常用 Fortran 或C语言来实现。
张量点积 & 逐元素乘积
点积运算,也叫张量积,是最常见也最有用的张量运算。与逐元素的运算不同,它将输入张量的元素合并在一起。在 Numpy 中,使用 dot 来实现点积。
dot(向量,向量)
两个向量之间的点积是一个标量,而且只有元素个数相同的向量之间才能做点积。看个例子。
>>> import numpy as np
>>> np.dot([1, 2, 3], [4, 5, 6])
32
dot(矩阵,向量)
对一个向量 x 和一个矩阵 y 做点积,结果是一个向量,其中每个元素是 x 与 y 的每一列之间的点积。
>>> np.dot([1, 2], [[4, 5, 6],
[7, 8, 9]])
array([18, 21, 24])
注意:如果两个张量中有一个的 ndim 大于 1,那么 dot 运算就不再是对称的,也就是说,
dot(x, y) 不等于 dot(y, x)。
以上面的例子来说,如果要互换 x,y 的位置,那么向量的维度要与矩阵的第0维大小相同。
>>> np.dot([[4, 5, 6],
[7, 8, 9]], [1, 2, 3])
array([32, 50])
dot(矩阵,矩阵)
两个矩阵之间的点积是最常用的,对于两个矩阵 x 和 y,只有 x.shape[1] == y.shape[0]
时,才能够使用点积,结果是一个 (x.shape[0], y.shape[1]) 的矩阵,其元素为 x 的行与 y 的列之间的点积
>>> np.dot([[1, 2, 3],
[4, 5, 6]],
[[1, 2],
[3, 4],
[5, 6]])
array([[22, 28],
[49, 64]])
图解如下
高维向量点积
对于更高维的张量点积,规则与 2D 张量类似。
- (a, b, c, d) . (d,) -> (a, b, c)
- (a, b, c, d) . (d, e) -> (a, b, c, e)
广播机制
如果将两个形状不同的张量相加,较小的张量会被广播(broadcast),以匹配较大张量的形状。看个例子。
>>> x = np.array([[1, 2, 3],
[3, 4, 5]])
>>> y = np.array([[1],
[3]])
>>> x + y
array([[2, 3, 4],
[6, 7, 8]])
最后的结果返回一个形状为(2,3)的矩阵。
张量变形(reshape)
张量变形是指改变张量的行和列,以得到想要的形状。但元素的个数不会改变。看个例子。
>>> x = np.array([[1, 2, 3],
[4, 5, 6]])
>>> x
array([[1, 2, 3],
[4, 5, 6]])
>>> x.shape
(2, 3)
>>> y = x.reshape(3, 2)
>>> y
array([[1, 2],
[3, 4],
[5, 6]])
>>> y.shape
(3, 2)
>>> z = x.reshape(6, 1)
>>> z
array([[1],
[2],
[3],
[4],
[5],
[6]])
>>> z.shape
(6, 1)
矩阵转置
转置也是张量变形的一种。对矩阵做转置是指将行和列互换, 使 x[i, :] 变为 x[:, i]。
>>> x = np.array([[1, 2, 3],
[4, 5, 6]])
>>> x.shape
(2, 3)
>>> y = np.transpose(x)
>>> y.shape
(3, 2)
本文简述了一下,几种张量运算的用法,还有很多其他用法没有涉及到,有需要的可以自行翻阅相关资料进行学习。
内容参考
《Python深度学习》 [美] 弗朗索瓦·肖莱/著 张亮/译
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
作者其他文章
评论(0)