深度学习-神经网络的数学基础
1.标量(0D 张量)仅包含一个数字的张量叫作标量(scalar,也叫标量张量、零维张量、0D 张量)。在 Numpy中,一个 float32 或 float64 的数字就是一个标量张量(或标量数组)。2.向量数字组成的数组叫作向量(vector)或一维张量(1D 张量)。一维张量只有一个轴。下面是一个 Numpy 向量。x=np.array([12,3,6,14,7])3.矩阵(2D 张量)向量
·
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)。这是张量中所包含数据的类型,例如,张
量的类型可以是 float32、uint8、float64 等。在极少数情况下,你可能会遇到字符
(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 个张量运算 a、b 和 c,还有 3 个权重矩阵 W1、W2 和 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)。反
向传播从最终损失值开始,从最顶层反向作用至最底层,利用链式法则计算每个参数对损失值
的贡献大小。
更多推荐




所有评论(0)