当前位置:网站首页>3.张量运算
3.张量运算
2022-08-03 04:05:00 【好名字能更容易让朋友记住】
张量运算
深度神经网络学到的所有变换也都可以简化为数值数据张量上的一些张量运算(tensor operation)
对于叠加Dense层来构建网络。Keras层的示例如下所示。
keras.layers.Dense(512, activation=‘relu’)
这个层可以理解为一个函数,输入一个2D张量,返回另一个2D张量,即输入张量的新表示。具体而言,如以下这个函数表示
output = relu(dot(W, input) + b)
其中W是一个2D张量,b是一个向量,二者都是该层的属性。拆开来看,这里有三个张量运算:
- 输入张量和张量W之间的点积运算(dot)
- 得到的2D张量与向量b之间的加法运算(+)
- 最后的relu运算。relu(x)是max(x,0)
逐元素运算
relu 运算和加分都是逐元素(element-wise)的运算,即运算独立地应用于张量中的每个元素,也就是说,这些运算非常适合大规模并行实现(向量化实现)
以下代码是对逐元素 relu 运算的简单实现
def navie_relu(x): assert len(x.shape) == 2 # assert 断言 以上语句的意思为如果 len(x.shape)==2即表示True,则正常运行,反之会报错。 x = x.copy() # 避免覆盖输入张量 for i in range(x.shape[0]): for j in range(x.shape[1]): x[i, j] = max(x[o, j], 0) return x
对于加法采用同样的实现方法。
def navie_add(x, y): assert len(x.shape) == 2 assert x.shape == y.shape # 保证 x 和 y 是Numpy的2D张量 x = x.copy() for i in range(x.shape[0]): for j in range(x.shape[1]): x[i, j] += y[i, j] return
在Numpy中可以直接进行下列逐元素运算,速度非常快
import numpy as np # 逐元素相加 z = x + y # 逐元素的relu z = np.maxinum(z, 0.)
广播
对于以上的 navie_add 的简单实现仅支持两个形状相同的2D张量相加。如果将两个形状不同的张量相加。较小的张量会被广播,以匹配较大张量的形状。广播包括以下两步:
- 将较小的张量添加轴(叫做广播轴),使其ndim与较大的张量相同。
- 将较小的张量沿着新轴重复,使其形状与较大的张量相同。
举例:
假设X的形状是(32,10),y的形状是(10,)。首先,我们给y添加一个空的第一个轴,这样y的形状变为(1,10)。然后,我们将y沿着新轴重复32次,这样得到张量Y的形状为(32,10),并且Y[i, :] == y for i in range(0,32)。此时二者可以相加。def navie_add_matrix_and_vector(x, y): assert len(x.shape) == 2 assert len(y.shape) == 1 assert x.shape[1] == y.shape[0] x = x.copy() for i in range(x.shape[0]): for j in range(x.shape[1]): x[i, j] += y[j] return x
如果一个张量的形状是(a,b,… n,n+1, … ,m),另一个张量为(n,n+1,… m),那么你可以利用广播对他们做两个张量之间的逐元素运算。广播操作会自动应用于a到n-1的轴。
# 利用广播将逐元素的maximum运算应用于两个形状不同的张量 import numpy as np # 形状为(64,3,32,10)的随机张量、 x = np.random.random((64, 3, 32, 10)) # 形状为(64,10)的随机张量。 y = np.random.random((32, 10)) # 输出z的形状是(64,3,32,10),与x相同。 z = np.maximum(x, y)
张量点积
点积运算,也叫做张量积(tensor product,不要与逐元素的乘积弄混)
在Numpy、Keras、Theano和TensorFlow中,都是用 * 实现逐元素乘积。TensorFlow中的点积使用了不同的语法,但在Numpy和Keras中,都是用标准的dot运算符来实现点积。
import numpy as np z = np.dot(x, y) # 数学符号中的点( . )表示点击运算。 z=x.y
从数学的角度来看,两个向量 x 和 y 的点积。其运算结果如下:
def navie_vector_dot(x, y): # 表示二者为向量 assert len(x.shape) == 1 assert len(y.shape) == 1 # 表示长度相同 assert x.shape[0] == y.shape[0] z = 0. for i in range(x.shape[0]): z += x[i] * y[i] # 返回值为一个标量 return z
矩阵x和一个向量y做点积:
import numpy as np def naive_matrix_vector_dot(x, y): # x 是一个Numpy矩阵 # y 是一个Numpy向量 assert len(x.shape) == 2 assert len(y.shape) == 1 # x的第1维和y的第0维大小必须相同 assert x.shape[1] == y.shape[0] z = np.zeros(x.shape[0]) for i in range(x.shape[0]): for j in range(x.shape[1]): z[i] += x[i, j] * y[j] return z
举例:
import numpy as np x = np.array([[1,2,3],[4,5,6]]) y = np.array([1,2,3]) z = navie_matrix_vector_dot(x,y) z # z = array([14., 32.]) # 即 z = [1×1 + 2×2 + 3×3 , 4×1 + 5×2 + 6×3]
通过以上两个函数进行结合
def mavie_matrix_vector_dot(x,y): z = np.zeros(x.shape[0]) for i in range(x.shape[0]): z[i] = naive_vector_dot(x[i, :], y) # x[i, :]表示x的第i个轴的所有元素 return z
进行推广,若两个矩阵进行点积,若矩阵x和y,当且仅当 x.shape[1] == y.shape[0] 时,二者可以进行点积。得到的结果为一个形状为**(x.shape[0],y.shape[1])**的矩阵。
def navie_matrix_dot(x, y): assert len(x.shape) == 2 assert len(y.shape) == 2 # x的第1维与y的第0维大小必须相同 # 即x的列数与y的行数相等 assert x.shape[1] == y.shape[0] z = np.zeros((x.shape[0], y.shape[1])) for i in range(x.shape[0]): for j in range(y.shape[1]): # 遍历x的所有行 row_x = x[i, :] # 遍历y的所有列 column_y = y[:, j] # x的行依次与y的列相乘 z[i, j] = navie_vector_dot(row_x, column_y) return z
综上所述:
两个矩阵相乘需要的要求为矩阵x的列于矩阵y的行相等,再将矩阵x的行依次与矩阵y的列想称再相加。得到一个以矩阵x的行为行,矩阵y的列为列的新矩阵。 一般来说,可以对更高维的张量做点积,只要其形状匹配遵循与前面2D张量相同的原则:
(a, b , c ,d) . (d,) -> (a, b, c)
(a, b , c ,d) . (d, e) -> (a, b, c, e)
以此类推。
张量变形
改变张量的行和列,以得到想要的形状,变形后的张量的元素总个数与初始张量相同。
举例:
x = np.array([[0., 1.], [2., 3.], [4., 5.]]) print(x.shape) # (3, 2) x = reshape((6, 1)) x # array([[ 0.], # 1.], # 2.], # 3.], # 4.], # 5.]]) x = x.reshape((2, 3)) x # array([[ 0., 1., 2.],[ 3., 4., 5.]])
最经常遇到的一种特殊的张量变形是转置。对矩阵做转置是指将行和列互换,使x[i, :]变为x[:, i]。
x = np.zeros((300,20)) x = np.transpose(x) print(x.shape)
边栏推荐
- 高等代数_证明_不同特征值的特征向量线性无关
- "Obs" start pushing flow failure: the Output. The StartStreamFailed call process
- 汇编书摘抄
- vscode access denied to unins000.exe
- 我将GuiLite移植到了STM32F4开发板上
- (2022牛客多校五)G-KFC Crazy Thursday(二分+哈希)
- 解析,强势供应商的管理方法
- easyswoole的mysqli 事务怎么写
- 2022 Henan Mengxin League Game (4): Zhengzhou University of Light Industry E - Sleep Well
- ESP8266-Arduino编程实例-LED点阵驱动(基于Max7219)
猜你喜欢
随机推荐
ClickHouse uninstall and reinstall
vscode access denied to unins000.exe
基于flowable的upp(统一流程平台)运行性能优化(2)
第三方支付--分账对接
TCP相关面试常问
第3周 用1层隐藏层的神经网络分类二维数据
2022中国五金制品行业发展前景分析
MySQL【约束】
StarRocks 7 月社区动态
工程制图第九章作业
Kotlin multiplication, how do I multiply smaller and smaller?
stdio.h(本机代码)
How many moments have you experienced the collapse of electronic engineers?
SkiaSharp 之 WPF 自绘 五环弹动球(案例版)
Browser listens for tab closing
2022河南萌新联赛第(四)场:郑州轻工业大学 E - 睡大觉
瑞鹄转债上市价格预测
寄存器(内存访问)
The flink sql task is changed, and after adding several fields to the sql, an error occurs when restoring from the previously saved savepoint.
2022 Henan Mengxin League Game (4): Zhengzhou University of Light Industry E - Sleep Well