1.创建tensor
1.1 直接创建
直接根据数据创建:
x = torch.tensor(2,3) # 创建 2*3 的 tensor
x = torch.tensor([5.5, 3]) # 创建 tensor,值为[5.5, 3]
print(x)
# tensor([5.5000, 3.0000])
# 在制定 GPU 上创建与 data 一样的类型
torch.tensor(data, dtype=torch.float64, device=torch.device('cuda:0'))
1.2 Tensor和NumPy相互转换
numpy 创建 tensor
# 从 numpy 创建 tensor
torch.tensor(numpy_array)
torch.from_numpy(numpy_array)
tensor 转换numpy
# 将 tensor 转换为 numpy
numpy_array = pytensor2.numpy() # 在 cpu 上
numpy_array = pytensor2.cpu().numpy() # 在 gpu 上
Tensor 与 numpy 对象共享内存,所以他们之间切换很快,几乎不消耗资源。但是,这意味着如果其中一个变化了,则另一个也会跟着改变。
直接用
torch.tensor()
将NumPy数组转换成Tensor
,该方法总是会进行数据拷贝,返回的Tensor
和原来的数据不再共享内存。# 用torch.tensor()转换时不会共享内存 c = torch.tensor(a) a += 1 print(a, c) # [4. 4. 4. 4. 4.] tensor([3., 3., 3., 3., 3.], dtype=torch.float64)
1.3 拷贝创建
通过 clone 的方式进行创建:
b = a.clone()
1.4 创建特殊矩阵
x = torch.empty(5, 3) # 创建空的 Tensor
x = torch.ones(3,2) # 创建 1 矩阵
x = torch.zeros(2,3) # 创建 0 矩阵
x = torch.eye(2,3) # 创建单位矩阵
x = torch.arange(1,6,2) # 创建 [1, 6),间隔为 2
x = torch.linspace(1, 10, 3) # [1, 10] 等间距取 3 个数
x = torch.randn(2,3) # 随机矩阵
x = torch.randperm(5) # 长度为 5 的随机排列
通过现有的Tensor
来创建,此方法会默认重用输入Tensor
的一些属性,例如数据类型,除非是自定义数据类型。
x = x.new_ones(5, 3, dtype=torch.float64) # 返回的tensor默认具有相同的torch.dtype和torch.device
x = torch.randn_like(x, dtype=torch.float) # 指定新的数据类型
# tensor([[ 1.6973e+00, 1.8816e+00, 4.3511e-01],
# [ 1.8384e+00, -1.0594e+00, -1.5551e-03],
# [ 7.7326e-01, 3.3609e-02, 4.8899e-01],
# [ 6.7233e-01, -5.9922e-01, 9.3289e-01],
# [-3.5564e-01, -1.8505e-01, -6.8453e-01]])
2.tensor的属性
2.1 类型属性
通过如下代码查看 tensor
的类型:
x.type() # 类型
# <function Tensor.type>
pytorch
中的 tensor
支持如下类型:
数据类型 | CPU tensor | GPU Tensor |
---|---|---|
32 bit浮点 | torch.FloatTensor | torch.cuda.FloatTensor |
64bit浮点 | torch.DoubleTensor | torch.cuda.DoubleTensor |
16bit半精度浮点 | N/A | torch.cuda.HalfTensor |
8bit无符号整型 | torch.ByteTensor | torch.cuda.ByteTensor |
8bit 有符号整型 | torch.CharTensor | torch.cuda.CharTensor |
16bit有符号整型 | torch.ShortTensor | torch.cuda.ShortTensor |
32bit 有符号整型 | torch.IntTensor | torch.cuda.lntTensor |
64 bit有符号整型 | torch.LongTensor | torch.cuda.LongTensor |
其中,HalfTensor
是专门为 GPU
设计的,其占用的内存空间只有 CPU
下 FloatTensor
的一半。
2.2 尺度属性
查看 tensor
的相关尺寸:
x.shape # 尺寸,tuple
# torch.Size([5, 3])
x.size() # 尺寸,tuple 的 size 对象
# torch.Size([5, 3])
x.dim() # 维度
# 2
x.numel() # 所有元素个数
# 15
查看值
# 将一个标量Tensor转换成一个Python number
x[0, 0]
# tensor(1.6973)
x[0, 0].item()
# 1.6973174810409546
3.数据操作
tensor
的 API
与 Numpy
类似。
3.1 操作的类型
API 角度
从 Pytorch API
角度而言,对 tensor
的操作,可分为两类:
- torch.function:如
torch.save()
- tensor.function:如
tensor.save()
为方便使用,对 tensor
而言,大部分操作同时支持这两类接口。
存储角度
从存储角度讲,对 tensor
的操作又分为两类:
- 不修改自身,而是返回新的
tensor
:如a.add(b)
- 对自身进行修改,即 inplace 操作,如:
a.add_(b)
3.2 索引操作
索引出来的结果与原数据共享内存,也即修改一个,另一个会跟着修改。
a = t.randn(3,4)
b= a[:, 1]
# tensor([[-1.2908, 1.0193, 1.0039, 0.9335],
# [ 1.2542, -1.0350, -0.5729, -0.2693],
# [ 1.2768, -0.7739, -0.0743, -0.3614]])
# tensor([ 1.0193, -1.0350, -0.7739])
3.3 类型转换
各种类型之间可以转换,type(new_type) 是通用做法。而 CPU 和 GPU 之间通过 tensor.cuda 和 tensor.cpu 进行转换。
import torch
torch.set_default_tensor_type(torch.FloatTensor)
a = torch.tensor([1., 3])
print(a.dtype)
print(a.device)
# torch.float32
# cpu
3.4 沿指定维度操作
import torch
x = torch.randn(3,4)
print(x)
# 沿着行取最大值。返回 value 和 index
max_value, max_idx = torch.max(x, dim=1)
print(max_value, max_idx)
# 沿着行对x求和
sum_x = torch.sum(x, dim=1)
print(sum_x)
# tensor([[-0.8164, -1.6156, 1.8044, -0.0276],
# [-0.5526, 0.7886, -0.8338, -0.5740],
# [-2.0342, -0.6267, 0.2875, 1.2596]])
# tensor([1.8044, 0.7886, 1.2596]) tensor([2, 1, 3])
# tensor([-0.6551, -1.1718, -1.1139])
3.5 修改维数
import torch
x = torch.randn(3,4)
print(x.shape)
# 在指定维度增加
x = x.unsqueeze(0)
print(x.shape)
x = x.unsqueeze(1) # 在第二维增加
print(x.shape)
# 在指定维度减少
x = x.squeeze(0) # 减少第一维
print(x.shape)
x = x.squeeze()
print(x.shape)
# torch.Size([3, 4])
# torch.Size([1, 3, 4])
# torch.Size([1, 1, 3, 4])
# torch.Size([1, 3, 4])
# torch.Size([3, 4])
3.6 维度转置
import torch
x = torch.randn(3,4,5)
print(x.shape)
# 使用permute和transpose进行维度交换
x = x.permute(1,0,2)
print(x.shape)
# transpose交换tensor中的两个维度
x = x.transpose(0,2)
print(x.shape)
# torch.Size([3, 4, 5])
# torch.Size([4, 3, 5])
# torch.Size([5, 3, 4])
3.7 修改尺寸
常用的修改尺寸的方式有 tensor.view,tensor.unsqueeze(),以及 tensor.squeeze() 等。
import torch
# 使用 view 对 tensor 进行 reshape
x = torch.randn(3,4,5)
print(x.shape)
x = x.view(-1, 5)
# -1 表示任意的大小,5 表示第二维变成 5
print(x.shape)
# 重新 reshape 成 (3, 20) 的大小
x = x.view(3,20)
print(x.shape)
# torch.Size([3, 4, 5])
# torch.Size([12, 5])
# torch.Size([3, 20])
除此之外,还有另一种方式,即 resize。与 view 不同,它可以修改 tensor
的尺寸。如果新尺寸总尺寸超过原尺寸,则会自动分配新空间;如果小于,则之前的数据依旧会保留。
a = torch.arange(0, 6)
b = a.view(-1, 3) # [[0,1,2], [3,4,5]]
b.resize_(1, 3) # [0,1,2] 仍会保留截断的数据
b.resize_(3,3) # [[0, 1, 2], [3, 4, 5], [0, 0, 0]]
3.8 转换为列表
通过 tolist() 可以将 tensor
转换为 list,如下所示:
a.tolist()
3.9 其他操作
3.9.1 元素选择
函数 | 功能 |
---|---|
index_select(input, dim, index) | 在指定维度dim上选取 |
masked_select(input, mask) | 如:a[a>0],使用ByteTensor 进行选取 |
non_zero(input) | 非0元素下标 |
gather(input, dim, index) | 根据index,在dim维度上选取数据,输出size与index一致 |
例如:
a.masked_select(a > 1) # 等价于 a[a>1]
3.9.2 element-wise 操作
函数 | 功能 |
---|---|
abs/sqrt/div/exp/fmod/1og/pow... | 绝对值/平方根/除法/指数/求余/幂… |
cos/sin/asin/atan2/cosh | 三角函数 |
ceil/round/floor/trunc | 上取整/四舍五入/下取整/保留整数 |
clamp(input,min,max) | 截断为指定区间的值 |
sigmoid/tanh... | 激活函数 |
例如:
cosine_score = torch.clamp(cosine_score, -1, 1.0)
3.9.3 聚合操作
函数 | 功能 |
---|---|
mean/sum/meian/mode | 均值/和/中位数/众数 |
norm/dist | 范数/距离 |
std/var | 标准差/方差 |
cumsum/cumprod | 累加/累乘 |
以上大多数函数都有一个参数 dim,表示对指定维度进行聚合运算。
例如:
candidate_norm = torch.norm(candidate, dim=-1)
cosine_score = torch.sum(torch.multiply(query, candidate), dim=-1)
3.9.4 比较运算
函数 | 功能 |
---|---|
gt / lt / ge / le / eq / ne | 大于 / 小于 / 不小于 / 不大于 / 等于 / 不等 |
topk | 最大的k个数 |
sort | 排序 |
max / min | 比较两个tensor的最值 |
4.广播机制
x = torch.arange(1, 3).view(1, 2)
print(x)
y = torch.arange(1, 4).view(3, 1)
print(y)
print(x + y)
# tensor([[1, 2]])
# tensor([[1],
# [2],
# [3]])
# tensor([[2, 3],
# [3, 4],
# [4, 5]])
5.Tensor on GPU
if torch.cuda.is_available():
device = torch.device("cuda") # GPU
y = torch.ones_like(x, device=device) # 直接创建一个在GPU上的Tensor
x = x.to(device) # 等价于 .to("cuda")
z = x + y
print(z)
print(z.to("cpu", torch.double)) # to()还可以同时更改数据类型