pytorch学习笔记(一)pytorch基础知识

系列文章目录

pytorch学习笔记(二)pytorch主要组成模块


文章目录

  • 系列文章目录
  • pytorch学习笔记(一)pytorch基础知识
    • 1.1 张量
      • 1.1.1 简介
      • 1.1.2 创建tensor
      • 1.1.3 张量的操作
      • 1.1.4 广播机制
    • 1.2 自动求导
      • 1.2.1 Autograd简介
      • 1.2.2 梯度


pytorch学习笔记(一)pytorch基础知识

本文是在学习DataWhale开源教程《深入浅出PyTorch》过程中做的简单摘抄,原文请点这里第二章:PyTorch基础知识 — 深入浅出PyTorch (datawhalechina.github.io)

1.1 张量

1.1.1 简介

张量是现代机器学习基础,它的核心是一个数据容器,不同维度的张量可以表示不同的数据类型

如:

  • 3维:时间序列
  • 4维:图像
  • 5维:视频

一个图像可以用三个字段表示:

(width, height, channel) = 3D

但是,在机器学习工作中,我们经常要处理不止一张图片或一篇文档——我们要处理一个集合。我们可能有10,000张郁金香的图片,这意味着,我们将用到4D张量:

(batch_size, width, height, channel) = 4D

在PyTorch中, torch.Tensor 是存储和变换数据的主要工具

1.1.2 创建tensor

pytorch学习笔记(一)pytorch基础知识_第1张图片

下面是几种常见方法的示例

  1. 随即初始化矩阵 torch.rand()

    import torch
    x = torch.rand(4, 3) 
    print(x)
    
    tensor([[0.7569, 0.4281, 0.4722],
            [0.9513, 0.5168, 0.1659],
            [0.4493, 0.2846, 0.4363],
            [0.5043, 0.9637, 0.1469]])
    
  2. 全零矩阵 torch.zeros()

    import torch
    x = torch.zeros(4, 3, dtype=torch.long)
    print(x)
    
    tensor([[0, 0, 0],
            [0, 0, 0],
            [0, 0, 0],
            [0, 0, 0]])
    
  3. 构建张量 torch.tensor()

    import torch
    x = torch.tensor([5.5, 3]) 
    print(x)
    
    tensor([5.5000, 3.0000])
    
  4. 基于已经存在的tensor,创建一个tensor

    x = x.new_ones(4, 3, dtype=torch.double) 
    # 创建一个新的全1矩阵tensor,返回的tensor默认具有相同的torch.dtype和torch.device
    # 也可以像之前的写法 x = torch.ones(4, 3, dtype=torch.double)
    print(x)
    x = torch.randn_like(x, dtype=torch.float)
    # 重置数据类型
    print(x)
    # 结果会有一样的size
    # 获取它的维度信息
    print(x.size())
    print(x.shape)
    
    tensor([[1., 1., 1.],
            [1., 1., 1.],
            [1., 1., 1.],
            [1., 1., 1.]], dtype=torch.float64)
    tensor([[ 2.7311, -0.0720,  0.2497],
            [-2.3141,  0.0666, -0.5934],
            [ 1.5253,  1.0336,  1.3859],
            [ 1.3806, -0.6965, -1.2255]])
    torch.Size([4, 3])
    torch.Size([4, 3])
    

1.1.3 张量的操作

  1. 加法

    1. x+y
    2. torch.add(x+y)
    3. y.add_(x)
  2. 索引

    import torch
    x = torch.rand(4,3)
    # 取第二列
    print(x[:, 1]) 
    
  3. 维度变换

    torch.view()

    x = torch.randn(4, 4)
    y = x.view(16)
    z = x.view(-1, 8) # -1是指这一维的维数由其他维度决定
    print(x.size(), y.size(), z.size())
    
    torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])
    

torch.view() 返回的新tensor与源tensor共享内存(其实是同一个tensor),更改其中的一个,另外一个也会跟着改变。(顾名思义,view()仅仅是改变了对这个张量的观察角度)。

如果我们希望原始张量和变换后的张量互相不影响,可以先用 clone() 创造一个张量副本然后再使用 torch.view()进行维度变换

1.1.4 广播机制

当对两个形状不同的 Tensor 按元素运算时,可能会触发广播(broadcasting)机制:先适当复制元素使这两个 Tensor 形状相同后再按元素运算。

x = torch.arange(1, 3).view(1, 2)
print(x)
y = torch.arange(1, 4).view(3, 1)
print(y)
print(x + y)
tensor([[1, 2]])
tensor([[1],
        [2],
        [3]])
tensor([[2, 3],
        [3, 4],
        [4, 5]])

由于x和y分别是1行2列和3行1列的矩阵,如果要计算x+y,那么x中第一行的2个元素被广播 (复制)到了第二行和第三行,而y中第⼀列的3个元素被广播(复制)到了第二列。如此,就可以对2个3行2列的矩阵按元素相加。

1.2 自动求导

1.2.1 Autograd简介

PyTorch 中,所有神经网络的核心是 autograd 包。autograd包为张量上的所有操作提供了自动求导机制。它是一个在运行时定义 ( define-by-run )的框架,这意味着反向传播是根据代码如何运行来决定的,并且每次迭代可以是不同的。

tensor是这个包的核心类,设置它的属性 .requires_gradTrue,那么它将会追踪对于该张量的所有操作。当完成计算后可以通过调用 .backward(),来自动计算所有的梯度。这个张量的所有梯度将会自动累加到.grad属性。

为了防止跟踪历史记录(和使用内存),可以将代码块包装在 with torch.no_grad(): 中。在评估模型时特别有用,因为模型可能具有 requires_grad = True 的可训练的参数,但是我们不需要在此过程中对他们进行梯度计算。

还有一个类对于autograd的实现非常重要:FunctionTensor Function 互相连接生成了一个无环图 (acyclic graph),它编码了完整的计算历史。每个张量都有一个.grad_fn属性,该属性引用了创建 Tensor 自身的Function(除非这个张量是用户手动创建的,即这个张量的grad_fnNone )。

eg:

创建一个张量并设置requires_grad=True用来追踪其计算历史

x = torch.ones(2, 2, requires_grad=True)
print(x)
tensor([[1., 1.],
        [1., 1.]], requires_grad=True)

对这个张量做一次运算:

y = x ** 2
print(y)
tensor([[1., 1.],
        [1., 1.]], grad_fn=<PowBackward0>)

y是计算的结果,所以它有grad_fn属性。

print(y.grad_fn)
<PowBackward0 object at 0x000001CB45988C70>

对 y 进行更多操作

z = y * y * 3
out = z.mean()
print(z, out)
tensor([[3., 3.],
        [3., 3.]], grad_fn=<MulBackward0>) tensor(3., grad_fn=<MeanBackward0>)

1.2.2 梯度

out.backward()

输出导数 d(out)/dx

print(x.grad)
tensor([[3., 3.],
        [3., 3.]])

注意:grad在反向传播过程中是累加的(accumulated),这意味着每一次运行反向传播,梯度都会累加之前的梯度,所以一般在反向传播之前需把梯度清零。

如果我们想要修改 tensor 的数值,但是又不希望被 autograd 记录(即不会影响反向传播), 那么我们可以对 tensor.data 进行操作。

x = torch.ones(1,requires_grad=True)

print(x.data) # 还是一个tensor
print(x.data.requires_grad) # 但是已经是独立于计算图之外

y = 2 * x
x.data *= 100 # 只改变了值,不会记录在计算图,所以不会影响梯度传播

y.backward()
print(x) # 更改data的值也会影响tensor的值 
print(x.grad)
tensor([1.])
False
tensor([100.], requires_grad=True)
tensor([2.])

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