基于PyTorch学AI——一切从Tensor开始

起源

通过PyTorch学习AI是一种最好的学习方法。

  • PyTorch应用范围很广、文档健全;
  • 可以通过PyTorch源码学习AI的绝大部分算法;
  • PyTorch源码本身的架构设计和注释比较规范,可以为开发提供参考。

在这里插入图片描述

第一篇先从Tensor相关的代码开始,这是所有的基础。
函数众多,只挑比较常用的,其余的可以查文档。

tensor的常用函数

torch.is_tensor

判断是否是Tensor对象。

>>> x = torch.tensor([1, 2, 3])
>>> torch.is_tensor(x)
True

torch.tensor

创建tensor对象。

  • data (array_like) – 用于创建tensor的数据。
  • dtype (torch.dtype, optional) – tensor的数据类型。默认根据data的数据自动推导。
  • device (torch.device, optional) – 在什么设备创建tensor。
  • requires_grad (bool, optional) – 是否自动求导。默认为False。
>>> torch.tensor([[0.1, 1.2], [2.2, 3.1], [4.9, 5.2]])
tensor([[ 0.1000,  1.2000],
        [ 2.2000,  3.1000],
        [ 4.9000,  5.2000]])

>>> torch.tensor([0, 1])  # Type inference on data
tensor([ 0,  1])

>>> torch.tensor([[0.11111, 0.222222, 0.3333333]],
...              dtype=torch.float64,
...              device=torch.device('cuda:0'))  # creates a double tensor on a CUDA device
tensor([[ 0.1111,  0.2222,  0.3333]], dtype=torch.float64, device='cuda:0')

>>> torch.tensor(3.14159)  # Create a zero-dimensional (scalar) tensor
tensor(3.1416)

>>> torch.tensor([])  # Create an empty tensor (of size (0,))
tensor([])

torch.as_tensor

用于Numpy的tensor转换成PyTorch的tensor,两个对象有可能共享内存。
如果原数据已经是一个tensor并且没有修改device,则共享内存。如果原数据的type和设备不相同,则复制一份新的数据,那么不共享内存。

>>> a = numpy.array([1, 2, 3])
>>> t = torch.as_tensor(a)
>>> t
tensor([ 1,  2,  3])
>>> t[0] = -1
>>> a
array([-1,  2,  3])

>>> a = numpy.array([1, 2, 3])
>>> t = torch.as_tensor(a, device=torch.device('cuda'))
>>> t
tensor([ 1,  2,  3])
>>> t[0] = -1
>>> a
array([1,  2,  3])

torch.from_numpy

通过numpy的数组创建tensor。
注意,创建的tensor与原来的数组共享内存。

>>> a = numpy.array([1, 2, 3])
>>> t = torch.from_numpy(a)
>>> t
tensor([ 1,  2,  3])
>>> t[0] = -1
>>> a
array([-1,  2,  3])

创建各种 tensor

  • torch.zeros —— 创建tensor,用0填充
  • torch.zeros_like —— 根据参数的大小创建tensor,用0填充
  • torch.ones —— 创建tensor,用1填充
  • torch.ones_like —— 根据参数的大小创建tensor,用1填充
  • torch.empty —— 创建空tensor,用未初始化数据填充
  • torch.empty_like —— 根据参数的大小创建空tensor,用未初始化数据填充
  • torch.full —— 创建tensor,用参数指定的值填充
  • torch.full_like —— 根据参数的大小创建tensor,用参数指定的值填充

torch.arange

这个方法经常用到,用于创建tensor,从start到end,指定step。
注意:[start, end)

>>> torch.arange(5)
tensor([ 0,  1,  2,  3,  4])
>>> torch.arange(1, 4)
tensor([ 1,  2,  3])
>>> torch.arange(1, 2.5, 0.5)
tensor([ 1.0000,  1.5000,  2.0000])

torch.eye

创建单位对角矩阵,也就是对角线是1,区域都是0。

>>> torch.eye(3)
tensor([[ 1.,  0.,  0.],
        [ 0.,  1.,  0.],
        [ 0.,  0.,  1.]])

torch.cat

通过指定维度连接tensor。
可以看作是split和chunk的反向操作。
别名:torch.concat,torch.concatenate。

>>> x = torch.randn(2, 3)
>>> x
tensor([[ 0.6580, -1.0969, -0.4614],
        [-0.1034, -0.5790,  0.1497]])
>>> torch.cat((x, x, x), 0)
tensor([[ 0.6580, -1.0969, -0.4614],
        [-0.1034, -0.5790,  0.1497],
        [ 0.6580, -1.0969, -0.4614],
        [-0.1034, -0.5790,  0.1497],
        [ 0.6580, -1.0969, -0.4614],
        [-0.1034, -0.5790,  0.1497]])
>>> torch.cat((x, x, x), 1)
tensor([[ 0.6580, -1.0969, -0.4614,  0.6580, -1.0969, -0.4614,  0.6580,
         -1.0969, -0.4614],
        [-0.1034, -0.5790,  0.1497, -0.1034, -0.5790,  0.1497, -0.1034,
         -0.5790,  0.1497]])

torch.chunk

将张量拆分为指定数量的多个块。
可以指定拆分基于那个维度,默认维度0。

如指定维度dim的tensor大小可以被块数量整除,则所有返回的块大小相同。
如指定维度dim的tensor大小不能被块数量整除,则除了最后一个块,所有返回的块都将是相同的大小。
如不能进行这样的划分,则返回的块数可能少于块数量参数。

>>> torch.arange(11).chunk(6)
(tensor([0, 1]),
 tensor([2, 3]),
 tensor([4, 5]),
 tensor([6, 7]),
 tensor([8, 9]),
 tensor([10]))
>>> torch.arange(12).chunk(6)
(tensor([0, 1]),
 tensor([2, 3]),
 tensor([4, 5]),
 tensor([6, 7]),
 tensor([8, 9]),
 tensor([10, 11]))
>>> torch.arange(13).chunk(6)
(tensor([0, 1, 2]),
 tensor([3, 4, 5]),
 tensor([6, 7, 8]),
 tensor([ 9, 10, 11]),
 tensor([12]))

torch.gather

沿着由dim指定的轴聚集值。
对于三维数组来说,计算公式如下:

out[i][j][k] = input[index[i][j][k]][j][k]  # if dim == 0
out[i][j][k] = input[i][index[i][j][k]][k]  # if dim == 1
out[i][j][k] = input[i][j][index[i][j][k]]  # if dim == 2

代码举例:

>>> t = torch.tensor([[1, 2], [3, 4]])
>>> torch.gather(t, 1, torch.tensor([[0, 0], [1, 0]]))
tensor([[ 1,  1],
        [ 4,  3]])

torch.index_select

根据一个tensor,利用指定维度dim以及指定的索引返回一个新的tensor。
返回的tensor与原始tensor维数相同。
dim维度的大小与索引的长度相同,其余维度的大小与原始tensor中的大小相同。

>>> x = torch.randn(3, 4)
>>> x
tensor([[ 0.1427,  0.0231, -0.5414, -1.0009],
        [-0.4664,  0.2647, -0.1228, -1.1068],
        [-1.1734, -0.6571,  0.7230, -0.6004]])
        
>>> indices = torch.tensor([0, 2])
>>> torch.index_select(x, 0, indices)
tensor([[ 0.1427,  0.0231, -0.5414, -1.0009],
        [-1.1734, -0.6571,  0.7230, -0.6004]])
        
>>> torch.index_select(x, 1, indices)
tensor([[ 0.1427, -0.5414],
        [-0.4664, -0.1228],
        [-1.1734,  0.7230]])

torch.reshape

根据一个tensor和指定shape返回一个张量,新的tensor与原tensor具有相同的数据和元素数。
如果可能,返回的张量是输入的view,否则,创建一个副本。

如果传的shape是-1,则根据输入中的剩余维度和元素数量推断出新的tensor。

>>> a = torch.arange(4.)
>>> torch.reshape(a, (2, 2))
tensor([[ 0.,  1.],
        [ 2.,  3.]])
        
>>> b = torch.tensor([[0, 1], [2, 3]])
>>> torch.reshape(b, (-1,))
tensor([ 0,  1,  2,  3])

>>> b = torch.tensor([[0, 1, 2], [3, 4, 5]]) 
>>> torch.reshape(b, (2,-1)) 
tensor([[0, 1, 2],
        [3, 4, 5]])

torch.split

Splits the tensor into chunks. Each chunk is a view of the original tensor.
把一个tensor拆分为多个快,每个块的大小由参数split_size_or_sections 决定。
参数split_size_or_sections可以是整数或列表。
如split_size_or_sections是整数,则tensor将被拆分为大小相等(=split_size_or_sections)的块(尽量)。如果沿着给定维度dim的tensor大小不能被split_size_or_sections整除,则最后一个块最小。
如果split_size_or_sections是一个列表,则张量将被拆分为个len(split_size _or_section)块,其大小根据split_sze_or_secttions和dim共同确定。。

>>> a = torch.arange(10).reshape(5, 2)
>>> a
tensor([[0, 1],
        [2, 3],
        [4, 5],
        [6, 7],
        [8, 9]])
>>> torch.split(a, 2)
(tensor([[0, 1],
         [2, 3]]),
 tensor([[4, 5],
         [6, 7]]),
 tensor([[8, 9]]))
>>> torch.split(a, [1, 4])
(tensor([[0, 1]]),
 tensor([[2, 3],
         [4, 5],
         [6, 7],
         [8, 9]]))

torch.stack

沿着一个新的维度连接一系列张量,所有张量都需要具有相同的大小。

>>> x = torch.randn(2, 3)
>>> x
tensor([[ 0.3367,  0.1288,  0.2345],
        [ 0.2303, -1.1229, -0.1863]])
>>> x = torch.stack((x, x)) # same as torch.stack((x, x), dim=0)
>>> x
tensor([[[ 0.3367,  0.1288,  0.2345],
         [ 0.2303, -1.1229, -0.1863]],

        [[ 0.3367,  0.1288,  0.2345],
         [ 0.2303, -1.1229, -0.1863]]])
>>> x.size()
torch.Size([2, 2, 3])
>>> x = torch.stack((x, x), dim=1)
tensor([[[ 0.3367,  0.1288,  0.2345],
         [ 0.3367,  0.1288,  0.2345]],

        [[ 0.2303, -1.1229, -0.1863],
         [ 0.2303, -1.1229, -0.1863]]])
>>> x = torch.stack((x, x), dim=2)
tensor([[[ 0.3367,  0.3367],
         [ 0.1288,  0.1288],
         [ 0.2345,  0.2345]],

        [[ 0.2303,  0.2303],
         [-1.1229, -1.1229],
         [-0.1863, -0.1863]]])
>>> x = torch.stack((x, x), dim=-1)
tensor([[[ 0.3367,  0.3367],
         [ 0.1288,  0.1288],
         [ 0.2345,  0.2345]],

        [[ 0.2303,  0.2303],
         [-1.1229, -1.1229],
         [-0.1863, -0.1863]]])

torch.flatten

flatten方法把默认把多维tensor变为一维tensor,如果传递start_dim或end_dim参数,则仅展平start_dim到end_dim之间的元素,输入中元素的顺序不变。

>>> t = torch.tensor([[[1, 2],
...                    [3, 4]],
...                   [[5, 6],
...                    [7, 8]]])
>>> torch.flatten(t)
tensor([1, 2, 3, 4, 5, 6, 7, 8])
>>> torch.flatten(t, start_dim=1)
tensor([[1, 2, 3, 4],
        [5, 6, 7, 8]])

总结

上述函数都是后续理解各种算法时的一些常用函数。

再次强调,学习AI最好的办法就是看PyTorch文档,没有之一,即使有英文不怎么好也没关系,坚持看就一定有收获,文档中的源码例子都很经典,即使看不懂文字解释,单看例子,也基本能秒懂大部分函数了,再配合实操,学习效果炸裂!
本文提到的函数只是抛砖引玉,只是一小部分,想全面的了解和学习,还是要自己多看文档多读源码。

另外,随着学习的不断深入,应该还会不断增加一些会用到的函数,本文会持续更新。

  • 18
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值