资讯详情

PyTorch日积月累_1-Tensor

文章目录

    • 前言 _ PyTorch主要模块
    • Tensor
      • 张量数据类型
      • 张量的创建
        • 1. 对于预先有数据的情况,通过Torch.tensor()创建
        • 2. 通过`torch`模块下的内置函数创建特殊形状的张量
      • 张量存储设备
      • 张量运算
      • 张量维度
          • 关于contiguous该方法的应用场景
      • 张量极值和排序
      • 张量乘法
      • 拼接分割张量
      • 扩张、压缩和广播
      • 扩张、压缩和广播

前言 _ PyTorch主要模块

本专栏以张校捷为主PyTorch:从模型到源代码的阅读笔记,既有作者自己的思考和补充,又有更详细的内容,请支持原作者。

模块名 功能
torch 1. 常见的,例如torch.relutorch.sigmoid;2. PyTorch中张量的一些操作,比如torch.add(x,y),注:这些操作通常也可以通过张量本身来实现,两者都是等价的,例如x.add(y),对于一些常用的操作,PyTorch运算符的重载已经实现,例如x y3. 产生一定形状的张量,如torch.zerostorch.randn
torch.Tensor PyTorch中张量类型
torch.cuda cuda比如检查cuda是否可用,torch.cuda.is_avalible
torch.nn PyTorch神经网络模块的核心1. 卷积层nn.Conv2d和全连接层nn.Linear等等,其实是调用的nn.functional.Conv2d2. 在构建深度学习模型时,需要继承nn.Module类,并重写forward实现新神经网络的方法3. nn.MSELossnn.CrossEntropyLoss
torch.nn.functional 卷积函数,,不常见的激活函数,如relu6
torch.optim 优化器;学习率下降的子模块,如optim.lr_scheduler
torch.autograd 自动微分包括反向传播autograd.backward函数,autograd.grad实现一个标量(scalar)求导一张量;设置不需要参与求导的模块
torch.distributed PyTorch分布式计算模块的原理是多过程
torch.distributions 可以解决 加强学习Policy Gradient 输出结果离散,无法求导的问题(采样,对数求导)
torch.jit 动态图 → 静态图
torch.utils.data 主要包括数据集(Dataset)数据载入器(DataLoader)
torch.utils.tensorboard 可视化

Tensor

张量数据类型

PyTorch目前支持9种数据类型(torch.float32,torch.int32,torch.uint8,torch.bool,etc.),对应每种数据类型CPU和GPU例如,两个版本,torch.FloatTensortorch.cuda.FloatTensor,但是目前PyTorch复数类型不支持。

可以通过数据类型to例如,转换方法>>> x.to(torch.FloatTensor)

张量的创建

1. 对于预先有数据的情况,通过Torch.tensor()创建

若已提前有数据x(Python list 或 numpy array)可以通过这种方法创建torch.tensor(x),需要注意问题:

  1. 对于numpy数组,精度不变(numpy数组和tensor转换非常快,和tensor这里不表示底层实现)
  2. 对于Python list类型数据,PyTorch默默地将浮点数转换为单精度浮点数(torch.float32)而不是 torch.float64

此外,该方法,但子列表的大小要一致,否则会报错。

注意:torch.Tensor()也支持这种创建方式,但不支持直接引入 例如,创建标量的实数torch.tensor(1)结果是一个scalar类型标量,其shape为torch.Size([]),不同于torch.tensor([1])的shape。

2. 通过torch模块下的内置函数创建特殊形状的张量

>>> import torch   >>> torch.rand(3,3)  # [0,1)均匀分布,注意,如果没有特别说明,一般是前闭后开 tensor([[0.6227, 0.5353, 0.4991],
        [0.9781, 0.3917, 0.0828],
        [0.7478, 0.5403, 0.7267]])
>>> torch.randn(3,3) # 标准正态分布
tensor([[-0.0391,  0.4533,  1.1559],
        [-0.0949,  0.0836,  0.1401],
        [-0.2005,  0.2361, -0.5077]])
>>> torch.zeros(3,3) 
tensor([[0., 0., 0.],
        [0., 0., 0.],
        [0., 0., 0.]])
>>> torch.eye(3,3) 
tensor([[1., 0., 0.],
        [0., 1., 0.],
        [0., 0., 1.]])
>>> torch.ones(3,3) 
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]])
>>> torch.randint(0,10,(3,3))  # [0,10)均匀分布的整数
tensor([[2, 9, 4],
        [1, 7, 7],
        [5, 3, 0]])

注意最后一个torch.randint(0,10,(3,3))的用法。

也可以创建形状相同的张量

torch.ones_like(),torch.zeros_like(), torch.rand_like(),torch.randn_like()

或者直接传入张量的shape/形状的元组,会先检查空间是否足够,然后创建,用时才分配空间。

也在创建时,通过.dtype(torch.float32)指定张量的元素类型

张量的存储设备

注意:只有在相同设备上的张量才能进行运算,否则会报错。

将数据转移到其他设备的方法: x.cpu()或者x.gpu(0)x.to("cuda:0")

推荐使用后一种,参数可以是设备名,也可以是torch.device实例。

张量运算

一般有两种等价的运算方法

  1. torch.add(a,b) 或者 torch.add(a,b,out=c),第二种需提前声明c
  2. a.add(b)或者 a.add_(b), 第二种方法后加下划线,表明是就地操作,即修改了a的值

张量维度

可以通过size(x)或者x.shape查看张量形状,两种方法等价,返回的都是PyTorch基于Python Tuple封装的torch.Size类型,通过索引查看每个维度的大小。

改变张量形状:

  1. view方法,指定-1,PyTorch会自动计算,只改变tensor头部中的步长(stride)信息,而改变底层数据,注意,一定要保证前后元素个数一致。

    如果想要将内容复制到新的一份内存空间,若前后不兼容,使用.contiguous(),否则,直接深拷贝torch.clone()即可。

    More about contiguous

  2. reshape方法

    相当于view+contiguous

关于contiguous方法的一个应用场景

需求:将四张256*256的RGB图片截取成上下两部分,并保存为六张照片。

思考:实际就是[4,3,256,256]→[12,3,128,256]

img_PIL = torch.rand(4,3,256,256)

new_img_tensor = img_tensor.view(4,3,2,128,256)
new_img_tensor = new_img_tensor.permute(0,2,1,3,4)
new_img_tensor.contiguous()  # 注意,view方法只能处理语义和内存一致/兼容的张量,需要提前进行一致化处理
new_img_tensor = new_img_tensor.view(8,2,128,256)

张量极值和排序

使用案例

>>> x = torch.rand(3,4)
>>> x
tensor([[0.6890, 0.6742, 0.1902, 0.9747],
        [0.4639, 0.3918, 0.4839, 0.8264],
        [0.7149, 0.8934, 0.9888, 0.4748]])
>>> x.argmin(1) 
tensor([2, 1, 3])
>>> x.min(1) 
torch.return_types.min(
values=tensor([0.1902, 0.3918, 0.4748]),
indices=tensor([2, 1, 3]))
>>> torch.argmin(x,1) 
tensor([2, 1, 3])
>>> torch.min(x,1) 
torch.return_types.min(
values=tensor([0.1902, 0.3918, 0.4748]),
indices=tensor([2, 1, 3]))
>>> x.sort(1) 
torch.return_types.sort(
values=tensor([[0.1902, 0.6742, 0.6890, 0.9747],
        [0.3918, 0.4639, 0.4839, 0.8264],
        [0.4748, 0.7149, 0.8934, 0.9888]]),
indices=tensor([[2, 1, 0, 3],
        [1, 0, 2, 3],
        [3, 0, 1, 2]]))
>>> x.sort(1,descending=True)
torch.return_types.sort(
values=tensor([[0.9747, 0.6890, 0.6742, 0.1902],
        [0.8264, 0.4839, 0.4639, 0.3918],
        [0.9888, 0.8934, 0.7149, 0.4748]]),
indices=tensor([[3, 0, 1, 2],
        [3, 2, 0, 1],
        [2, 1, 0, 3]]))

argmin和min既可以使用torch模块下的方法,也可以使用tensor自带的方法,前者返回indices,后者返回最小值和其在原始张量上的位置,sort排序默认是升序,也可通过descending=True指定为降序。

张量乘法

前面的a.mul(b)是对应元素相乘,而a.mm(b)对应的是矩阵乘法,在Python3.5之后,根据PEP465提案,也可以用a@b进行矩阵乘法。

mini-batch 矩阵乘法:torch.bmm(a,b)针对有batch的情况,如果此时调用a@b,会自动调用bmm

对于更多维度的张量相乘的情况,需要决定各自张量元素乘积的结果沿着哪些维度求和,这个过程称作 contraction,需引入爱因斯坦求和约定 Einstein Summation Convention:

More about Einsum in PyTorch

但是,einsum的运行速度非常慢,下面在cpu上写一个测试时间的装饰器

# 验证torch.einsum的速度
import time
import torch

def time_test(func):
    def inner(*args,**kwargs):
        start_time = time.time()
        func(*args,**kwargs)
        end_time = time.time()
        return end_time - start_time
    return inner

@time_test
def common_test(a,b):
    for i in range(1000):
        a.mul(b)

@time_test
def einsum_test(a,b):
    for i in range(1000):
        torch.einsum('ik,kj->ij',[a,b])

def main():
    a = torch.arange(10000).reshape(100, 100)
    b = torch.arange(10000).reshape(100, 100)
    einsum_time = einsum_test(a,b)
    common_time = common_test(a,b)
    print("common_test takes %s\neinsum_test takes %.3f s"%(common_time,einsum_time))

if __name__ == "__main__":
    main()
# common_test takes 0.016 s
# einsum_test takes 2.647 s

张量的拼接与分割

拼接

  1. torch.stack 传入 张量列表,指定并一个维度堆叠
  2. torch.cat 传入张量列表,一个维度拼接

分割

  1. torch.split 传入 被分割张量,分割后维度的 整数/列表,分割的维度
  2. torch.chunk 传入 被分割张量,分割的 整数/列表,分割的维度

张量的扩增、压缩和广播

torch.squeezetorch.unsqueeze

广播机制,主要是用来解决 四则运算时 张量维度不一致的问题

  1. 如果两张量的形状不一致,不能进行计算,例如(3,4,5)只能和(3,4,5)形状的张量运算

  2. 除了一种特殊情况,张量的某个维度为1,则进行复制,使其满足条件1

    例如 (3,4,5)和(3,1,5),需要将(3,1,5)扩增为(3,4,5),然后进行运算

数/列表,分割的维度

张量的扩增、压缩和广播

torch.squeezetorch.unsqueeze

广播机制,主要是用来解决 四则运算时 张量维度不一致的问题

  1. 如果两张量的形状不一致,不能进行计算,例如(3,4,5)只能和(3,4,5)形状的张量运算

  2. 除了一种特殊情况,张量的某个维度为1,则进行复制,使其满足条件1

    例如 (3,4,5)和(3,1,5),需要将(3,1,5)扩增为(3,4,5),然后进行运算

标签: 3917连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台