线性代数的实现
就像向量是标量的推广一样,矩阵是向量的推广,我们可以构建具有更多轴的数据结构。
对称矩阵的转置是他本身
B = A.clone()通过分配新内存,将A的一个副本给B
计算操作
- 矩阵的按元素乘法被称为哈达玛积
张量的求和
- 如果是一个标量和一个张量相加,就是张量所有元素加上标量
- 无论是任意形状张量的元素和
x.sum()结果都是标量
axis用来为超过一维的数组定义属性。0表示最高维,1表示次高维,2表示再低一维
- 对于axis的补充说明:
从图上代码可以看出来,当axis=0时是上下两个维度同一位置的元素相加;而axis=1时是两个维度中的元素做纵向相加;axis=2时是两个维度的元素做横向相加
求均值
- 求均值
A.mean()或A.sum() / A.numel()。numel()函数可以获取张量元素个数 - 按某个轴求平均值:
A.mean(axis=0)或A.sum(axis=0) / A.shape[0] - 计算总和或均值是保持轴数不变:
sum_A = A.sum(axis=1,keepdims=True)如果按照某一维度求和,那个维度就会被丢掉,如果是三维数组求和就会变成二维数组 - 通过广播将A除以sum_A:
A / sum_A cumsum()函数可以将输入的数组或序列按元素顺序进行累加,并返回一个新的数组,其中新数组的每个元素都是原数组中前面所有元素的和。新数组b的第一个元素是原数组的第一个元素,第二个元素是原数组的前两个元素的和,以此类推。
乘积
-
点积是相同位置按元素乘积的和。
torch.dot(x,y)x,y是两个向量- 也可以用元素乘法然后进行求和来表示两个向量点积
torch.sum(x * y)
- 也可以用元素乘法然后进行求和来表示两个向量点积
-
矩阵向量积:
torch.mv(A, x)矩阵和向量的积是一个列向量 -
矩阵相乘:
torch.mm(A, B)
范数
- L2范数是向量元素平方和的平方根:
torch.norm(u) - L1范数是向量元素的绝对值之和:
torch.abs(u).sum()或者torch.norm(u,1)
norm要求向量必须是浮点数
- 矩阵的范数是矩阵元素的平方和的平方根:
torch.norm(A)
矩阵计算
- 标量的导数拓展到向量就是梯度。梯度指向变化值最大的地方。
- 标量对向量求导:
3.矩阵求导
- 拓展到矩阵
矩阵求导
这里学习了: 矩阵求导的本质与分子布局、分母布局的本质(矩阵求导——本质篇): zhuanlan.zhihu.com/p/263777564
函数与变元
这里考虑一个函数function(input),针对function和input类型我们可以将其划分成不同种类
- function作为标量,变元分为三种:标量、向量、矩阵
- function作为向量,f是由若干个f组成的一个向量,变元同样分为三种
- function作为向量,变元也是向量的例子:
- 先将y拆解成列向量,和每个x求导,是个行向量,最后展开变成矩阵
- function作为矩阵,F是由若干个f组成的矩阵
矩阵求导的本质
在高数中,对于多元函数求导,一般是分别对每个变元求偏导。而矩阵求导就是将求出来的结果写成列向量的形式。所以如果一个 function有m个f,变元中有n个元素,那么,每个f对变元的每个元素逐个求编导,就会产生m乘n个结果
矩阵求导结果的布局
- 分子布局:分子是列向量,分母是行向量。
- 本质是,分子是标量、列向量、矩阵向量化后的列向量;分母是标量、列向量转置后的行向量、矩阵的转置矩阵、矩阵向量化后的列向量转置后的行向量。
- 分母布局:分母是列向量,分子是行向量。
- 本质是,分子是标量、列向量转置后的行向量、矩阵向量化后的列向量转置后的行向量;分母是标量、列向量、矩阵自己、矩阵向量化后的列向量。
总结:谁转置了,就是另一方的布局。分子转置了,就是分母布局;分母转置了,就是分子布局。
矩阵求导公式的数学推导(矩阵求导——基础篇): zhuanlan.zhihu.com/p/273729929
矩阵求导公式的数学推导(矩阵求导——进阶篇): zhuanlan.zhihu.com/p/288541909
自动求导
这里的<x,w>是标量,标量对向量的求导,向量取转置。
自动求导
- 显示构造
from mxnet import sym
a = sym.var()
b = sym.var()
c = 2 * a + b
需要读取之前的结果,来计算
自动求导实现
- 假设对函数y=2x^Tx关于列向量x求导
import torch
x = torch.arange(4.0)
x
- 在计算y关于x梯度之前,需要一个地方来存储梯度
x.requires_grad_(True) # 等价于 `x = torch.arange(4.0, requires_grad=True)`
x.grad # 默认值是None
设置一个tensor的 requires_grad为True 会保存该Tensor是否记录所有操作用于计算梯度 x.grad查看梯度值
- 现在计算y
dot():返回内积
grad_fn用来记录变量是怎么来的,方便计算梯度
- 通过调用反向传播函数来自动计算y关于x每个分量的梯度,最后验证是否正确
grad:当执行完了backward()之后,通过x.grad查看x的梯度值
backward函数实际上是通过传递参数来计算梯度,它通过backward图一直到每个叶节点,每个叶节点都可以从调用的根张量追溯到叶节点。然后将计算出的梯度存储在每个叶节点的.gard中
- 现在计算x的另一个函数
_表示重写内容,zero_表示将所有梯度清零
sum()函数求导全1,相当于对x1+x2+...+xn求偏导
-
深度学习中,我们的目的不是计算微分矩阵,而是批量中每个样 本单独计算的偏导数之和。
-
将某些计算移动到记录的计算图之外
detach()将y作为一个常数u
- 即使构建函数的计算图需要通过python控制流,我们仍然可以计算得到的变量的梯度
torch.randn(size=(), requires_grad=True)生成随机数,size随机