线代这考研必考,没啥多说的,直接看torch的操作
import torch
a = torch.tensor(1.0)
b = torch.arange(12.0)
c = b.reshape([3, 4])
print(c.T) # 矩阵转置操作
d = c.clone() # clone函数 内容相同 内存不同
y = torch.tensor([0, 1, 2, 3])
print(y * y)
c.sum() # 求和
c.sum(axis=1) # 按列求和,丢失维度变成行向量
x = c.sum(axis=1, keepdims=True) # 求和时候不丢失维度,此处按列求和,结果也是列向量
print(c / x) # 利用广播机制求值
# 向量点积||数量积
a = torch.tensor([0, 1, 2, 3])
b = torch.tensor([1, 1, 2, 9])
print(torch.dot(a, b)) # 对应元素相乘再相加
# 矩阵乘向量
a = torch.arange(20).reshape([4, 5]) # 4 * 5的矩阵
b = torch.tensor([1, 2, 3, 4, 5]) # 其实应该是列向量,此处先定义为1 * 5的行向量
print(a.shape, b.shape)
print(torch.mv(a, b)) # 函数内自动转置b 卡了半天在这 所以b定义为行向量即可 数学意义上是与5 * 1的列向量相乘
# 矩阵乘矩阵
a = torch.arange(20).reshape([4, 5]) # 4 * 5
b = torch.arange(20).reshape([5, 4]) # 5 * 4
print(torch.mm(a, b)) # 4 * 4
print(torch.mm(b, a)) # 5 * 5
# L2范数
u = torch.tensor([1.0, -1.0])
print(torch.norm(u))
# L1范数 一般受异常值影响较小 绝对值求和
print(torch.abs(u).sum())
# F范数 矩阵元素的平方和的平方根 矩阵拉成向量然后求L2范数
print(torch.norm(torch.arange(12, dtype=torch.float32).reshape([2, 6])))
基本部分仅限于求导的一些知识,也没啥可说的
亚导数:将导数拓展到不可微的函数
梯度:连接一个多元函数的所有变量的偏导数,得到函数的梯度向量(这里教材的这句话要比视频中好理解的多)
以下举例说明
有 y = x 1 2 x_1^2 x12 + 2 x 2 2 2x_2^2 2x22
y的导数 [ 2 x 1 2x_1 2x1, 4 x 2 4x_2 4x2] 的行向量
公式 | 结果 |
---|---|
∂ y / ∂ X \partial y / \partial X ∂y/∂X | X为列向量 结果为行向量 |
∂ Y / ∂ x \partial Y / \partial x ∂Y/∂x | Y为行向量 结果为行向量 |
∂ Y / ∂ X \partial Y / \partial X ∂Y/∂X | Y、X为列向量 结果为矩阵 |
梯度指向值变化最大的方向
其余知识基本在高数课本上都有,这里不做赘述,梯度这里可以后续慢慢理解,不必过分纠结。
神经网络中手动求导基本不可能做到,因此需要自动求导,自动求导其实是在计算一个函数在指定值的导数
顺序计算链式法则 → \rightarrow → 正向累计
逆序计算链式法则 → \rightarrow → 反向传播
看代码
import torch
x = torch.arange(12.0) # x = torch.arange(12, dtype=torch.float32)
print(x)
print(x.shape)
# 计算梯度需要告诉torch开启存储
x.requires_grad_(True)
# 或者在定义的时候就直接开启
x = torch.arange(4.0, requires_grad=True)
print(x.grad) # 默认梯度为None
y = 2 * torch.dot(x, x)
y.backward() # 求导
print(x.grad) # 查看导数
print(x.grad == 4 * x) # 查看是否一致
x.grad_zero_() # 此操作清空之前的梯度存储,填充0进去
# 设计一个新的函数
y = x.sum()
y.backward()
print(x.grad)
print(x.grad == 1) # 清空之后此处为True
'''
如果没有`x.grad_zero_()`
获得的结果为 [1, 5, 9, 13]
来源为之前的 "4 * x + 1" [0, 4, 8, 12] + [1, 1, 1, 1]
'''
x.grad.zero_()
y = x * x # 对应元素相乘,哈达玛积
y.sum().backward() # 绝大部分情况标量求导,后续课程中展开探讨
print(x.grad)
print(2 * x == x.grad)
x.grad.zero_()
y = x * x
u = y.detach() # 将y作为一个常数,值为x*x,不再视作x的函数
z = u * x # z为x的函数
z.sum().backward()
print(x.grad)
print(x.grad == u)
概率论基本知识,不赘述
个人目前(2022.09.26)浅薄的认知机器学习 == 统计学习