• 【PyTorch教程】03-张量运算详细总结



    1. 张量运算

    PyTorch中的张量运算函数超过100种,包括转置、索引、切片、数学运算、线性代数、随机采样。更详细的张量运算请查看官方文档:

    torch — PyTorch 1.12 documentation

    以上所有运算都可以在GPU上运行,比CPU的运算速度更快。


    2. 把张量移到GPU运算

    首先,要确保你的电脑已经安装了GPU版本的PyTorch,用以下命令来查看:

    torch.cuda.is_available()
    
    • 1

    若返回 True ,则GPU是可用的。否则,只能在CPU上进行张量运算。


    接下来,我们使用 to('cuda') 函数把张量移动到GPU上。

    【注意】原本在CPU的张量只是复制了一个副本过去GPU,其本身仍旧存储在CPU上。因此使用 to('cuda') 函数时,要声明一个新的变量来接收GPU张量。


    举个栗子:

    import torch
    
    tensor = torch.rand(3, 4)  # 创建形状为(3, 4)的随机张量
    if torch.cuda.is_available():  # 检查GPU是否可用
        tensor_gpu = tensor.to('cuda')  # 声明了新变量tensor_gpu来接收
        print(f"GPU张量现在存储在:{tensor_gpu.device}")
    print(f"原张量存储在:{tensor.device}")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    输出:

    GPU张量现在存储在:cuda:0
    原张量存储在:cpu
    
    • 1
    • 2

    3. 张量索引和切片

    以二维张量 (矩阵) 为例,我们先创建一个形状为 (4, 4) 的二维张量 tensor

    import torch
    
    tensor = torch.ones(4, 4)
    print(f"Ones tensor: \n {tensor}")
    
    • 1
    • 2
    • 3
    • 4

    输出:

    Ones tensor: 
    tensor([[1., 1., 1., 1.],
            [1., 1., 1., 1.],
            [1., 1., 1., 1.],
            [1., 1., 1., 1.]])
    
    • 1
    • 2
    • 3
    • 4
    • 5

    张量切片的标准格式为:

    tensor[r1:r2, c1:c2]
    
    • 1

    其中:

    • r1 表示切片开始的行数,r2 表示结束的行数。c1 表示切片开始的列数,c2 表示结束的列数。
    • 若想选择整行,写成:tensor[r1:r2, :] ;同理,若想选择整列,写成:tensor[:, c1:c2] ;全选则写成:tensor[:, :]
    • 当只选择某一行 (或某一列) 时,可以省略 : ,只写行号 (列号) 。
    • 张量的切片范围遵循左闭右开原则。即开始包含,结束不包含。
    • 张量的行数、列数,均是从 0 开始。

    举几个栗子:

    1.标准切片

    import torch
    
    tensor = torch.ones(4, 4).to('cuda')
    print(f"Ones tensor: \n{tensor} \n")
    tensor[1:3, 1:3] = 0
    print(tensor)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    输出:

    Ones tensor: 
    tensor([[1., 1., 1., 1.],
            [1., 1., 1., 1.],
            [1., 1., 1., 1.],
            [1., 1., 1., 1.]], device='cuda:0') 
    
    tensor([[1., 1., 1., 1.],
            [1., 0., 0., 1.],
            [1., 0., 0., 1.],
            [1., 1., 1., 1.]], device='cuda:0')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2.整行切片

    tensor[1:3, :] = 0
    
    • 1

    输出:

    Ones tensor: 
    tensor([[1., 1., 1., 1.],
            [1., 1., 1., 1.],
            [1., 1., 1., 1.],
            [1., 1., 1., 1.]], device='cuda:0') 
    
    tensor([[1., 1., 1., 1.],
            [0., 0., 0., 0.],
            [0., 0., 0., 0.],
            [1., 1., 1., 1.]], device='cuda:0')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3.一列切片

    tensor[:, 2] = 0
    
    • 1

    输出:

    Ones tensor: 
    tensor([[1., 1., 1., 1.],
            [1., 1., 1., 1.],
            [1., 1., 1., 1.],
            [1., 1., 1., 1.]], device='cuda:0') 
    
    tensor([[1., 1., 0., 1.],
            [1., 1., 0., 1.],
            [1., 1., 0., 1.],
            [1., 1., 0., 1.]], device='cuda:0')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4.全部切片

    tensor[:, :] = 0
    
    • 1

    输出:

    Ones tensor: 
    tensor([[1., 1., 1., 1.],
            [1., 1., 1., 1.],
            [1., 1., 1., 1.],
            [1., 1., 1., 1.]], device='cuda:0') 
    
    tensor([[0., 0., 0., 0.],
            [0., 0., 0., 0.],
            [0., 0., 0., 0.],
            [0., 0., 0., 0.]], device='cuda:0')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    学会了以上操作,其他情况相信你可以很轻易地举一反三。


    4. 张量的拼接

    通过 torch.cat() 函数 ,可以把若干个张量按照你指定的维度方向进行拼接。

    • 沿着维度 0 0 0 是沿着行 (row) 的方向,即竖直方向;
    • 沿着维度 1 1 1 是沿着列 (column) 的方向,即水平方向;

    举个栗子:

    import torch
    
    tensor = torch.ones(4, 4).to('cuda')
    tensor[:, 1] = 0
    print(f"Origin tensor:\n{tensor}\n")
    
    t1 = torch.cat([tensor, tensor, tensor], dim=1)  # 水平拼接
    print(f"Horizontal concatenate:\n{t1}\n")
    
    t2 = torch.cat([tensor, tensor], dim=0)  # 竖直拼接
    print(f"Vertical concatenate:\n{t2}\n")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    输出:

    Origin tensor:
    tensor([[1., 0., 1., 1.],
            [1., 0., 1., 1.],
            [1., 0., 1., 1.],
            [1., 0., 1., 1.]], device='cuda:0')
    
    Horizontal concatenate:
    tensor([[1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.],
            [1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.],
            [1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.],
            [1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.]], device='cuda:0')
    
    Vertical concatenate:
    tensor([[1., 0., 1., 1.],
            [1., 0., 1., 1.],
            [1., 0., 1., 1.],
            [1., 0., 1., 1.],
            [1., 0., 1., 1.],
            [1., 0., 1., 1.],
            [1., 0., 1., 1.],
            [1., 0., 1., 1.]], device='cuda:0')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    5. 张量的转置

    tensor = torch.ones(4, 4).to('cuda')
    tensor[:, 1] = 0
    print(f"Origin tensor:\n{tensor}\n")
    
    t1 = tensor.T  # 张量的转置
    print(f"Transposing tensor: \n{t1}")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    输出:

    Origin tensor:
    tensor([[1., 0., 1., 1.],
            [1., 0., 1., 1.],
            [1., 0., 1., 1.],
            [1., 0., 1., 1.]], device='cuda:0')
    
    Transposing tensor: 
    tensor([[1., 1., 1., 1.],
            [0., 0., 0., 0.],
            [1., 1., 1., 1.],
            [1., 1., 1., 1.]], device='cuda:0')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    6. 张量的点乘和叉乘


    1.点乘

    张量每个元素对应相乘,用 a ⋅ b a\cdot b ab 表示。要求两个张量形状 (维度) 完全相同。

    import torch
    
    tensor = torch.ones(4, 4).to('cuda')
    tensor[:, 1] = 2
    print(f"Origin tensor:\n{tensor}\n")
    
    # 张量的点乘:逐个元素对应相乘
    t1 = tensor.mul(tensor)
    print(f"tensor.mul(tensor): \n{t1}\n")
    # 等价写法
    t2 = tensor * tensor
    print(f"tensor * tensor: \n{t2}\n")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    输出:

    Origin tensor:
    tensor([[1., 2., 1., 1.],
            [1., 2., 1., 1.],
            [1., 2., 1., 1.],
            [1., 2., 1., 1.]], device='cuda:0')
    
    tensor.mul(tensor): 
    tensor([[1., 4., 1., 1.],
            [1., 4., 1., 1.],
            [1., 4., 1., 1.],
            [1., 4., 1., 1.]], device='cuda:0')
    
    tensor * tensor: 
    tensor([[1., 4., 1., 1.],
            [1., 4., 1., 1.],
            [1., 4., 1., 1.],
            [1., 4., 1., 1.]], device='cuda:0')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2.叉乘

    也称为矩阵乘法,矩阵的乘法就是矩阵 A A A 的第 m m m 行乘以矩阵 B B B 的第 n n n 列,各个元素对应相乘然后求和作为第 m m m n n n 列元素的值。用 a × b a\times b a×b 表示。

    要求:矩阵 A A A 的第 m m m 行元素数量等于矩阵 B B B 的第 n n n 列 。

    # 张量的叉乘:矩阵乘法
    t3 = tensor.matmul(tensor.T)
    print(f"tensor.matmul(tensor.T): \n{t3}\n")
    # 等价写法
    t4 = tensor @ tensor.T
    print(f"tensor @ tensor.T: \n{t4}")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    输出:

    tensor.matmul(tensor.T): 
    tensor([[7., 7., 7., 7.],
            [7., 7., 7., 7.],
            [7., 7., 7., 7.],
            [7., 7., 7., 7.]], device='cuda:0')
    
    tensor @ tensor.T: 
    tensor([[7., 7., 7., 7.],
            [7., 7., 7., 7.],
            [7., 7., 7., 7.],
            [7., 7., 7., 7.]], device='cuda:0')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    7. 自动赋值运算

    自动赋值运算在函数后添加 _ 后缀来表示。例如,tensor.add_(x) 操作会改变 tensor 本身的值。

    import torch
    
    tensor = torch.ones(4, 4).to('cuda')
    tensor[:, 1] = 2
    print(f"Origin tensor:\n{tensor}\n")
    
    tensor.add_(5)  # 广播机制,每个元素都加5
    print(f"tensor.add(5): \n{tensor}")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    输出:

    Origin tensor:
    tensor([[1., 2., 1., 1.],
            [1., 2., 1., 1.],
            [1., 2., 1., 1.],
            [1., 2., 1., 1.]], device='cuda:0')
    
    tensor.add_(5): 
    tensor([[6., 7., 6., 6.],
            [6., 7., 6., 6.],
            [6., 7., 6., 6.],
            [6., 7., 6., 6.]], device='cuda:0')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    注意:

    自动赋值运算虽然可以节省内存, 但在求导时会因为丢失了中间过程而导致一些问题,所以PyTprch官方并不鼓励使用它。

  • 相关阅读:
    python 之爬虫基础(2)
    数据库-MySQL-索引介绍
    京东按关键字搜索商品 API 返回值说明
    C++ 语言的学习 纯虚函数,析构函数建议定义成虚函数,解决菱形继承,文件操作,二进制文件,虚函数表
    系统篇: ubuntu 下利用 apt 安装与卸载详解
    发个地区和对应的价格方案
    Lambda表达式,Stream流
    SpringBoot SpringBoot 基础篇 4 基于 SpringBoot 的SSMP 整合案例 4.15 删除功能
    Bun v0.8.0 正式发布,Zig 编写的 JavaScript 运行时
    数据分析(二):学生成绩预测分析报告
  • 原文地址:https://blog.csdn.net/Sihang_Xie/article/details/125634607