动手学深度学习v2笔记-Day1-线代高数概率

动手学深度学习v2

Day 1


0x00 线性代数

线代这考研必考,没啥多说的,直接看torch的操作

import torch
  • 标量a、向量b、矩阵c
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])))

0x01 微积分(矩阵计算)

基本部分仅限于求导的一些知识,也没啥可说的

亚导数:将导数拓展到不可微的函数
梯度:连接一个多元函数的所有变量的偏导数,得到函数的梯度向量(这里教材的这句话要比视频中好理解的多)
以下举例说明
有 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为列向量 结果为矩阵

梯度指向值变化最大的方向
其余知识基本在高数课本上都有,这里不做赘述,梯度这里可以后续慢慢理解,不必过分纠结。

0x02 自动微分

神经网络中手动求导基本不可能做到,因此需要自动求导,自动求导其实是在计算一个函数在指定值的导数

  • 计算图
  1. 系统会对于我们的模型自动构建一个叫做计算图的东西,它将计算表示成一个无环图,实际上表示的是链式求导过程
  2. 两种构造方法,显式&隐式
  • 反向传播

动手学深度学习v2笔记-Day1-线代高数概率_第1张图片

顺序计算链式法则 → \rightarrow 正向累计
逆序计算链式法则 → \rightarrow 反向传播

看代码

  • 自动求导 requires_grad_() || requires_grad=True
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
  • 反向传播 – 获得每个导数(梯度)backward()
y = 2 * torch.dot(x, x)
y.backward()            # 求导
print(x.grad)           # 查看导数
print(x.grad == 4 * x)  # 查看是否一致
  • 清除梯度 – pytorch默认累计梯度 grad_zero_()
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]
'''
  • 对样本和求导 – 深度学习一般不直接计算矩阵的微分,先求和再求导 sum()
x.grad.zero_()
y = x * x           # 对应元素相乘,哈达玛积
y.sum().backward()  # 绝大部分情况标量求导,后续课程中展开探讨
print(x.grad)
print(2 * x == x.grad)
  • 分离计算 – 将某些元素移动到计算图之外 detach()
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)
  • python的各种条件/流程控制语句不影响自动求导

0x03 概率

概率论基本知识,不赘述
个人目前(2022.09.26)浅薄的认知机器学习 == 统计学习

你可能感兴趣的:(动手学深度学习v2笔记,深度学习,python,pytorch,神经网络,conda)