Pytorch使用笔记

记录&总结一下自己写model时需要用到的函数。官方文档
pytorch-lightning
torchvision

nn.Module

CNN

torch.nn.Conv1d

torch.nn.Conv1d(in_channels, #int 输入信号的通道
				out_channels, # int 卷积产生的通道
				kernel_size, # int/tuple 卷积核的尺寸
				stride=1, #int/tuple, opt卷积步长
				padding=0, #int/tuple, opt 输入的每一条边补充0的层数
				dilation=1, #int/tuple, opt 卷积核元素之间的间距
				groups=1, #int, opt 从输入通道到输出通道的阻塞连接数
				bias=True # bool, opt 如果bias=True,添加偏置)

shape
输入: ( N , C i n , L i n ) (N,C_{in},L_{in}) (N,Cin,Lin)
weight: ( C o u t , C i n , k _ s ) (C_{out}, C_{in}, k\_s) (Cout,Cin,k_s) Cout个卷积核并行运算
输出: ( N , C o u t , L o u t ) (N,C_{out},L_{out}) (N,Cout,Lout)
L o u t = [ L i n + 2 p − d ( k _ s − 1 ) − 1 ] / s + 1 L_{out}=[L_{in}+2p-d(k\_s-1)-1]/s+1 Lout=[Lin+2pd(k_s1)1]/s+1
con1d的输入输出的计算方式
Example

# [1,5,7] 卷积核[2,5,3] = [1, 3, 6]
a = torch.ones(1,5,7)
b = nn.Conv1d(in_channels=5, out_channels=3, kernel_size=2)(a)
print(b.size()) #torch.Size([1, 3, 6])

在这里插入图片描述

torch.nn.Conv2d

torch.nn.Conv2d(in_channels, 
				out_channels, 
				kernel_size, 
				stride=1, 
				padding=0, 
				dilation=1, 
				groups=1, 
				bias=True)

参数kernel_sizestride,paddingdilation

  1. 可以是一个int的数据,此时卷积height和width值相同;
  2. 可以是一个tuple数组,tuple的第一维度表示height的数值,tuple的第二维度表示width的数值

shape
输入: ( N , C i n , H i n , W i n ) (N, C_{in}, H_{in}, W_{in}) (N,Cin,Hin,Win)
weight: ( C o u t , C i n , k _ s ) (C_{out}, C_{in}, k\_s) (Cout,Cin,k_s)
输出: ( N , C o u t , H o u t , W o u t ) (N, C_{out}, H_{out}, W_{out}) (N,Cout,Hout,Wout)
H o u t = [ H i n + 2 p [ 0 ] − d [ 0 ] ( k _ s [ 0 ] − 1 ) − 1 ] / s [ 0 ] + 1 W o u t = [ W i n + 2 p [ 1 ] − d [ 1 ] ( k _ s [ 1 ] − 1 ) − 1 ] / s [ 1 ] + 1 H_{out}=[H_{in}+2p[0]-d[0](k\_s[0]-1)-1]/s[0]+1 \\ W_{out}=[W_{in}+2p[1]-d[1](k\_s[1]-1)-1]/s[1]+1 Hout=[Hin+2p[0]d[0](k_s[0]1)1]/s[0]+1Wout=[Win+2p[1]d[1](k_s[1]1)1]/s[1]+1
请添加图片描述

torch.nn.ConvTranspose1d

1维的解卷积操作(transposed convolution operator,注意改视作操作可视作解卷积操作,但并不是真正的解卷积操作
注意
由于内核的大小,输入的最后的一些列的数据可能会丢失。因为输入和输出是不是完全的互相关。因此,用户可以进行适当的填充(padding操作)。

torch.nn.ConvTranspose1d(in_channels, 
						out_channels, 
						kernel_size, 
						stride=1, 
						padding=0, #输入的每一条边补充0的层数
						output_padding=0, #输出的每一条边补充0的层数
						groups=1, 
						bias=True)

shape
输入: ( N , C i n , L i n ) (N,C_{in},L_{in}) (N,Cin,Lin)
输出: ( N , C o u t , L o u t ) (N,C_{out},L_{out}) (N,Cout,Lout)
L o u t = ( L i n − 1 ) s − 2 p + k _ s + o _ p L_{out}=(L_{in}-1)s-2p+k\_s+o\_p Lout=(Lin1)s2p+k_s+o_p

变量

  • weight(tensor) - 卷积的权重,大小是(in_channels, in_channels,kernel_size)
  • bias(tensor) - 卷积的偏置系数,大小是(out_channel)

RNN

LSTM

self.rnn = nn.LSTM(self.ninput, self.nhidden,
             self.nlayers, batch_first=True,
             dropout=self.drop_prob, bidirectional=self.bidirectional)

self.register_buffer()

回顾模型保存:torch.save(model.state_dict())model.state_dict()是一个字典,里边存着我们模型各个部分的参数。
在model中,我们需要更新其中的参数,训练结束将参数保存下来。但在某些时候,我们可能希望模型中的某些参数参数不更新(从开始到结束均保持不变),但又希望参数保存下来model.state_dict() ),这是我们就会用到 register_buffer()
参考网址

Loss

BCELoss

torch.nn.BCELoss(weight=None, size_average=True)

计算了输出与target之间的二进制交叉熵
l o s s ( o , t ) = − 1 n ∑ i [ t [ i ] l o g ( o [ i ] ) + ( 1 − t [ i ] ) l o g ( 1 − o [ i ] ) ] loss(o,t)=-\frac{1}{n}\sum_i[t[i] log(o[i])+(1-t[i]) log(1-o[i])] loss(o,t)=n1i[t[i]log(o[i])+(1t[i])log(1o[i])] 如果weight被指定 : l o s s ( o , t ) = − 1 n ∑ i w e i g h t s [ i ] ( t [ i ] l o g ( o [ i ] ) + ( 1 − t [ i ] ) ∗ l o g ( 1 − o [ i ] ) ) loss(o,t)=-\frac{1}{n}\sum_iweights[i] (t[i] log(o[i])+(1-t[i])* log(1-o[i])) loss(o,t)=n1iweights[i](t[i]log(o[i])+(1t[i])log(1o[i]))
这个用于计算 auto-encoder 的 reconstruction error。注意 0<=target[i]<=1。

默认情况下,loss会基于element平均,如果size_average=False的话,loss会被累加。

torch

torch

请添加图片描述
.cuda()
cuda放到了gpu上,CPU和GPU的tensor不能直接想加,会报错

gpu

设置gpu
#第一种写法(更推荐)
import os
os.environ[“CUDA_VISIBLE_DEVICES”] = “2”
#第二种写法pytorch
import torch
torch.cuda.set_device(id)

打印当前gpu

其他数据类型转化为torch

numpy->torch

>>> a=np.ones(5)
>>> b=torch.from_numpy(a)

torch->numpy

>>> a = torch.ones(5)
>>> b=a.numpy()

参考:
https://zhuanlan.zhihu.com/p/55419865

torch维度形状变换

开始改模型代码的时候发现模型里的torch有很多维度变换,不熟悉这些函数或者不认真看的话就数据维度就会乱七八糟,自己改的模型很容易跑不起来(在这里反省一下我本科居然读的还是软件工程,真的好不专业TAT)

1.repeat()

参数的个数,不能少于被操作的张量的维度的个数

>>> a = torch.randn(33, 55)
>>> a.size()
torch.Size([33, 55])
>>> a.repeat(1,2).size()     # 原始值:torch.Size([33, 55])
torch.Size([33, 110])
>>> a.repeat(1,1,2).size()   # 原始值:torch.Size([33, 55])
torch.Size([1, 33, 110])
>>> a.repeat(1,1,1,1).size() # 原始值:torch.Size([33, 55])
torch.Size([1, 1, 33, 55])

2.transpose()和permute()

transpose()交换指定的两个维度的内容

>>>a = torch.tensor([[[1, 2, 3, 4], [4, 5, 6, 7]], [[7, 8, 9, 10], [10, 11, 12, 13]], [[13, 14, 15, 16], [17, 18, 19, 20]]])
>>>print(a, a.shape)
tensor([[[ 1,  2,  3,  4],[ 4,  5,  6,  7]],
       	[[ 7,  8,  9, 10],[10, 11, 12, 13]],
       	[[13, 14, 15, 16],[17, 18, 19, 20]]])
torch.Size([3, 2, 4])
>>>b = a.transpose(1,2)
>>>print(b, b.shape)
tensor([[[ 1,  4],
        [ 2,  5],
        [ 3,  6],
        [ 4,  7]],
       [[ 7, 10],
        [ 8, 11],
        [ 9, 12],
        [10, 13]],
       [[13, 17],
        [14, 18],
        [15, 19],
        [16, 20]]])
torch.Size([3, 4, 2])

permute()可以一次性交换多个维度

>>>c = a.permute(2, 1, 0)
>>>print(c, c.shape)
tensor([[[ 1,  7, 13],
         [ 4, 10, 17]],
        [[ 2,  8, 14],
         [ 5, 11, 18]],
        [[ 3,  9, 15],
         [ 6, 12, 19]],
        [[ 4, 10, 16],
         [ 7, 13, 20]]]) torch.Size([4, 2, 3])

3.view()

把原先tensor中的数据按照行优先的顺序排成一个一维的数据(地址是连续存储的),然后按照参数组合成其他形状的tensor。(相当于tensorflow里边的reshape)
参数不可为空,参数中的-1就代表这个位置由其他位置的数字来推断,不允许同时有两个-1。
view()不影响传入的tensor

>>> a=torch.Tensor([[[1,2,3],[4,5,6]]])
>>> print(a.view(3,2))
tensor([[1., 2.],
        [3., 4.],
        [5., 6.]])

4.squeeze()和unsqueeze()

torch.squeeze()用于对数据的维度进行压缩,去掉维数为1的的维度。squeeze(a)就是将a中所有为1的维度删掉,不为1的维度没有影响。a.squeeze(N) 和 b=torch.squeeze(a,N) 就是去掉a中指定的维数为一的维度。
torch.unsqueeze()用于对数据维度进行扩充,给指定位置加上维数为一的维度。a.squeeze(N) 和 b=torch.squeeze(a,N) 就是在a中指定位置N加上一个维数为1的维度。

torch分布

  • 均匀分布
    torch.rand(*sizes, out=None) → Tensor
    返回一个张量,包含了从区间[0, 1)的均匀分布中抽取的一组随机数。张量的形状由参数sizes定义。
    参数:
    • sizes (int…) - 整数序列,定义了输出张量的形状
    • out (Tensor, optinal) - 结果张量

torch.bmm

用来计算两个tensor之间乘积(两个tensor必须都是三维的
维度有限制,要求啊a,b两个tensor有如下格式:
a: ( z , x , y ) (z,x,y) (z,x,y)
b: ( z , y , c ) (z,y,c) (z,y,c)
则result = torch.bmm(a,b),维度为: ( z , x , c ) (z,x,c) (z,x,c)

torchvision

Pytorch计算机视觉工具包,包含三大模块
torchvision.transforms: 常用的图像预处理方法

• 数据中心化\quad• 数据标准\quad• 缩放 \quad• 裁剪
• 旋转\quad• 翻转\quad• 填充 \quad• 噪声添加
• 灰度变换\quad• 线性变换\quad• 仿射变换\quad• 亮度、饱和度及对比度变换

torchvision.datasets: 常用数据集的dataset实现,MNIST,CIFAR-10,ImageNet等
torchvision.models : 常用的模型预训练,AlexNet,VGG, ResNet,GoogLeNet等
参考:torchvision / torchvision官方文档

torchvision.transforms

self.norm = transforms.Compose([
            transforms.ToTensor(),
            transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
image_transform = transforms.Compose([
        transforms.Scale(int(imsize * 76 / 64)),
        transforms.RandomCrop(imsize),
        transforms.RandomHorizontalFlip()])     
1 数据标准化—transforms.Normalize

transforms.Normalize(mean,std,inplace=False)

功能:逐channel的对图像进行标准化
o u t p u t = i n p u t − m e a n s t d output =\frac{input-mean}{std} output=stdinputmean

• mean:各通道的均值
• std:各通道的标准差
• inplace:是否原地操作

2 transforms.ToTensor

transforms.ToTensor()
将shape为(H, W, C)的nump.ndarrayimg转为shape为(C, H, W)的tensor,其将每一个数值归一化到[0,1],其归一化方法比较简单,直接除以255即可。

3 transforms.Scale / transforms.Resize

transforms.Resize(size[, interpolation, max_size, …])
用于对载入的图片数据按需求的大小进行缩放。
size可以是一个整形数据,也可以是一个类似于(h,w)的序列,其中,h代表高度,w代表宽度,但是如果使用的是一个整形数据,那么代表缩放的宽度和高度都是这个整形数据的值。
transforms.Scale()
用于对载入的图片数据按需求进行缩放,和torchvision.transforms.Resize()用法类似。

4 transforms.RandomCrop()

transforms.RandomCrop(size, padding=None, pad_if_needed=False, fill=0, padding_mode='constant')
Crop the given image at a random location.

5 transforms.RandomHorizontalFlip()

transforms.RandomHorizontalFlip(p=0.5)
Horizontally flip the given image randomly with a given probability.

torchvision.models

models

1 inception_v3
model = models.inception_v3()
url = 'https://download.pytorch.org/models/inception_v3_google-1a9a5a14.pth'
model.load_state_dict(model_zoo.load_url(url))
for param in model.parameters():
	param.requires_grad = False
2 VisionTransformer: vit_h_14

ViT_H_14_Weights.IMAGENET1K_SWAG_E2E_V1
Acc@1 88.552
Acc@5 98.694
633.5M

PyTorch Lightning

可以理解为keras之于tensorflow
为了让用户能够脱离PyTorch一些繁琐的细节,专注于核心代码的构建,提供了许多实用工具,可以让实验更加高效
PyTorch Lightning 官方文档
参考教程
PyTorch Lightning初步教程(下) - 知乎
Lightning将大部分AI相关代码分为三个部分:

  • 研究代码,主要是模型的结构、训练等部分。被抽象为LightningModule类
    研究代码可划分为以下几个组件:

    • 模型
    • 数据处理
    • 损失函数
    • 优化器
  • 工程代码,这部分代码重复性强,比如16位精度,分布式训练。被抽象为Trainer类

  • 非必要代码,这部分代码和实验没有直接关系,不加也可以,加上可以辅助,比如梯度检查,log输出等。被抽象为Callbacks类

main函数

import pytorch_lightning as pl
pl.seed_everything(1234) # 这个是用于固定seed用
# args
parser = ArgumentParser()
parser = pl.Trainer.add_argparse_args(parser)
parser = LitClassifier.add_model_specific_args(parser)
parser = MNISTDataModule.add_argparse_args(parser)
args = parser.parse_args()
 
# data
dm = MNISTDataModule.from_argparse_args(args)
 
# model
model = LitClassifier(args.hidden_dim, args.learning_rate)
 
# training
trainer = pl.Trainer.from_argparse_args(args)
trainer.fit(model, datamodule=dm)
 
result = trainer.test(model, datamodule=dm)
pprint(result)

Trainer

parser = Trainer.add_argparse_args(parser) 将所有可用的trainer选项添加到argparse

其他

torch.backends.cudnn.benchmark

GPU 相关的 flag:在一般场景下,只要简单地在 PyTorch 程序开头将其值设置为 True,就可以大大提升卷积神经网络的运行速度。

  • 具体功能:在 PyTorch 中对模型里的卷积层进行预先的优化,也就是在每一个卷积层中测试 cuDNN 提供的所有卷积实现算法,然后选择最快的那个。
  • 不能用的场景:如果我们的网络模型一直变的话,那肯定是不能设置 cudnn.benchmark=True 的。因为网络结构经常变,每次 PyTorch 都会自动来根据新的卷积场景做优化:这次花费了半天选出最合适的算法出来,结果下次你结构又变了,之前就白做优化了。不仅如此,还得要根据这个新的结构继续做选择最高效的算法组合,又花费不少的时间。这样反而会大大降低效率。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值