转载自 [深度学习框架]PyTorch常用代码段
1. 基本配置 导入包和版本查询 1 2 3 4 5 6 7 import torchimport torch.nn as nnimport torchvisionprint(torch.__version__) print(torch.version.cuda) print(torch.backends.cudnn.version()) print(torch.cuda.get_device_name(0 ))
可复现性 - 随机种子 在硬件设备(CPU、GPU)不同时,完全的可复现性无法保证,即使随机种子相同。但是,在同一个设备上,应该保证可复现性。具体做法是,在程序开始的时候固定torch的随机种子,同时也把numpy的随机种子固定。1 2 3 4 5 6 np.random.seed(0 ) torch.manual_seed(0 ) torch.cuda.manual_seed_all(0 ) torch.backends.cudnn.deterministic = True torch.backends.cudnn.benchmark = False
显卡设置 如果只需要一张显卡1 2 device = torch.device('cuda' if torch.cuda.is_available() else 'cpu' )
如果需要指定多张显卡,比如0,1号显卡。1 2 import osos.environ['CUDA_VISIBLE_DEVICES' ] = '0,1'
也可以在命令行运行代码时设置显卡:1 CUDA_VISIBLE_DEVICES=0,1 python train.py
清除显存 1 torch.cuda.empty_cache()
也可以使用在命令行重置GPU的指令1 nvidia-smi --gpu-reset -i [gpu_id]
2. 张量(Tensor)处理 张量的数据类型 PyTorch有9种CPU张量类型和9种GPU张量类型。
张量基本信息 1 2 3 4 tensor = torch.randn(3 ,4 ,5 ) print(tensor.type()) print(tensor.size()) print(tensor.dim())
命名张量 张量命名是一个非常有用的方法,这样可以方便地使用维度的名字来做索引或其他操作,大大提高了可读性、易用性,防止出错。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 images = torch.randn(32 , 3 , 56 , 56 ) images.sum(dim=1 ) images.select(dim=1 , index=0 ) NCHW = [‘N’, ‘C’, ‘H’, ‘W’] images = torch.randn(32 , 3 , 56 , 56 , names=NCHW) images.sum('C' ) images.select('C' , index=0 ) tensor = torch.rand(3 ,4 ,1 ,2 ,names=('C' , 'N' , 'H' , 'W' )) tensor = tensor.align_to('N' , 'C' , 'H' , 'W' )
数据类型转换 1 2 3 4 5 6 7 8 torch.set_default_tensor_type(torch.FloatTensor) tensor = tensor.cuda() tensor = tensor.cpu() tensor = tensor.float() tensor = tensor.long()
torch.Tensor与np.ndarray转换 除了CharTensor,其他所有CPU上的张量都支持转换为numpy格式然后再转换回来。1 2 3 ndarray = tensor.cpu().numpy() tensor = torch.from_numpy(ndarray).float() tensor = torch.from_numpy(ndarray.copy()).float()
Torch.tensor与PIL.Image转换 1 2 3 4 5 6 7 8 9 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))
np.ndarray与PIL.Image的转换 1 2 3 image = PIL.Image.fromarray(ndarray.astype(np.uint8)) ndarray = np.asarray(PIL.Image.open(path))
从只包含一个元素的张量中提取值 1 value = torch.rand(1 ).item()
张量形变 1 2 3 4 5 tensor = torch.rand(2 ,3 ,4 ) shape = (6 , 4 ) tensor = torch.reshape(tensor, shape)
打乱顺序 1 tensor = tensor[torch.randperm(tensor.size(0 ))]
水平翻转 1 2 3 tensor = tensor[:,:,:,torch.arange(tensor.size(3 ) - 1 , -1 , -1 ).long()]
复制张量 1 2 3 4 tensor.clone() tensor.detach() tensor.detach.clone()()
张量拼接 1 2 3 4 5 6 7 ''' 注意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 )
将整数标签转为one-hot编码 1 2 3 4 5 6 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())
得到非零元素 1 2 3 4 torch.nonzero(tensor) torch.nonzero(tensor==0 ) torch.nonzero(tensor).size(0 ) torch.nonzero(tensor == 0 ).size(0 )
判断两个张量相等 1 2 torch.allclose(tensor1, tensor2) torch.equal(tensor1, tensor2)
张量扩展 1 2 3 tensor = torch.rand(64 ,512 ) torch.reshape(tensor, (64 , 512 , 1 , 1 )).expand(64 , 512 , 7 , 7 )
矩阵乘法 1 2 3 4 5 6 7 8 result = torch.mm(tensor1, tensor2) result = torch.bmm(tensor1, tensor2) result = tensor1 * tensor2
计算两组数据之间的两两欧式距离 利用broadcast机制1 dist = torch.sqrt(torch.sum((X1[:,None ,:] - X2) ** 2 , dim=2 ))
3. 模型定义和操作 一个简单两层卷积网络的示例