PyTorch入门 1 —— 张量的创建、属性与类型转换
PyTorch 简介与安装
简介
PyTorch 是一个开源的深度学习框架,由 Facebook 人工智能研究院(FAIR)在2017年1月基于 Torch 推出,广泛用于需要搭建训练深度神经网络的应用程序。它提供了两个高级功能:强大的GPU加速的张量计算;包含自动求导系统的深度神经网络。PyTorch 相当清晰简洁且高效快速,设计符合人类思维,让用户尽可能地专注于实现自己的想法,设计追求最少的封装,已经是使用最广泛的深度学习工具之一。并且,PyTorch 是 Python 化的,就像 NumPy 一样,这使得新手很容易上手,是入门深度学习的最佳选择。其官网是:https://pytorch.org/,有系统全面的教程、手册和帮助文档。
安装
与许多 Python 库的安装类似,PyTorch 库的安装也比较简单。根据 PyTorch 官网,对系统和安装方式等灵活选择即可,自动生成安装命令,运行该命令即可安装。笔者电脑无GPU,选择了CPU版的 1.13.0 版本,命令如下:pip install torch
。需要注意的是该 pytorch 库需要一个依赖包 typing-extensions 4.4.0,运行命令时会自动联网下载安装。安装完成后可以用如下方法查看:
import torch
print(torch.__version__) # 1.13.0+cpu (pytorch版本)
print(torch.cuda.is_available()) # False (机器是否有GPU)
张量
正如 NumPy 提供了 array 数组计算,PyTorch 为我们提供了一种数据类型,即张量(tensor),通常用来存储数字、向量、矩阵或数组并参与运算。本质上,PyTorch 中的张量就是元素为同一种数据类型的多维矩阵。在 PyTorch 中,张量以 “类” 的形式封装起来,对张量的一些运算、处理的方法被封装在类中。PyTorch 提供了多种多样操作它们的函数方法,使得用户使用非常方便灵活。包括本文在内,笔者将用一系列文章梳理这些函数和功能,首先就是介绍张量的创建及其属性、类型。
张量创建
- 根据指定数据创建张量:
torch.tensor(data, *, dtype, device, requires_grad=False, pin_memory=False)
data:指定数据,可以是数字、数值列表、numpy 数组(默认不共享内存)等。
dtype:指定张量数据类型,可以是 torch.int8、torch.int16 / torch.ShortTensor、torch.int32 / torch.int / torch.IntTensor、torch.int64 / torch.LongTensor、torch.float16、torch.float32 / torch.float / torch.FloatTensor、torch.float64 / torch.double / torch.DoubleTensor。
device:指定位置,若机器上有GPU可以设置为 ‘cuda’,若没有则默认 ‘cpu’。
requires_grad:布尔值,是否参与梯度计算。
pin_memory:布尔值,当内存充足的时候,可设为True。
torch.Tensor()
根据形状创建张量,也可创建指定数据的张量。torch.IntTensor()
、torch.FloatTensor()
、torch.DoubleTensor()
创建指定类型的张量。torch.arange(start=0, end, step=1, *)
和torch.linspace(start, end, steps, *)
创建线性张量。torch.randn(size, *)
和torch.randint(low=0, high, size, *)
创建随机张量,使用torch.random.initial_seed()
、torch.random.manual_seed(seed)
或torch.manual_seed(seed)
设置随机种子。torch.ones(size, *)
和torch.ones_like(input, *)
创建全1张量。torch.zeros(size, *)
和torch.zeros_like(input, *)
创建全0张量。torch.full(size, fill_value)
和torch.full_like(input, fill_value)
创建全为指定值张量。torch.fill(data, k)
、torch.fill_(data, k)
或data.fill_(k)
、data.fill_diagonal_(k)
、torch.masked_fill(data, p, v)
或data.masked_fill(p, v)
通过对已有张量data填充特定值创建。torch.from_numpy(ndarray)
从 numpy 数组创建张量,默认共享内存。torch.where(condiction, x, y)
或x.where(condiction, y)
从已有张量x中取出符合特定条件的值创建。torch.triu(data, diagonal=0)
或data.triu(diagonal=0)
创建上三角矩阵张量,参数 diagonal 控制0元素与非0元素分界线位置,下同。torch.tril(data, diagonal=0)
或data.tril(diagonal=0)
创建下三角矩阵张量。
示例如下:
import numpy as np
import torch
data = torch.tensor([[3.8, 0, 2], [-9, 12, 5]])
data = torch.Tensor(3) # tensor([1.4013e-45, 0.0000e+00, 2.3417e-29])
data = torch.Tensor([3.8, 0, 2]) # tensor([3.8000, 0.0000, 2.0000])
data = torch.IntTensor([3.8, 0.8, -2.9]) # tensor([ 3, 0, -2], dtype=torch.int32)
data = torch.DoubleTensor([3.8, 0.8, -2.9]) # tensor([ 3.8000, 0.8000, -2.9000], dtype=torch.float64)
data = torch.arange(-3, 4) # tensor([-3, -2, -1, 0, 1, 2, 3])
data = torch.arange(-3, 4, 2) # tensor([-3, -1, 1, 3])
data = torch.arange(-2.5, 1.2) # tensor([-2.5000, -1.5000, -0.5000, 0.5000])
data = torch.arange(-2.5, 1.2, 0.8) # tensor([-2.5000, -1.7000, -0.9000, -0.1000, 0.7000])
data = torch.linspace(0, 5, 3) # tensor([0.0000, 2.5000, 5.0000])
data = torch.linspace(0, 5, 6) # tensor([0., 1., 2., 3., 4., 5.])
data = torch.linspace(-5.2, 3.1, 4) # tensor([-5.2000, -2.4333, 0.3333, 3.1000])
torch.random.manual_seed(0) # <torch._C.Generator object at 0x000000000781CE90>
x = torch.randn(1, 3) # tensor([[-0.0809, 0.0513, -0.8688]])
y = torch.randint(0, 5, [1, 3]) # tensor([[4, 1, 2]])
data = torch.ones(1, 4) # tensor([[1., 1., 1., 1.]])
data = torch.ones_like(x) # tensor([[1., 1., 1.]]) 元素数据类型也相同
data = torch.zeros(1, 1, 3) # tensor([[[0., 0., 0.]]])
data = torch.zeros_like(y) # tensor([[0, 0, 0]]) 元素数据类型也相同
data = torch.full([1, 4], 0.3) # tensor([[0.3000, 0.3000, 0.3000, 0.3000]])
data = torch.full_like(x, 5) # tensor([[5., 5., 5.]]) 元素数据类型也相同
z = torch.fill(data, -8) # tensor([[-8., -8., -8.]])
torch.fill_(data, -3) # 张量 data 变为 tensor([[-3., -3., -3.]]),等价于 data.fill_(-3)
data.fill_diagonal_(7) # 张量 data “对角线元素”填充为7.0:tensor([[ 7., -3., -3.]])
data = torch.tensor([[ 7., -3., -3.], [2, 0, 0.8]])
pos = torch.tensor([1, 0, 1]) # 或者 pos = torch.tensor([True, False, True])
mf = torch.masked_fill(data, pos, 12) # 张量 data 指定位置pos上的值被填充为12:tensor([[12., -3., 12.], [12., 0., 12.]])
mf = torch.masked_fill(data, torch.tensor([[1], [0]]), 12) # tensor([[12.0000, 12.0000, 12.0000], [ 2.0000, 0.0000, 0.8000]])
mf = torch.masked_fill(data, data > 1, 10) # 把张量 data 中大于1的值用10填充代替。
arr = np.array([[3.4, 9, 12]])
t_arr = torch.from_numpy(ndarray) # tensor([[ 3.4000, 9.0000, 12.0000]], dtype=torch.float64)
data = torch.where(t_arr > 5, 0, 3) # tensor([[3, 0, 0]])
data = torch.where(t_arr > 5, t_arr, 3) # tensor([[ 3., 9., 12.]], dtype=torch.float64)
data = torch.randint(0, 5, [4, 7])
print(data)
print(torch.triu(data)) # 创建上三角矩阵张量,保留上三角(与对角线)元素且下三角全为0
print(torch.triu(data, 2)) # 0元素与非0元素分界线位置上移2个位置
print(torch.triu(data, -1)) # 0元素与非0元素分界线位置下移1个位置
print(torch.tril(data)) # 创建下三角矩阵张量,保留下三角(与对角线)元素且上三角全为0
print(torch.tril(data, 3)) # 0元素与非0元素分界线位置上移3个位置
print(torch.tril(data, -2)) # 0元素与非0元素分界线位置下移2个位置
张量的属性与类型转换
- 张量的属性一般有:形状、维数、数据类型、所在机器位置、是否参与梯度计算、梯度、数据等等。
- 张量类型转换
从上述张量创建第一种方法中可知,张量的类型分整型和浮点型,且两种都有不同的细分类型,不同类型之间可相互转换。张量同 numpy 数组亦可相互转换,需要注意的是:
- 使用 data.numpy() 将张量 data 转换为数组要求该张量的 requires_grad=False,并且会共享内存,可使用 copy 函数避免共享。
- 使用 torch.from_numpy(arr) 将数组转换为张量也会共享内存,可使用 copy 函数避免共享。
- 使用 torch.tensor(arr) 将数组转换为张量默认不共享内存。
- 对于只有一个元素的张量,使用 item 方法可将该值从张量中提取出来。
示例如下:
import torch
data1 = torch.tensor([[3.8, 0, 2], [-9, 12, 5]])
print(data1)
print(data1.shape) # 张量形状:torch.Size([2, 3])
print(data1.size()) # 同上
print(data1.dim()) # 张量维数:2
print(data1.dtype) # 张量数据类型:torch.float32
print(data1.type()) # 同上:torch.FloatTensor
print(data1.device) # 张量所在机器位置:cpu
print(data1.requires_grad) # 张量是否参与梯度计算:False
print(data1.grad) # 张量梯度:None
print(data1.data) # 张量数据:与张量本身相同
data2 = torch.full([3, 4], 7) # 3行4列元素为7的张量
print(data2)
print(data2.dtype) # torch.int64
# 将 data2 元素类型转换为 float64 类型
data2 = data2.type(torch.DoubleTensor) # 或者 data2 = data2.double()
# 转换为其他类型
data2 = data2.type(torch.ShortTensor) # 或者 data2 = data2.short()
data2 = data2.type(torch.IntTensor) # 或者 data2 = data2.int()
data2 = data2.type(torch.LongTensor) # 或者 data2 = data2.long()
data2 = data2.type(torch.FloatTensor) # 或者 data2 = data2.float()
data2 = data2.type_as(data1) # 将张量 data2 转换成与张量 data1 相同的类型
arr = data2.numpy() # 将张量 data2 转换成 numpy 数组
data3 = torch.tensor([[[35]]])
print(data3.item()) # 35
以上。