Pytorch深度学习【二】

线性代数基础

  • 知识框架
    • 标量操作及长度
    • 向量操作及长度—向量的长度就是每个向量的平方和开根号
    • 向量点乘、正交
    • 矩阵—就是把一个空间进行扭曲
    • 矩阵简单操作、乘法—就是空间扭曲—矩阵乘矩阵就是一行乘一列
    • 向量范数
      • L1范数—每一个数绝对值求和
      • L2范数—向量或者矩阵的长度—元素平方求和开根号
    • 矩阵范数
      • F范数—矩阵元素的平方和的平方根
      • 意义上就是把矩阵拉成向量再做L2范数
    • 正定的定义—矩阵乘任意一个向量都大于等于0
    • 正交矩阵—所有行都相互正交、所有行都有单位长度
    • 特征向量特征值
    • 不被矩阵改变方向的向量—特征向量
  • 代码实现
      import torch 
      # 标量运算
      x = torch.tensor([3.0])
      y = torch.tensor([3.0])
      x + y, x * y
      # 向量运算
      x = torch.arange(4)
      x[3] # 索引访问
      len(x) # 张量长度
      x.shape # 形状只有一个元素
      # 创建一个m*n的矩阵
      A = torch.arange(20.).reshape(5, 4)
      A
      A.T # 矩阵的转置
      B = torch.arange(9).reshape(3, 3)
      B == B.T # 对称矩阵
      C = torch.arange(24).reshape(2, 3, 4)
      C # 构建一个双通道的二维矩阵
      D = C.clone() # 通过分配新内存,将C的一个副本分配D
      C * D # 矩阵中对应元素相乘---不是矩阵乘法
      A.sum() # 直接将所有元素求和---结果是一个标量
      D_sum_axis0 = D.sum(axis=0) # 将(2, 3, 4)中的第一个维度合并即通道对应位置合并
      D, D.shape, D_sum_axis0, D_sum_axis0.shape
      # axis = 1 和 axis = 2 就是两个通道各自行合并和列合并 也可以 axis=[0,1]
      A.numel() # 求元素个数
      A.sum() # 求元素和
      A.mean() # 求平均数
      A.mean(axis=0) # 对A的第一个参数求平均
      A.mean(axis=1) # 对A的第二个参数求平均
      sum_A = A.sum(axis=1, keepdims=True) 
      # keepdims可以保证求和后维度不变---方便后续广播机制---广播机制有赖于维度一致
      A.cumsum(axis=0) # 累加求和
      x = torch.ones(4, dtype=torch.float32)
      y = torch.ones(4, dtype=torch.float32)
      #==========================关于各类乘积运算==========================#
      # dot理解为对一维向量的点乘
      torch.dot(x, y) 
      # 点积是相同位置的按元素乘积的和---torch.sum(x * y)---但是这只能针对一维向量
      # *只能是矩阵中对应位置相乘
      C * D # 矩阵中对应元素相乘---不是矩阵乘法
      # .mv()是一个矩阵与一个向量相乘的运算---结果是列向量---可以理解为矩阵A对向量x进行了扭曲
      A = torch.tensor([[1,2,3], [1,1,1]])
      x = torch.tensor([1,1,1]) # 列向量
      torch.mv(A, x)
      # .mm()是真正的矩阵乘法的定义
      A = torch.tensor([[1,2,3], [1,1,1]]) # (2, 3)
      B = torch.tensor([[1,1], [1,1], [1,1]]) # (3, 2)
      torch.mm(A, B)
      # 向量范数
      u = torch.tensor([1., 2.])
      torch.norm(u) # L2
      torch.abs(u).sum() # L1
      # 矩阵范数
      U = torch.ones(3,2)
      torch.norm(U)
    

矩阵计算—如何求导数

  • 标量的导数
  • 亚导数—将导数拓展到不可微函数
  • 梯度—将导数拓展到向量—指向某一点变化最剧烈的方向
    • 一个标量对一个列向量求导—结果为一个行向量—相当于转置
    • 一个列向量对一个标量求导—结果为一个列向量
    • 一个内积对一个列向量求导—结果为另外一个列向量的转置
    • 一个向量对一个向量求导—结果为一个矩阵

自动求导

  • 标量对链式法则
  • 自动求导计算一个函数在指定值上的导数
    • 符号求导—直接根据表达式进行计算
    • 数值求导—不需要知道具体表达式,通过数值拟合
  • 计算图—分解计算流程
    • 将代码分解成操作子
    • 将计算表示成一个无环图
    • 显式构造—写出表达式再给值计算结果
      from mxnet import sym
      a = sym.var() # 定义变量
      b = sym.var()
      c = 2*a + b
    
    • 隐式构造—记住每一步的计算,最后进行组合
      from mxnet import autograd, nd
      with autograd.record():
          a = nd.ones((2, 1))
          b = nd.ones((2, 1))
          c = 2*a + b
    
  • 自动求导的两种模式
    • 链式法则拆分公式
    • 正向积累—从前向后推
      • 前向执行过程中需要保存中间结果
      • N层神经网络的计算复杂度为 n,但存储复杂度也为 n
    • 反向传递—从后向前推—其实就是平时手算的方向
      • 依次进行执行,不需要存储中间的枝干
      • N层神经网络的计算复杂度为 n,但存储复杂度为 1
  • 自动求导的pytorch实现
      # 对函数y = 2x(转置)x 关于列向量x求导
      import torch
      x = torch.arange(4.0)
      x
      x.requires_grad_(True) # 开辟存储梯度的位置
      x.grad  # 默认值为None---可以存储梯度
      y = 2 * torch.dot(x, x) # 内积-->生成标量
      y.backward() # 计算反向传播自动计算y关于x每个分量的梯度
      x.grad
      x.grad.zero_() # grad是不能自动清零的,因此在每次计算前进行一个清零
      y = x.sum()
      y.backward()
      x.grad
    
  • 深度学习中,我们的目的不是计算微分矩阵,而是批量中每个样本单独计算的偏导数之和
    import torch
    x = torch.arange(4.0)
    x
    x.requires_grad_(True) # 开辟存储梯度的位置
    y = x * x
    y.sum().backward()
    x.grad
  • 如果我们对网络希望将某些参数固定住,那么我们可以将某些计算移动到记录的计算图外
# 对函数y = 2x(转置)x 关于列向量x求导
import torch
x = torch.arange(4.0)
y = x * x
u = y.detach() # 使得u成为数值为y的常数, u不再是x的函数
z = u * x
z.sum().backward()
x.grad # 等于u
x.grad.zero_()
y.sum().backward() # 通过y可以依然对x进行求导
x.grad
  • 构建函数的计算图需要通过python控制流(条件,循环)我们仍然可以计算得到的变量的梯度
def f(a):
    b = a * 2
    while b.norm() < 1000:
        b = b * 2
    if b.sum() > 0:
        c = b
    else:
        c = 100 * b
    return c
a = torch.randn(size=(), requires_grad=True) # size = () 就是标量
d = f(a)
d.backward()
a.grad == d / a 

你可能感兴趣的:(深度学习,pytorch)