1、在pytorch中,有以下9种张量类型
2、查看张量的基本信息
tensor=torch.randn(3,4,5)
print(tensor.size())
print(tensor.type())
print(tensor.dim())
torch.Size([3, 4, 5])
torch.FloatTensor
3
3、命名张量
张量命名是一个非常有用的方法,这样可以方便地使用维度的名字来做索引或其他操作,大大提高了可读性、易用性,防止出错。
# 在PyTorch 1.3之前,需要使用注释
# Tensor[N, C, H, W]
images = torch.randn(32, 3, 56, 56)
images.sum(dim=1)
images.select(dim=1, index=0)
# PyTorch 1.3之后
NCHW = [‘N’, ‘C’, ‘H’, ‘W’]
images = torch.randn(32, 3, 56, 56, names=NCHW)
images.sum('C').size()#按通道相加
torch.Size([32, 32, 32])
不过需要注意:1.4版本中该特性正在处于测试阶段,因此就不要随便的使用了。
#选择第0个通道
images.select('C',index=0).size()
torch.Size([32, 32, 32])
# 也可以这么设置
tensor = torch.rand(3,4,1,2,names=('C', 'N', 'H', 'W'))
# 使用align_to可以对维度方便地排序
tensor = tensor.align_to('N', 'C', 'H', 'W')
4、数据类型转换
# 设置默认类型,pytorch中的FloatTensor远远快于DoubleTensor
torch.set_default_tensor_type(torch.FloatTensor)
# 类型转换
tensor = tensor.cuda()
tensor = tensor.cpu()
tensor = tensor.float()
tensor = tensor.long()
5、tensor和numpy.ndarray转换
除了CharTensor,其他所有CPU上的张量都支持转换为numpy格式然后再转换回来。
ndarray = tensor.cpu().numpy()
tensor = torch.from_numpy(ndarray).float()
tensor = torch.from_numpy(ndarray.copy()).float() # If ndarray has negative stride.
6、tensor和PIL.Image转换
pytorch中的张量默认采用[N, C, H, W]的顺序,并且数据范围在[0,1],需要进行转置和规范化
PIL.Image转换为tensor
from PIL import Image
import numpy as np
image=r'/content/drive/My Drive/colab notebooks/image/test.jpg'
tensor=torch.from_numpy(np.asarray(Image.open(image))).permute(2,0,1).float()/255.0
tensor.size()
torch.Size([3, 300, 200])
另一种方式:
import torchvision
tensor=torchvision.transforms.functional.to_tensor(PIL.Image.open(path))
tensor.size()
torch.Size([3, 300, 200])
tensor转换为PIL.Image
img=Image.fromarray(torch.clamp(tensor*255,min=0,max=255).byte().permute(1,2,0).cpu().numpy())
print(type(img))
<class 'PIL.Image.Image'>
另一种方式:
image = torchvision.transforms.functional.to_pil_image(tensor)
7、np.ndarray和PIL.Image进行转换
np.ndarray转换为PIL.Image
image = PIL.Image.fromarray(ndarray.astype(np.uint8))
PIL.Image转换为np.ndarray
ndarray = np.asarray(PIL.Image.open(path))
8、从只包含一个元素的tensor中取出值
value = torch.rand(1)
print(value)
print(value.item())
tensor([0.2959])
0.2958560585975647
9、改变张量的形状
# 在将卷积层输入全连接层的情况下通常需要对张量做形变处理,
# 相比torch.view,torch.reshape可以自动处理输入张量不连续的情况。
tensor = torch.rand(2,3,4)
shape = (6, 4)
tensor = torch.reshape(tensor, shape)
10、打乱顺序
tensor = tensor[torch.randperm(tensor.size(0))] # 打乱第一个维度
11、水平翻转
# pytorch不支持tensor[::-1]这样的负步长操作,水平翻转可以通过张量索引实现
# 假设张量的维度为[N, C, H, W].
tensor = tensor[:,:,:,torch.arange(tensor.size(3) - 1, -1, -1).long()]
12、复制张量
# Operation | New/Shared memory | Still in computation graph |
tensor.clone() # | New | Yes |
tensor.detach() # | Shared | No |
tensor.detach.clone()() # | New | No |
13、张量拼接
'''
注意torch.cat和torch.stack的区别在于torch.cat沿着给定的维度拼接,
而torch.stack会新增一维。例如当参数是3个10x5的张量,torch.cat的结果是30x5的张量,
而torch.stack的结果是3x10x5的张量。
'''
tensor = torch.cat(list_of_tensors, dim=0)
tensor = torch.stack(list_of_tensors, dim=0)
t1=torch.randn(10,5)
t2=torch.randn(10,5)
t3=torch.randn(10,5)
s1=torch.cat([t1,t2,t3],dim=0)
s2=torch.stack([t1,t2,t3],dim=0)
print(s1.size())
print(s2.size())
torch.Size([30, 5])
torch.Size([3, 10, 5])
14、将整数标签转换为ont-hot码
tensor=torch.tensor([0,2,1,3])
N=tensor.size(0)
num_classes=4
one_hot=torch.zeros(N,num_classes).long()
one_hot.scatter_(dim=1, index=torch.unsqueeze(tensor, dim=1), src=torch.ones(N, num_classes).long())
tensor([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]])
15、得到非零元素
torch.nonzero(tensor) # index of non-zero elements
torch.nonzero(tensor==0) # index of zero elements
torch.nonzero(tensor).size(0) # number of non-zero elements
torch.nonzero(tensor == 0).size(0) # number of zero elements
16、判断两个张量相等
torch.allclose(tensor1, tensor2) # float tensor
torch.equal(tensor1, tensor2) # int tensor
17、张量扩展
# Expand tensor of shape 64*512 to shape 64*512*7*7.
tensor = torch.rand(64,512)
torch.reshape(tensor, (64, 512, 1, 1)).expand(64, 512, 7, 7).size()
torch.Size([64, 512, 7, 7])
18、矩阵乘法
# Matrix multiplcation: (m*n) * (n*p) * -> (m*p).
result = torch.mm(tensor1, tensor2)
# Batch matrix multiplication: (b*m*n) * (b*n*p) -> (b*m*p)
result = torch.bmm(tensor1, tensor2)
# Element-wise multiplication.
result = tensor1 * tensor2
19、计算两组数据之间的两两欧式距离
利用广播机制
dist = torch.sqrt(torch.sum((X1[:,None,:] - X2) ** 2, dim=2))