pytorch
pytorch基础
Tensor(张量)
pytorch中最基本的操作对象,表示的是一个多维的矩阵
pytorch可以在GPU上运行,numpy的ndarry只能在CPU上运行
Tensor数据类型:
32位浮点型: torch.FloatTensor
64位浮点型:torch.DoubleTensor
16位整形:torch.ShoutTensor
32位整形:torch.IntTensor
64位整形:torch.LongTensor
定义一个三行两列矩阵:
a = torch.Tensor([2,3][4,5][6,7])
torch.Tensor默认为torch.FloatTensor
Variable(变量)
Variable Tensor 本质上没有区别,不过 Variable 会被放入个计算图中,然后进行前向传播,反向传播,自动求导
Variable 是在 torch.autograd.Variable 中
Variable有三个较重要的组成属性:
data 取出Variable中的tensor数值
grad 这个Variable传播梯度
grad_fn 表示得到这个Variable的操作,比如通过加减还是乘除来得到的
dataset(数据集)
定义数据类
from torch.utils.data import Dataset
import os
from PIL import Image
class my_dateset(Dataset):
def __init__(self,root_dir,label_dir):
self.root_dir = root_dir
self.label_dir = label_dir
self.path = os.path.join(self.root_dir,self.label_dir)
self.img_path = os.listdir(self.path)
def __getitem__(self, idx):
img_name = self.img_path[idx]
img_item_path = os.path.join(self.root_dir,self.label_dir,img_name)
img = Image.open(img_item_path)
label = self.label_dir
return img,label
def __len__(self):
return len(self.img_path)
pytorch提供torch.utils.data.DataLoader 来定义一个新的迭代器
dataiter = DataLoader(my_dataset, batch_size=32, shuffle=True, collate_fn=default_collate)
collate_fn 是表示如何取样本的
torchvision中有一个关于计算机视觉的数据读取类ImageFolder主要功能是处理图片,且要求图片是下面这种存放形式
root/dog/xxx.png
root/dog/xxy.png
root/dog/xxz.png
root/cat/123.png
root/cat/asd.png
root/cat/zxc.png
之后这样来调用这个类:
dset = ImageFolder(root='root_path', transform=None, loader=default_loader)
nn.Module (模组)
PyTorch 里面编写神经网络,所有的层结构和损失函数都来自于 torch.nn
class net_name(nn.Module):
def __init__(self, other_argi ments):
super(net_name, self) .__init__
self.convl = nn .Conv2d(in channels, out channels, kernel size)
# other network layer
def forward(self, x) :
x = self. convl (x)
return x
相当于建立了一个计算图,并且这个结构可以复用多次,每次调用就相当于用该计算图定义的相同参数做一次前向传播
torch.optim (优化)
一阶优化算法
![](C:\Users\wyx\Pictures\Screenshots\屏幕截图 2024-04-18 155241.png)
最常用的一阶优化算法是梯度下降
二阶优化算法
二阶优化算法使用了二阶导数( 也叫做 Hessian 方法)来最小化或最大化损失函数
模型的保存与加载
PyTorch 里面使用 torch.save 来保存模型的结构和参数,有两种保存方式:
(1)保存整个模型的结构信息和参数信息,保存的对象是模型 model;
(2)保存模型的参数,保存的对象是模型的状态 model.state diet ()
可以这样保存, save 的第一个参数是保存对象,第二个参数是保存路径及名称:
torch.save(model ,’./model.pth ’)
torch.save(model.state_dict(), './model_state . pth ’)
加载模型有两种方式对应于保存模型的方式:
(1)加载完整的模型结构和参数信息,使用
load model = torch.load (’ model. pth ')
在网络较大的时候加载的时间比较长,同时存储空间也比较大;
(2)加载模型参数信息,需要先导人模型的结构,然后通过
model.load_state_die (torch.load( 'model_state pth '))来导人
pytorch核心模块
Tensor
张量表示的是一个多维数组,它是标量、向量、矩阵的拓展.标量是零维张量,向量是一维张量,矩阵是二维张量,一个RGB图像数组就是一个三维张量,第一维是图像高,第二维是图像的宽,第三维是图像颜色通道
张量相关函数
张量的创建
直接创建
torch.tensor(data, dtype=None, device=None, requires_grad=False, pin_memory=False)
- data(array_like) - tensor的初始数据,可以是list, tuple, numpy array, scalar或其他类型。
- dtype(torch.dtype, optional) - tensor的数据类型,如torch.uint8, torch.float, torch.long等
- device (torch.device, optional) – 决定tensor位于cpu还是gpu。如果为None,将会采用默认值,默认值在torch.set_default_tensor_type()中设置,默认为 cpu。
- requires_grad (bool, optional) – 决定是否需要计算梯度。
- pin_memory (bool, optional) – 是否将tensor存于锁页内存。这与内存的存在方式有关,通常为False。
torch.from_numpy()
通过numpy创建tensor,改变array中的值,tensor的值也会改变
依据数值创建
torch.zeros(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
依给定的size创建一个全0的tensor,默认数据类型为torch.float32(也称为torch.float)
layout(torch.layout, optional) - 参数表明张量在内存中采用何种布局方式。常用的有torch.strided, torch.sparse_coo等。
out(tensor, optional) - 输出的tensor,即该函数返回的tensor可以通过out进行赋值
torch.zeros_like(input, dtype=None, layout=None, device=None, requires_grad=False)
依input的size创建全0的tensor。
input(Tensor) - 创建的tensor与intput具有相同的形状。
依据概率分布创建
torch.normal(mean, std, out=None)
为每一个元素以给定的mean和std用高斯分布生成随机数
mean (Tensor or Float) - 高斯分布的均值,
std (Tensor or Float) - 高斯分布的标准差
torch.rand(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
在区间[0, 1)上,生成均匀分布
size (int...) - 创建的张量的形状
张量的操作
cat |
将多个张量拼接在一起,例如多个特征图的融合可用。 |
---|---|
concat |
同cat, 是cat()的别名。 |
conj |
返回共轭复数。 |
chunk |
将tensor在某个维度上分成n份。 |
dsplit |
类似numpy.dsplit()., 将张量按索引或指定的份数进行切分。 |
column_stack |
水平堆叠张量。即第二个维度上增加,等同于torch.hstack。 |
dstack |
沿第三个轴进行逐像素(depthwise)拼接。 |
gather |
高级索引方法,目标检测中常用于索引bbox。在指定的轴上,根据给定的index进行索引。强烈推荐看example。 |
hsplit |
类似numpy.hsplit(),将张量按列进行切分。若传入整数,则按等分划分。若传入list,则按list中元素进行索引。例如:[2, 3] and dim=0 would result in the tensors input[:2], input[2:3], and input[3:]. |
hstack |
水平堆叠张量。即第二个维度上增加,等同于torch.column_stack。 |
index_select |
在指定的维度上,按索引进行选择数据,然后拼接成新张量。可知道,新张量的指定维度上长度是index的长度。 |
masked_select |
根据mask(0/1, False/True 形式的mask)索引数据,返回1-D张量。 |
movedim |
移动轴。如0,1轴交换:torch.movedim(t, 1, 0) . |
moveaxis |
同movedim。Alias for torch.movedim() .(这里发现pytorch很多地方会将dim和axis混用,概念都是一样的。) |
narrow |
变窄的张量?从功能看还是索引。在指定轴上,设置起始和长度进行索引。例如:torch.narrow(x, 0, 0, 2), 从第0个轴上的第0元素开始,索引2个元素。x[0:0+2, ...] |
nonzero |
返回非零元素的index。torch.nonzero(torch.tensor([1, 1, 1, 0, 1])) 返回tensor([[ 0], [ 1], [ 2], [ 4]])。建议看example,一看就明白,尤其是对角线矩阵的那个例子,太清晰了。 |
permute |
交换轴。 |
reshape |
变换形状。 |
row_stack |
按行堆叠张量。即第一个维度上增加,等同于torch.vstack。Alias of torch.vstack() . |
scatter |
scatter_(dim, index, src, reduce=None) → Tensor。将src中数据根据index中的索引按照dim的方向填进input中。这是一个十分难理解的函数,其中index是告诉你哪些位置需要变,src是告诉你要变的值是什么。这个就必须配合例子讲解,请跳转到本节底部进行学习。 |
scatter_add |
同scatter一样,对input进行元素修改,这里是 +=, 而scatter是直接替换。 |
split |
按给定的大小切分出多个张量。例如:torch.split(a, [1,4]); torch.split(a, 2) |
squeeze |
移除张量为1的轴。如t.shape=[1, 3, 224, 224]. t.squeeze().shape -> [3, 224, 224] |
stack |
在新的轴上拼接张量。与hstack\vstack不同,它是新增一个轴。默认从第0个轴插入新轴。 |
swapaxes |
Alias for torch.transpose() .交换轴。 |
swapdims |
Alias for torch.transpose() .交换轴。 |
t |
转置。 |
take |
取张量中的某些元素,返回的是1D张量。torch.take(src, torch.tensor([0, 2, 5]))表示取第0,2,5个元素。 |
take_along_dim |
取张量中的某些元素,返回的张量与index维度保持一致。可搭配torch.argmax(t)和torch.argsort使用,用于对最大概率所在位置取值,或进行排序,详见官方文档的example。 |
tensor_split |
切分张量,核心看indices_or_sections变量如何设置。 |
tile |
将张量重复X遍,X遍表示可按多个维度进行重复。例如:torch.tile(y, (2, 2)) |
transpose |
交换轴。 |
unbind |
移除张量的某个轴,并返回一串张量。如[[1], [2], [3]] --> [1], [2], [3] 。把行这个轴拆了。 |
unsqueeze |
增加一个轴,常用于匹配数据维度。 |
vsplit |
垂直切分。 |
vstack |
垂直堆叠。 |
where |
根据一个是非条件,选择x的元素还是y的元素,拼接成新张量。看案例可瞬间明白。 |
张量的随机种子
seed |
获取一个随机的随机种子。Returns a 64 bit number used to seed the RNG. |
---|---|
manual_seed |
手动设置随机种子 |
initial_seed |
返回初始种子。 |
get_rng_state |
获取随机数生成器状态。Returns the random number generator state as a torch.ByteTensor. |
set_rng_state |
设定随机数生成器状态。这两怎么用暂时未知。Sets the random number generator state. |
随机种子主要用于对实验的复现
张量的数学操作
- Pointwise Ops: 逐元素的操作,如abs, cos, sin, floor, floor_divide, pow等
- Reduction Ops: 减少元素的操作,如argmax, argmin, all, any, mean, norm, var等
- Comparison Ops:对比操作, 如ge, gt, le, lt, eq, argsort, isnan, topk,
- Spectral Ops: 谱操作,如短时傅里叶变换等各类信号处理的函数。
- Other Operations:其它, clone, diag,flip等
- BLAS and LAPACK Operations:BLAS(Basic Linear Algebra Subprograms)基础线性代数)操作。如, addmm, dot, inner, svd等。
计算图--自动求导核心
计算图由节点和边构成
节点表示数据,如标量,向量,矩阵,张量等;
边表示运算,如加、减、乘、除、卷积、relu等;
![](C:\Users\wyx\Desktop\pytorch\屏幕截图 2024-04-19 161906.png)
叶子节点
叶子结点是最基础的结点,其数据不是由运算生成的,因此是整个计算图的基石,是不可轻易”修改“的
张量有一个属性是is_leaf, 就是用来指示一个张量是否为叶子结点的属性
例
import torch
w = torch.tensor([1.], requires_grad=True)
x = torch.tensor([2.], requires_grad=True)
a = torch.add(w, x)
b = torch.add(w, 1) # retain_grad()
y = torch.mul(a, b)
y.backward()
print(w.grad)
# 查看叶子结点
print("is_leaf:\n", w.is_leaf, x.is_leaf, a.is_leaf, b.is_leaf, y.is_leaf)
# 查看梯度
print("gradient:\n", w.grad, x.grad, a.grad, b.grad, y.grad)
# 查看 grad_fn
print("grad_fn:\n", w.grad_fn, x.grad_fn, a.grad_fn, b.grad_fn, y.grad_fn)
#
只有叶子节点的梯度得到保留,中间变量的梯度默认不保留;在pytorch中,非叶子结点的梯度在反向传播结束之后就会被释放掉,如果需要保留的话可以对该结点设置retain_grad()
grad_fn是用来记录创建张量时所用到的运算,在链式求导法则中会使用到。
自动微分--Autograd
- 自动求导机制通过有向无环图(directed acyclic graph ,DAG)实现
- 在DAG中,记录数据(对应tensor.data)以及操作(对应tensor.grad_fn)
- 操作在pytorch中统称为Function,如加法、减法、乘法、ReLU、conv、Pooling等,统统是Function
autograd的使用
torch.autograd.backward
使用频率最高的自动求导函数
torch.autograd.backward(tensors,grad_tensors=None,retain_graph=None,create_graph=False, grad_variables=None, inputs=None)
- tensors (Sequence[Tensor] or Tensor) – 用于求导的张量。如上例的loss。
- grad_tensors (Sequence[Tensor or None] or Tensor, optional) – 雅克比向量积中使用
- retain_graph (bool, optional) – 是否需要保留计算图。pytorch的机制是在方向传播结束时,计算图释放以节省内存。连续使用loss.backward(),就会报错。如果需要多次求导,则在执行backward()时,retain_graph=True。
- create_graph (bool, optional) – 是否创建计算图,用于高阶求导
使用时可直接调用.backward()函数
torch.autograd.grad
torch.autograd.grad(outputs, inputs, grad_outputs=None, retain_graph=None, create_graph=False, only_inputs=True, allow_unused=False)
功能:计算outputs对inputs的导数
主要参数:
- outputs (sequence of Tensor) – 用于求导的张量,如loss
- inputs (sequence of Tensor) – 所要计算导数的张量
- grad_outputs (sequence of Tensor) – 雅克比向量积中使用。
- retain_graph (bool, optional) – 是否需要保留计算图。
- create_graph (bool, optional) – 是否创建计算图,用于高阶求导。
- allow_unused (bool, optional) – 是否需要指示,计算梯度时未使用的张量是错误的。
例:
import torch
x = torch.tensor([3.], requires_grad=True)
y = torch.pow(x, 2) # y = x**2
# 一阶导数
grad_1 = torch.autograd.grad(y, x, create_graph=True) # grad_1 = dy/dx = 2x = 2 * 3 = 6
print(grad_1)
# 二阶导数
grad_2 = torch.autograd.grad(grad_1[0], x) # grad_2 = d(dy/dx)/dx = d(2x)/dx = 2
print(grad_2)
torch.autograd.Function
想要实现自己的一些操作时,如特殊的数学函数、pytorch的module中没有的网络层,那就需要自己写一个Function
pytorch数据模块
Dataset
torch.utils.data.Dataset,供用户继承编写dataset
例:
from torch.utils.data import Dataset
import os
from PIL import Image
class my_dateset(Dataset):
def __init__(self,root_dir,label_dir):
self.root_dir = root_dir
self.label_dir = label_dir
self.path = os.path.join(self.root_dir,self.label_dir)
self.img_path = os.listdir(self.path)
def __getitem__(self, idx):
img_name = self.img_path[idx]
img_item_path = os.path.join(self.root_dir,self.label_dir,img_name)
img = Image.open(img_item_path)
label = self.label_dir
return img,label
def __len__(self):
return len(self.img_path)
- getitem:需要实现读取一个样本的功能。通常是传入索引(index,可以是序号或key),然后实现从磁盘中读取数据,并进行预处理(包括online的数据增强),然后返回一个样本的数据。数据可以是包括模型需要的输入、标签,也可以是其他元信息,例如图片的路径。getitem返回的数据会在dataloader中组装成一个batch。即,通常情况下是在dataloader中调用Dataset的getitem函数获取一个样本。
- len:返回数据集的大小。如果这个函数返回的是0,dataloader会报错:"ValueError: num_samples should be a positive integer value, but got num_samples=0"
DataLoader
torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=False, sampler=None, batch_sampler=None, num_workers=0, collate_fn=None, pin_memory=False, drop_last=False, timeout=0, worker_init_fn=None, multiprocessing_context=None, generator=None, *, prefetch_factor=2, persistent_workers=False)
- dataset:一个Dataset实例,要能实现从索引(indices/keys)到样本的映射。(即getitem函数)
- batch_size:每个batch的样本量
- shuffle:是否对打乱样本顺序。训练集通常要打乱它!验证集和测试集无所谓。
- sampler:设置采样策略。
- batch_sampler:设置采样策略, batch_sampler与sampler二选一
- num_workers: 设置多少个子进程进行数据加载(data loading)
- collate_fn:组装数据的规则, 决定如何将一批数据组装起来。
- pin_memory:是否使用锁页内存,具体行为是“the data loader will copy Tensors into CUDA pinned memory before returning them”
- drop_last:每个epoch是否放弃最后一批不足batchsize大小的数据,即无法被batchsize整除时,最后会有一小批数据,是否进行训练,如果数据量足够多,通常设置为True。
Dataset及常用API
concat
在实际项目中,数据的来源往往是多源的,很难统一到一个数据格式.一种灵活的方式是每批数据编写一个Dataset,然后使用torch.utils.data.ConcatDataset类将他们拼接起来,这种方法可以灵活的处理多源数据,也可以很好的使用别人的数据及Dataset
Subset
subset可根据指定的索引获取子数据集,Subset也是Dataset类
例
def __init__(self, dataset: Dataset[T_co], indices: Sequence[int]) -> None:
self.dataset = dataset
self.indices = indices
def __getitem__(self, idx):
if isinstance(idx, list):
return self.dataset[[self.indices[i] for i in idx]]
return self.dataset[self.indices[idx]]
def __len__(self):
return len(self.indices)
random_aplit
该函数的功能是随机的将dataset划分为多个不重叠的子集,适合用来划分训练、验证集
torch.utils.data.random_split(dataset, lengths, generator=None)
只需要设置每个子集的数据量,传给lengths即可
sampler
sampler是在dataloader中起到挑选数据的功能,主要是设置挑选策略,如按顺序挑选、随机挑选、按类别分概率挑选等
sampler 与 batch_sampler
本质上两者都是采样器,当采用auto_collation时,采用batch_sampler
batch_sampler是一次返回一个batch的索引。通常我们用的都是batch_sampler,其对应的是BatchSampler类
BatchSampler
torch.utils.data.BatchSampler(sampler, batch_size, drop_last)
第一个参数传入的是一个sampler采样器,在这里会有两种情况,如果需要shuffle,则传入RandomSampler,不需要打乱,则传入SequentialSampler
BatchSampler是在其它两者之上封装了一个批抽取的功能,一次yield一个batch的index,而样本采样的顺序取决于RandomSampler和SequentialSample。
SequentialSampler
顺序迭代器,按顺序的迭代器
RandomSamoler
默认情况下会使用这行代码实现:yield from torch.randperm(n, generator=generator).tolist(), 利用torch的随机方法生成一个随机整数序列,对于generator默认采用的是随机一个随机种子进行设置
SubsetRandomSampler
通过索引定义一个自己的随机采样器
这个采样器返回的样本总数是传入的索引的长度
def __iter__(self) -> Iterator[int]:
for i in torch.randperm(len(self.indices), generator=self.generator):
yield self.indices[i]
WeightedRandomSampler
torch.utils.data.WeightedRandomSampler(weights, num_samples, replacement=True, generator=None)
- weights (sequence) – 每个样本的采样权重,权重之和不必为1,只需要关心各样本之间的比例即可。
- num_samples (int) – 采样数量,一般设为样本总量。
- replacement (bool) –是否有放回采样。 True,表示有放回。
- generator (Generator) – 自定义生成器,通常用默认的
transforms
pytorch的图像数据增强函数库
变换方法
Compose
用于包装一系列transforms方法
例:
dataset_transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor()])
Resize
支持对PIL或Tensor对象的缩放
例
Resize(size, interpolation=, max_size=None, antialias=None)
Totensor
将PIL对象或nd.array对象转换成tensor,并且对数值缩放到[0, 1]之间,并且对通道进行右移
Normalize
对tensor对象进行逐通道的标准化,具体操作为减均值再除以标准差
Normalize(mean, std, inplace=False)
transforms.Pad
对图像进行填充
torchvision.transforms.Pad(padding, fill=0, padding_mode='constant')
transforms.Grayscale
将图片转为灰度图
torchvision.transforms.Grayscale(num_output_channels=1)
PILImage:transforms.ToPILImage
torchvision.transforms.ToPILImage(mode=None)
将 tensor 或者 ndarray 的数据转换为 PIL Image 类型数据
mode- 为None时为 1 通道, mode=3 通道默认转换为 RGB,4 通道默认转换为 RGBA
裁剪方法
随机裁剪:transforms.RandomCrop
依据给定的 size 随机裁剪
torchvision.transforms.RandomCrop(size, padding=None, pad_if_needed=False, fill=0,
padding_mode='constant')
中心裁剪:transforms.CenterCrop
torchvision.transforms.CenterCrop(size)
依据给定的 size 从中心裁剪
随机长宽比裁剪:transforms.RandomResizedCrop
torchvision.transforms.RandomResizedCrop(size, scale=(0.08, 1.0), ratio=(0.75, 1.33333
33333333333), interpolation=2)
机大小,随机长宽比裁剪原始图片,最后将图片 resize 到设定好的 size
size- 输出的分辨率
scale- 随机 crop 的大小区间,如 scale=(0.08, 1.0),表示随机 crop 出来的图片会在的 0.08
倍至 1 倍之间。
ratio- 随机长宽比设置
interpolation- 插值的方法,默认为双线性插值(PIL.Image.BILINEAR)
上下左右中心裁剪transforms.FiveCrop
torchvision.transforms.FiveCrop(size)
功能:对图片进行上下左右以及中心裁剪,获得 5 张图片,返回一个 4D-tensor
上下左右中心裁剪后翻转: transforms.TenCrop
torchvision.transforms.TenCrop(size,vertical_flip=False)
功能:对图片进行上下左右以及中心裁剪,然后全部翻转(水平或者垂直),获得 10 张图
片,返回一个 4D-tensor。
vertical_flip (bool) - 是否垂直翻转,默认为 flase,即默认为水平翻转
翻转和旋转
依概率 p 水平翻转 transforms.RandomHorizontalFlip
torchvision.transforms.RandomHorizontalFlip(p=0.5)
功能:依据概率 p 对 PIL 图片进行水平翻转
p- 概率,默认值为 0.5
垂直翻转 transforms.RandomVerticalFlip
torchvision.transforms.RandomVerticalFlip(p=0.5)
功能:依据概率 p 对 PIL 图片进行垂直翻转
p- 概率,默认值为 0.5
随机旋转transforms.RandomRotation
torchvision.transforms.RandomRotation(degrees,resample=False,expand=False,center=None)
功能:依 degrees 随机旋转一定角度
degress- (sequence or float or int) ,若为单个数,如 30,则表示在(-30,+30)之间随机旋
转
resample- 重采样方法选择,可选PIL.Image.NEAREST, PIL.Image.BILINEAR, PIL.Image.BICUBIC,默认为False
expand-用于指定是否扩展图像以适应旋转后的图像。如果设置为 True
,则会扩展图像的边界以容纳整个旋转后的图像;如果设置为 False
,则会保留旋转后图像的原始尺寸,默认为 False
。
center- 可选为中心旋转还是左上角旋转
自动数据增强
AutoAugment
torchvision.transforms.AutoAugment(policy: torchvision.transforms.autoaugment.AutoAugmentPolicy = , interpolation: torchvision.transforms.functional.InterpolationMode = , fill: Optional[List[float]] = None)
功能:自动数据增强方法的封装,支持三种数据增强策略,分别是IMAGENET、CIFAR10 和SVHN
参数:
policy :需要是AutoAugmentPolicy类
interpolation:设置插值方法
fill :设置填充像素的像素值,默认为0,黑色。
RandAugment
RandAugment是进行N次(num_ops )变换,变换方法从策略池中随机挑选
num_ops :执行多少次变换
magnitude :每个变换的强度,
num_magnitude_bins:与变化强度的采样分布有关
pytorch模型模块
module
Module是所有神经网络的基类,所有的模型都必须继承于Module类,并且它可以嵌套
构建自己的网络只需要三步:
- 写一个类继承于Module
- init函数中把需要的网络层创建好
- forward函数中把模型如何搭建的规则写好
parameter--参数
parameter继承于Tensor,主要作用是用来区分可训练的参数与常规的tensor
Parameter指模型的参数,如卷积层的卷积核权重和偏置,Linear层的权重和偏置,BN层的α和β等等
例
optimizer = optim.SGD(model.parameters(), lr=0.1, momentum=0.9, weight_decay=5e-4)
module的容器
Sequential
将一系列网络层按固定的先后顺序串起来,当成一个整体,调用时数据从第一个层按顺序执行到最后一个层
例:
model = nn.Sequential(
nn.Conv2d(1,20,5),
nn.ReLU(),
nn.Conv2d(20,64,5),
nn.ReLU()
)
def forward(self, input):
for module in self:
input = module(input)
return input
ModuleList
将各个网络层放到一个“列表”中,便于迭代的形式调用
例
class MyModule(nn.Module):
def __init__(self):
super(MyModule, self).__init__()
self.linears = nn.ModuleList([nn.Linear(10, 10) for i in range(10)])
def forward(self, x):
for sub_layer in self.linears:
x = sub_layer(x)
return x
ModuleDict
ModuleDict就是可以像python的Dict一样为每个层赋予名字,可以根据网络层的名字进行选择性的调用网络层
class MyModule2(nn.Module):
def __init__(self):
super(MyModule2, self).__init__()
self.choices = nn.ModuleDict({
'conv': nn.Conv2d(3, 16, 5),
'pool': nn.MaxPool2d(3)
})
self.activations = nn.ModuleDict({
'lrelu': nn.LeakyReLU(),
'prelu': nn.PReLU()
})
def forward(self, x, choice, act):
x = self.choices[choice](x)
x = self.activations[act](x)
return x
常用网络层
Convolutional Layers
卷积层
torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros')
对多个二维平面组成的信号进行二维卷积
- in_channels (int) – 输入这个网络层的图像的通道数是多少。
- out_channels (int) – 此网络层输出的特征图的通道数是多少,等价于卷积核数量是多少。
- kernel_size (int or tuple) – 卷积核大小。
- stride (int or tuple, optional) – 卷积核卷积过程的步长。
- padding (int, tuple or str, optional) –对于输入图像的四周进行填充的数量进行控制,可指定填充像素数量,也可以指定填充模式,
- padding_mode (string, optional) – 填充的像素值如何确定。默认填充0。
- dilation (int or tuple, optional) – 孔洞卷积的孔洞大小。
- groups (int, optional) – 分组卷积的分组。
- bias (bool, optional) – 是否采用偏置。
![](C:\Users\wyx\Desktop\pytorch\屏幕截图 2024-04-20 161320.png)
![](C:\Users\wyx\Desktop\pytorch\屏幕截图 2024-04-20 161332.png)
Pooling Layers
池化层
将特征图分辨率变小,通常减小一半(提取特征量)
可对池化层进行划分为最大值池化、平均值池化、分数阶池化、基于范数的池化。分别对应torch.nn中的Maxpool, Avgpool, FractionalMaxPool, LPPool
Maxpool:
torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)
2D最大池化
-
kernel_size – 池化窗口大小
-
stride – 滑窗步长
-
padding – 原图填充大小
-
dilation – 孔洞大小
-
return_indices – 是否返回最大值所在位置,主要在 torch.nn.MaxUnpool2d 中使用,是上采样的一种策略
-
ceil_mode – 当无法整除时,是向下取整还是向上取整,默认为向下。
![](C:\Users\wyx\Desktop\pytorch\屏幕截图 2024-04-20 161320-1713600998558-3.png)
Padding Layers
给特征图周围填充一定的像素,调整特征图分辨率的一种方法
可将padding layer划分为三类,镜像填充、边界重复填充,指定值填充、零值填充,分别对应nn的三大类,nn.ReflectionPad2d, nn.ReplicationPad2d, nn.ZeroPad2d, nn.ConstantPad2d
Linear Layers
线性层
Linear Layers包含4个层分别是nn.Identity,nn.Linear, nn.Bilinear, nn.LazyLinear
nn.Identity 是恒等映射,不对输入做任何变换,它通常用于占位。
nn.Linear 全连接层(Fully Connection Layer),可实现 y= Wx + b
nn.Bilinear 是双线性层,它有两个输入,实现公式 y = x1Wx2 +b
nn.LazyLinear 是nn.Linear的lazy版本,也就是懒惰的Linear层,它在第一次推理时自动根据输入特征图的尺寸来设定in_features,免去了手动计算in_features的麻烦。
Dropout Layers
随机失活--防止模型过拟合
Dropout使用注意事项:
- Dropout通常用于nn.Linear层之前;
- Dropout执行后,神经元个数会减少,导致数据尺度发生变化.
Non - linear Layers
非线性激活函数函数
Module常用函数
-
设置模型训练、评估模式
eval:设置模型为评估模式,与BN,Dropout息息相关,即评估模式下模型的某些层执行的操作与训练状态下是不同的。
train:设置模型为训练模式,如BN层需要统计runing_var这些统计数据,Dropout层需要执行随机失活等
-
设置模型存放在cpu/gpu/xpu
- cpu,将Module放到cpu上
- cuda,把需要运算的数据放到gpu即可。方法就是 xxx.cuda()
- to,可将对象放到指定的设备中去,如to.("cpu") 、 to.("cuda)、to("cuda:0") 等
-
获取模型参数、加载权重参数
- load_state_dict,将参数字典中的参数复制到当前模型中。要求key要一一对应
- state_dict,返回参数字典。key是告诉你这个权重参数是放到哪个网络层
-
管理模型的modules, parameters, sub_module
parameters:返回一个迭代器,迭代器可抛出Module的所有parameter对象
named_parameters:作用同上,不仅可得到parameter对象,还会给出它的名称
modules:返回一个迭代器,迭代器可以抛出Module的所有Module对象,注意:模型本身也是module,所以也会获得自己。
named_modules:作用同上,不仅可得到Module对象,还会给出它的名称
children:作用同modules,但不会返回Module自己。
named_children:作用同named_modules,但不会返回Module自己
-
设置模型的参数精度,可选半精度、单精度、双精度等
- bfloat16
- half
- float
- double
-
对子模块执行特定功能
- apply
- zero_grad
pytorch优化模块
损失函数--Loss Function
损失函数(loss function)是用来衡量模型输出与真实标签之间的差异,当模型输出越接近标签,认为模型越好,反之亦然
在pytorch中提供了二十一个损失函数,如下所示
nn.L1Loss
nn.MSELoss
nn.CrossEntropyLoss
nn.CTCLoss
nn.NLLLoss
nn.PoissonNLLLoss
nn.GaussianNLLLoss
nn.KLDivLoss
nn.BCELoss
nn.BCEWithLogitsLoss
nn.MarginRankingLoss
nn.HingeEmbeddingLoss
nn.MultiLabelMarginLoss
nn.HuberLoss
nn.SmoothL1Loss
nn.SoftMarginLoss
nn.MultiLabelSoftMarginLoss
nn.CosineEmbeddingLoss
nn.MultiMarginLoss
nn.TripletMarginLoss
nn.TripletMarginWithDistanceLoss
L1loss
torch.nn.L1Loss(size_average=None, reduce=None, reduction='mean')
计算output和target之差的绝对值,可选返回同维度的tensor(reduction=none)或一个标量(reduction=mean/sum)
CrossEntropyLoss -- 交叉熵损失函数
torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=- 100, reduce=None, reduction='mean', label_smoothing=0.0)
先将输入经过softmax激活函数之后,再计算交叉熵损失
eight (Tensor, optional) – 类别权重,用于调整各类别的损失重要程度,常用于类别不均衡的情况
ignore_index (int, optional) – 忽略某些类别不进行loss计算。
size_average (bool, optional) – 已舍弃使用的变量,功能已经由reduction代替实现,仍旧保留是为了旧版本代码可以正常运行。
reduce (bool, optional) – 已舍弃使用的变量,功能已经由reduction代替实现,仍旧保留是为了旧版本代码可以正常运行。
reduction (string, optional) – 是否需要对loss进行“降维”,这里的reduction指是否将loss值进行取平均(mean)、求和(sum)或是保持原尺寸(none)
优化器--Optimizer
对模型进行优化使loss不断降低
优化器的实现在torch.optim中
优化器基类
参数组(param_groups):参数组是用于管理需要进行优化的那些参数,例如权值weight,偏置bias,BN的alpha/beta等
这里是参数组不是参数,表明可以将所有参数进行分组,例如在finetune过程中,通常让前面层的网络采用较小的学习率,后面几层全连接层采用较大的学习率,这时我们就要把网络的参数划分为两组,每一组有它对应的学习率
参数组是一个list,其元素是一个dict,dict中包含,所管理的参数,对应的超参,例如学习率,momentum,weight_decay等等。
state:用于存储优化策略中需要保存的一些缓存值,例如在用momentum时,需要保存之前的梯度,这些数据保存在state中。
defaults:优化方法默认的超参数
方法:
zero_grad()
功能:清零所管理参数的梯度。由于pytorch不会自动清零梯度,因此需要再optimizer中手动清零,然后再执行反向传播,得出当前iteration的loss对权值的梯度。
step()
功能:执行一步更新,依据当前的梯度进行更新参数
add_param_group(param_group)
功能:给optimizer管理的参数组中增加一组参数,可为该组参数定制lr,momentum,weight_decay等,在finetune中常用。
例如:
optimizer_1.add_param_group({'params': w3, 'lr': 0.001, 'momentum': 0.8})
state_dict()
功能:获取当前state属性。
通常在保存模型时同时保存优化器状态,用于断点保存,下次继续从当前状态训练;
load_state_dict(state_dict)
功能:加载所保存的state属性,恢复训练状态。
SGD--随机梯度下降
深度学习中最基础的一个
SGD核心理论知识是梯度下降( gradient descent),即沿着梯度的负方向,是变化最快的方向。
SGD的使用
optimizer = optim.SGD(model.parameters(), lr=0.1, momentum=0.9, weight_decay=5e-4)#实例化
optimizer.zero_grad()#loss.backward()之前进行梯度清零
loss.backward()
optimizer.step()#loss.backward()之后执行一步更新
pytorch 可视化
TensorBoard
例
from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter("logs")
writer.add_image("test",img_array,2,dataformats="HWC")
writer.close()
终端输入
tensorboard --logdir=your path dir
add_scalar
add_scalar(tag, scalar_value, global_step=None, walltime=None, new_style=False, double_precision=False)
添加标量;tag的设置可以有个技巧是在同一栏下绘制多个图,如'Loss/train', 'Loss/Valid', 这就类似于matplotlib的subplot(121), subplot(122)
- tag (string) – Data identifier
- scalar_value (float or string/blobname) – Value to save
- global_step (int) – Global step value to record
add_scalars
add_scalars`(main_tag, tag_scalar_dict, global_step=None,walltime=None)
功能:在一个坐标轴中绘制多条曲线。常用于曲线对比。
- main_tag (string) – The parent name for the tags
- tag_scalar_dict (dict) – Key-value pair storing the tag and corresponding values
- global_step (int) – Global step value to record
add_image
add_image(tag, img_tensor, global_step=None, walltime=None, dataformats='CHW')
功能:绘制图像。
- tag (string) – Data identifier
- img_tensor (torch.Tensor, numpy.array, or string/blobname) – Image data
- global_step (int) – Global step value to record dataformats- 数据通道顺序物理意义。默认为 CHW