Pytorch(一):关于张量 Tensors

决定好好整理下学习的有关 Pytorch 的内容。系统性的梳理和笔记对我这种只有七秒记忆的来说真的太重要,撸起袖子加油干!!!

我一直看的文档是这个 Pytorch官方教程中文版(提取码:pyto) ,以及参考百度来的各种博客。如果本文的某些内容存在错误或其他问题,希望各位大佬能够帮我指出来,互相学习共同进步!

共勉!
————————————————————————————————————

0. Tensors 简介

Tensors 是一种特殊的数据结构,类似于数组(array)和矩阵(matrices),可以将 Tensors 想象成 NumPy 的 ndarray,两者的不同点在于 Tensors 可以在GPU或其他硬件加速器上运行。

那么Tensors 与 PyTorch 的关联是什么?PyTorch 是一个深度学习框架,通常用来搭建网络模型,其中模型的输入和输出以及模型的参数都是使用 Tensors 进行的编码,所以 Tensors 是学好 PyTorch 必备的基础知识。

正文开始前先把 torch 定义的10 种数据类型 放在这里。

在这里插入图片描述

1. Tensor的创建

1.1 torch.tensor() 构造函数

torch.tensor() 本质是一个构造函数,能够利用已经存在的数据创建一个 tensor,这里的数据可以是 Python 列表或序列。

>>> import torch
>>> data=[[1,2],[3,4]]
>>> x_data=torch.tensor(data)
>>> x_data
tensor([[1, 2],
        [3, 4]])

1.2 torch.* ( * 代表 tensor creation ops)

创建具有特定大小或数据的 tensor,例如:

>>> torch.rand((2,3))
tensor([[0.4003, 0.6610, 0.7162],
        [0.2321, 0.3320, 0.1750]])
>>> torch.randn((2,3))
tensor([[-0.4969, -0.9932,  0.6773],
       [-2.4680, -0.1342,  1.2729]])
>>> torch.randint(0,10,(2,3))
tensor([[0, 4, 3],
        [1, 6, 9]])
>>> torch.zeros((2,3))
tensor([[0., 0., 0.],
        [0., 0., 0.]])
>>> torch.ones((2,3))
tensor([[1., 1., 1.],
        [1., 1., 1.]])
>>> torch.empty((2,3))
tensor([[0.0000e+00, 0.0000e+00, 1.4013e-45],
        [0.0000e+00, 1.4013e-45, 0.0000e+00]])
>>> torch.full((2,3), 3.14)
tensor([[3.1400, 3.1400, 3.1400],
        [3.1400, 3.1400, 3.1400]])

1.3 torch.*_like ( * 代表 tensor creation ops)

创建与另一个 tensor 具有相同大小 (和相似类型) 的 tensor,例如:

>>> x_data = torch.tensor([[1,2],[3,4]])
>>> torch.rand_like(x_data,dtype=torch.float)
tensor([[0.9007, 0.4228],
        [0.7481, 0.3723]])
>>> torch.randn_like(x_data,dtype=torch.float)
tensor([[-0.3384,  0.8430],
        [-0.7049,  0.8661]])
>>> torch.randint_like(x_data,0,10)
tensor([[8, 0],
        [8, 8]])
>>> torch.zeros_like(x_data)
tensor([[0, 0],
        [0, 0]])
>>> torch.ones_like(x_data)
tensor([[1, 1],
        [1, 1]])
>>> torch.empty_like(x_data)
tensor([[0, 0],
        [0, 0]])
>>> torch.full_like(x_data,3.14)
tensor([[3, 3],
        [3, 3]])
# 生成的tensor之所以是由3填充而不是3.14的原因在于:
# x_data的数据类型是torch.int64
# 而torch.full_like()在不给定参数dtype时会生成与x_data大小和类型都相同的tensor

1.4 tensor.new_* ( * 代表 tensor creation ops)

创建与其他 tensor 具有相似类型但大小不同的 tensors,例如:

  • new_tensor(data, dtype=None, device=None, requires_grad=False)
>>> tensor = torch.ones((2,), dtype=torch.int8)
>>> data = [[0, 1], [2, 3]]
>>> tensor.new_tensor(data)
tensor([[ 0,  1],
        [ 2,  3]], dtype=torch.int8)
  • new_full(size, fill_value, dtype=None, device=None, requires_grad=False)
>>> tensor = torch.ones((2,), dtype=torch.float64)
>>> tensor.new_full((3, 4), 3.141592)
tensor([[ 3.1416,  3.1416,  3.1416,  3.1416],
        [ 3.1416,  3.1416,  3.1416,  3.1416],
        [ 3.1416,  3.1416,  3.1416,  3.1416]], dtype=torch.float64)
  • new_empty(size, dtype=None, device=None, requires_grad=False)
>>> tensor = torch.ones(())
>>> tensor.new_empty((2, 3))
tensor([[ 5.8182e-18,  4.5765e-41, -1.0545e+30],
        [ 3.0949e-41,  4.4842e-44,  0.0000e+00]])
  • new_ones(size, dtype=None, device=None, requires_grad=False)
>>> tensor = torch.tensor((), dtype=torch.int32)
>>> tensor.new_ones((2, 3))
tensor([[ 1,  1,  1],
        [ 1,  1,  1]], dtype=torch.int32)
  • new_zeros(size, dtype=None, device=None, requires_grad=False)
>>> tensor = torch.tensor((), dtype=torch.float64)
>>> tensor.new_zeros((2, 3))
tensor([[ 0.,  0.,  0.],
        [ 0.,  0.,  0.]], dtype=torch.float64)

2. Tensor的属性

2.1 tensor.shape

返回 tensor 的形状。

>>> import torch
>>> tensor=torch.randn((3,4))
>>> tensor.shape
torch.Size([3, 4])

2.2 tensor.dtype

返回 tensor 的数据类型。

>>> tensor.dtype
torch.float32

2.3 tensor.device

返回 tensor 存储的设备。

>>> tensor.device
device(type='cpu')

3. 在 GPU 上创建 tensor

2

一般情况下 tensors 默认是在 CPU 上创建的,如果想要在 GPU 上创建 tensor,有两种方式可选:

3.1 在 CPU 上创建后再复制到 GPU 上

>>> import torch
>>> cpu_tensor = torch.ones((2,2))
>>> cpu_tensor.device
device(type='cpu')

# 法一:利用 tensor.cuda()
>>> gpu_tensor = cpu_tensor.cuda()
>>> gpu_tensor.device
device(type='cuda', index=0)

# 法二:在确认 GPU 可用后,利用 tensor.to('cuda')
>>> gpu_tensor2 = cpu_tensor.to('cuda')
>>> gpu_tensor2.device
device(type='cuda', index=0)

3.2 使用 device 参数直接在 GPU 上创建:

>>> gpu_tensor = torch.ones((2,2), device='cuda')
>>> gpu_tensor.device
device(type='cuda', index=0)

实验证明跨设备复制 tensors 会非常的消耗时间与内存,所以~ 第二种方式速度会更快噢~ 这种方式使用的 RAM 更少,且不存在意外留下引用到CPU张量的参考的风险。

3.3 tensor.is_cuda

如果不清楚自己的 tensors 是存储在哪里,可以用 tensor.is_cuda 来判断:
3

# 接上面代码
>>> cpu_tensor.is_cuda
False
>>> gpu_tensor.is_cuda
True

4. Tensor 的运算

Pytorch 中有100多种 tensors 间的运算,包括 算术运算、线性代数运算、矩阵处理(如转置、索引、切片…)、采样等更复杂的运算,这些操作中的每一个都可以在GPU上运行(通常以比CPU更高的速度运行)。

操作列表链接

4
太多了也不能一一列举出来,就记录下几个常用的操作。

4.1 加法操作

x+y

>>> import torch
>>> x = torch.randint(0,10,(2,2))
>>> y = torch.randint(0,10,(2,2))
>>> x + y
tensor([[17,  9],
        [ 6,  6]])
torch.add(x, y)

torch.add(input, other, *, alpha=1, out=None):

out = input + alpha * other,这里的 other 可以是 tensor 或者数字,如果输入的类型为 Float Tensor 或 DoubleTensor,则 other 必须为实数,否则应为整数。

>>> torch.add(x,y)
tensor([[17,  9],
        [ 6,  6]])
       
>>> torch.add(x,2)
tensor([[10,  7],
        [ 6,  5]])

>>> torch.add(x,y,alpha=1)
tensor([[17,  9],
        [ 6,  6]])

>>> torch.add(x,2,alpha=1)
tensor([[10,  7],
        [ 6,  5]])
y.add_(x)

add_(other, *, alpha=1) → Tensor:

它是 torch.add() 的 in-place 版操作,这种操作会改变 tensor1 的值。

# 相当于将 x 的值加到 y 上,也就改变了 y 的值
# 但 x 的值不发生变换
# 如果操作为 x.add_(y)那么改变的就是 x 的值
# 因此这里要注意前后顺序

>>> y.add_(x)
tensor([[17,  9],
        [ 6,  6]])
>>> y
tensor([[17,  9],
        [ 6,  6]])
        
# 原本 x 的值
>>> x
tensor([[8, 5],
        [4, 3]])
# 将上述改变后的 y 加到 x 上
>>> x.add_(y)
tensor([[25, 14],
        [10,  9]])
# 可看到 x 发生了变化
>>> x
tensor([[25, 14],
        [10,  9]])

4.2 索引与切片

import torch

tensor = torch.ones(4, 4)
print('First row: ',tensor[0])
print('First column: ', tensor[:, 0])
print('Last column: ', tensor[..., -1])
tensor[:,1] = 0
print('Changed second colunm:', tensor)

"""
Out:
First row:  tensor([1., 1., 1., 1.])
First column:  tensor([1., 1., 1., 1.])
Last column: tensor([1., 1., 1., 1.])
Changed second colunm: tensor([[1., 0., 1., 1.],
        [1., 0., 1., 1.],
        [1., 0., 1., 1.],
        [1., 0., 1., 1.]])
"""

4.3 Tensor 拼接

上述两个操作均能将一系列 tensors 按照给定的维度拼接在一起,除拼接的维度之外要求被拼接的 tensors 具有相同的形状或者为空。

>>> import torch
>>> tensor = torch.randint(1,3,(2,2))
>>> tensor
tensor([[1, 2],
        [2, 1]])
# dim=1 表示拼接维度为 column
>>> tensor1 = torch.cat([tensor, tensor, tensor], dim=1)
>>> tensor1
tensor([[1, 2, 1, 2, 1, 2],
        [2, 1, 2, 1, 2, 1]])
>>> tensor2 = torch.cat([tensor, tensor, tensor], dim=0)
# dim=0 表示拼接维度为 row
>>> tensor2
tensor([[1, 2],
        [2, 1],
        [1, 2],
        [2, 1],
        [1, 2],
        [2, 1]])

4.4 单元素 Tensor

如果有一个单元素 tensor,则可以使用 tensor.item() 将其转换为 Python数值:

>>> import torch
>>> tensor = torch.randint(1,3,(2,2))
>>> tensor
tensor([[1, 2],
        [2, 1]])
>>> t = tensor.sum()
>>> t
tensor(6)
>>> t.item()
6

4.5 矩阵乘法

x @ x.T
>>> import torch
>>> x = torch.randint(1,3,(2,2))
>>> x
tensor([[2, 2],
        [1, 2]])
>>> y1 = x @ x.T
>>> y1
tensor([[8, 6],
        [6, 5]])
x.matmul(x.T)
>>> y2 = x.matmul(x.T)
>>> y2
tensor([[8, 6],
        [6, 5]])
torch.matmul(x, x.T)
>>> y3 = torch.matmul(x, x.T)
>>> y3
tensor([[8, 6],
        [6, 5]])

操作结果都是相同的。

4.6 element-wise product

x * x
>>> import torch
>>> x = torch.randint(1,3,(2,2))
>>> x
tensor([[2, 2],
        [1, 2]])
        
>>> z1 = x * x
>>> z1
tensor([[4, 4],
        [1, 4]])
x.mul(x)
>>> z2 = x.mul(x)
>>> z2
tensor([[4, 4],
        [1, 4]])
torch.mul(x, x)
>>> z3 = torch.mul(x, x)
>>> z3
tensor([[4, 4],
        [1, 4]])

5. Numpy 与 Tensor

CPU 上的 tensors 和NumPy 数组 可以共享其基础内存位置,更改一个将更改另一个。

  • tensor.numpy() 将 tensor 转换为 NumPy 数组:
>>> t = torch.ones(5)
>>> t
tensor([1., 1., 1., 1., 1.])
>>> n = t.numpy()
>>> n
array([1., 1., 1., 1., 1.], dtype=float32)
  • tensor 的变化会影响 NumPy 数组。
>>> t.add_(1)
tensor([2., 2., 2., 2., 2.])
>>> n
array([2., 2., 2., 2., 2.], dtype=float32)

6. 总结

关于 Pytorch 中 torch.Tensor 类还有很多知识点,一口吃不成大胖子啦,一步一个脚印的去学习会掌握的更好,冲鸭!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值