import torch
import torch.nn as nn
import torchvision
print(torch.__version__)
print(torch.version.cuda)
print(torch.backends.cudnn.version())
print(torch.cuda.get_device_name(0)) # GPUtype
在硬件设备(CPU、GPU)不同时,完全的可复现性无法保证,即使随机种子相同。但在同一个设备上,程序开始的时候固定torch的随机种子,固定numpy的随机种子,可以保证在同一个设备上的可复现性。
np.random.seed(0)
torch.manual_seed(0) # 固定随机种子
torch.cuda.manual_seed_all(0)
是否有CUDA支持
torch.cuda.is_available()
设置为cuDNN benchmark模式,提升计算速度,但是由于计算中的随机性,每次网络前馈结果略有差异。
torch.backends.cudnn.benchmark = True
如果想要避免这种结果波动
torch.backends.cudnn.deterministic = Ture
只需要一张显卡
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
指定多张显卡
import os
os.environ['CUDA_VISIBLE_DEVICES']='0,1'
或者在运行代码时设置显卡:
CUDA_VISIBLE_DEVICES=0,1 python train.py
清除GPU存储,在PyTorch内部使用
torch.cuda.empty_cache()
也可以在命令行重置GPU指令
nvidia-smi --gpu-reset -i [gpu_id]
或者在命令行使用ps找到程序的PID,再使用kill结束进程
ps aux | grep python
kill -9 [pid]
多gpu训练,必须有编号为device:0的gpu,不然会报错。AssertionError: Invalid device id。
torch.nn.DataParallel(model, device_ids=[0, 1])
如果编号为device:0的设备被占用,指定使用5,6,7卡时,需要修改torch默认编号5为0
os.environ["CUDA_VISIBLE_DEVICES"] = "5,6,7"
model = torch.nn.DataParallel(model, device_ids=[0,1,2])
基本信息
tensor = torch.randn(3,4,5) # 随机初始化
tensor = torch.tensor([2., 3.3], [1., 2.3]) # 初始化
print(tensor.type())
print(tensor.size())
print(tensor.dim())
命名张量(PyTorch 1.3之后)
images = torch.randn(2,3,56,56,names=('C','N','H','W'))
tensor = tensor.align_to('N','C','H','W') # channel, height, weight
张量形变
a = torch.arange(0, 6)
b = a.view(-1, 3) # 元素数需要相同
c = a.resize_(1,6) # 元素数可以不同
打乱顺序
tensor = tensor[torch.randperm(tensor.size(0))]
水平翻转
# pytorch不支持tensor[::-1]这样的负步长操作
tensor = torch.randn(2,3,4)
tensor = tensor[:,:,torch.arange(tensor.size(2)-1, -1).long()]
维度变换
tensor.unsqueeze(0) # 在最前面添加一个维度
tensor.randn(1, 32, 1, 1)
tensor.expand(4, 32, 14, -1) # expand只能够将1扩展为N,如果写-1就是不变,结果为[4,32,14,1]
tensor.expand(1, 32, 1, 1)
tensor.repeat(4, 32, 1, 1) #repeat是重复次数,结果为[4, 1024, 1, 1]
tensor.randn(3,4)
tensor.t() # 转置,只适用于2D
tensor.transpose(1,2) # 将第2和第3个维度交换,只能交换两个维度
tensor.permute(1,2,0) # 交换多个维度
张量拼接 拆分
a = torch.randn(1,2)
b = torch.randn(1,2)
c = torch.cat([a,b], dim=0) # c:[2,2]
d = torch.stack([a,b], dim=0) # d:[2,1,2]
a = torch.randn(32, 2)
b, c = torch.split([16,16], dim=0) # 拆成16和16
b, c =torch.split(16, dim=0) # 每份16, 按长度
b, c = torch.chunk(2, dim=0) # 拆成2份, 按数量
非零元素 零元素
torch.nonzero(tensor)
torch.nonzero(tensor == 0)
判断相等
torch.allclose(tensor1, tensor2) # float
torch.equal(tensor1, tensor2) # int
torch.set_default_tensor_type(torch.FloatTensor) # FloatTensor远远快于DoubleTensor
tensor = tensor.cuda()
tensor = tensor.cpu()
tensor = tensor.float()
tensor = tensor.long()
torch -> list
list(tensor.shape)
torch.Tensor <=> np.ndarray
ndarray = tensor.cpu().numpy()
ndarray = np.array([2, 3.3]) # 直接定义ndarray
tensor=torch.from_numpy(ndarray).float()
torch.Tensor <=> PIL.Image
image = PIL.Image.fromarray(torch.clamp(tensor*255, min=0, max=255).byte().permute(1,2,0).cpu().numpy())
image = torchvision.transforms.functional.to_pil_image(tensor) # 效果相同
path = r'./figure.jpg'
tensor = torch.from_numpy(np.asarray(PIL.Image.open(path))).permute(2,0,1).float() / 255
tensor = torchvision.transforms.functional.to_tensor(PIL.Image.open(path)) # 效果相同
tensor = torchvision.transforms.ToTensor(tensor) # 亲测有效
np.ndarray <=> PIL.Image
image = PIL.Image.fromarray(ndarray.astype(np.uint8))
ndarray = np.asarray(PIL.Image.open(path))
从只有一个元素的张量中提取数值
value = torch.rand(1).item()