1.标量(0D 张量)

仅包含一个数字的张量叫作标量scalar,也叫标量张量、零维张量、0D 张量)。在 Numpy
中,一个 float32 float64 的数字就是一个标量张量(或标量数组)。

2.向量

数字组成的数组叫作向量vector)或一维张量(1D 张量)。一维张量只有一个轴。下面是
一个 Numpy 向量。
x=np.array([12,3,6,14,7])

3.矩阵(2D 张量)

向量组成的数组叫作矩阵matrix)或二维张量(2D 张量)。矩阵有 2 个轴(通常叫作
)。你可以将矩阵直观地理解为数字组成的矩形网格。下面是一个 Numpy 矩阵。
 x = np.array([[5, 78, 2, 34, 0],
 [6, 79, 3, 35, 1],
 [7, 80, 4, 36, 2]])

4.3D 张量与更高维张量

将多个矩阵组合成一个新的数组,可以得到一个 3D 张量,你可以将其直观地理解为数字
组成的立方体。下面是一个 Numpy 3D 张量
x = np.array([[[5, 78, 2, 34, 0],
[6, 79, 3, 35, 1],
[7, 80, 4, 36, 2]],
[[5, 78, 2, 34, 0],
[6, 79, 3, 35, 1],
[7, 80, 4, 36, 2]],
[[5, 78, 2, 34, 0],
[6, 79, 3, 35, 1],
[7, 80, 4, 36, 2]]])
将多个 3D 张量组合成一个数组,可以创建一个 4D 张量,以此类推。深度学习处理的一般
0D 4D 的张量,但处理视频数据时可能会遇到 5D 张量。

5.关键属性

张量是由以下三个关键属性来定义的。
轴的个数(阶)例如,3D 张量有 3 个轴,矩阵有 2 个轴。这在 Numpy Python 库中
也叫张量的 ndim
形状:这是一个整数元组,表示张量沿每个轴的维度大小(元素个数)。例如,前面矩
阵示例的形状为 (3, 5)3D 张量示例的形状为 (3, 3, 5)。向量的形状只包含一个
元素,比如 (5,),而标量的形状为空,即 ()
 数据类型(在 Python 库中通常叫作 dtype)。这是张量中所包含数据的类型,例如,张
量的类型可以是 float32uint8float64 等。在极少数情况下,你可能会遇到字符
char)张量。注意,Numpy(以及大多数其他库)中不存在字符串张量,因为张量存
储在预先分配的连续内存段中,而字符串的长度是可变的,无法用这种方式存储。

6.张量运算

6.1逐元素运算
relu 运算和加法都是逐元素element-wise)的运算,即该运算独立地应用于张量中的每
个元素,也就是说,这些运算非常适合大规模并行实现。下列代码是对逐元素 relu 运算的简单实现。
def naive_relu(x):
     assert len(x.shape) == 2 
     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
对于加法采用同样的实现方法。
def naive_add(x, y): 
     assert len(x.shape) == 2 
     assert x.shape == y.shape
     x = x.copy() 
     for i in range(x.shape[0]):
         for j in range(x.shape[1]):
             x[i, j] += y[i, j]
     return x

6.2广播

广播包含 以下两步。
(1) 向较小的张量添加轴(叫作广播轴),使其 ndim 与较大的张量相同。
(2) 将较小的张量沿着新轴重复,使其形状与较大的张量相同。
来看一个具体的例子。假设 X 的形状是 (32, 10)y 的形状是 (10,)。首先,我们给 y
添加空的第一个轴,这样 y 的形状变为 (1, 10)。然后,我们将 y 沿着新轴重复 32 次,这样
得到的张量 Y 的形状为 (32, 10),并且 Y[i, :] == y for i in range(0, 32)。现在,
我们可以将 X Y 相加,因为它们的形状相同。
 def naive_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
6.3张量点积
点积运算,也叫张量积tensor product,不要与逐元素的乘积弄混),是最常见也最有用的
张量运算。与逐元素的运算不同,它将输入张量的元素合并在一起。
从数学的角度来看,点积运算做了什么?我们首先看一下两个向量 x y 的点积。其计算
过程如下:
 def naive_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
注意,两个向量之间的点积是一个标量,而且只有元素个数相同的向量之间才能做点积。

6.4张量变形

张量变形是指改变张量的行和列,以得到想要的形状。变形后的张量的元素总个数与初始
张量相同。简单的例子可以帮助我们理解张量变形。
import numpy as np
x = np.array([[ 0,1],
          [ 2,3],
          [ 4,5]])
print(x.shape)
x = x.reshape((6, 1))
print(x)

6.5张量运算的导数(梯度)

梯度gradient)是张量运算的导数。它是导数这一概念向多元函数导数的推广。多元函数
是以张量作为输入的函数。
随机梯度下降

 给定一个可微函数,理论上可以用解析法找到它的最小值:函数的最小值是导数为 0 的点, 因此你只需找到所有导数为 0 的点,然后计算函数在其中哪个点具有最小值。

将这一方法应用于神经网络,就是用解析法求出最小损失函数对应的所有权重值。

由于处理的是一个可微函数,你可以计算出它的梯度,从而有效地实
现第四步。沿着梯度的反方向更新权重,损失每次都会变小一点。
(1) 抽取训练样本 x 和对应目标 y 组成的数据批量。
(2) x 上运行网络,得到预测值 y_pred
(3) 计算网络在这批数据上的损失,用于衡量 y_pred y 之间的距离。
(4) 计算损失相对于网络参数的梯度[一次反向传播backward pass)]。
(5) 将参数沿着梯度的反方向移动一点,比如 W -= step * gradient,从而使这批数据
上的损失减小一点。
刚刚描述的方法叫作小批量随机梯度下降mini-batch stochastic gradient descent
又称为小批量 SGD)。

 

6.6链式求导:反向传播算法

在前面的算法中,我们假设函数是可微的,因此可以明确计算其导数。在实践中,神经网
络函数包含许多连接在一起的张量运算,每个运算都有简单的、已知的导数。例如,下面这个
网络 f 包含 3 个张量运算 ab c,还有 3 个权重矩阵 W1W2 W3
f(W1, W2, W3) = a(W1, b(W2, c(W3)))
根据微积分的知识,这种函数链可以利用下面这个恒等式进行求导,它称为链式法则chain
rule):(f(g(x)))' = f'(g(x)) * g'(x)。将链式法则应用于神经网络梯度值的计算,得
到的算法叫作反向传播backpropagation,有时也叫反式微分reverse-mode differentiation)。反
向传播从最终损失值开始,从最顶层反向作用至最底层,利用链式法则计算每个参数对损失值
的贡献大小。
Logo

一站式 AI 云服务平台

更多推荐