本节简单总结Pytorch中常见的4大归一化、模型如何保存并加载、以及模型如何实现微调,pytorch中多GPU的使用。【文中思维导图采用MindMaster软件,Latex公式采用在线编码器】 |
? 都是为了解决Internal Covariate Shift(ICS)问题,即数据分布出现异常而导致的网络训练困难。ICS问题在《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》中提到。
? 都是类似 \(\gamma \times \frac{x- mean }{\sqrt{var^{2}+ \varepsilon } } + \beta\) 这样的形式,即“加减乘除”。
? 均值mean和方差variance的求取方式不同,具体以下图为例:
‘‘‘BatchNorm基类‘‘‘
class _BatchNorm(Module):
def __init__(self, num_features, eps=1e-5, momentum=0.1, affine=True,
track_running_stats=True):
# 参数:
# num_features:一个样本的特征数量(或者是通道数量)
# eps:分母修正项
# momentum:指数加权平均 估计当前的mean/var!!!!!!!
# affine:是否进行affine transform,即gamma、beta的scale and shift
# track_running_stats:是训练状态 or 测试状态
? 注意:测试状态,mean和var只计算当前batch,而训练状态,当前时刻的mean和var会受之前的batch影响,即下面的公式(momentum):
? 上面的momentum在之前的博客中有提及。
class LayerNorm(Module):
def __init__(self, normalized_shape, eps=1e-5, elementwise_affine=True):
# 参数:
# normalized_shape:该样本的特征形状
# eps:分母修正项
# elementwise_affine:是否要对每个元素进行affine transform操作
? 注意:实例化LN时,要注意normalized_shape这一项,必须从size末尾写,例如:
>>> input = torch.randn(20, 5, 4, 10)
>>> m = nn.LayerNorm(input.size()[1:])
>>> m = nn.LayerNorm([4, 10])
>>> m = nn.LayerNorm([5,4, 10])
>>> m = nn.LayerNorm([10])
# 但不可以是:
>>> m = nn.LayerNorm([5, 4])
‘‘‘InstanceNorm基类‘‘‘
class _InstanceNorm(_BatchNorm):
def __init__(self, num_features, eps=1e-5, momentum=0.1, affine=False,
track_running_stats=False):
# 参数:
# num_features:一个样本的特征数量(或者是通道数量)
# eps:分母修正项
# momentum:指数加权平均 估计当前的mean/var!!!!!!!
# affine:是否进行affine transform,即gamma、beta的scale and shift
# track_running_stats:是训练状态 or 测试状态
class GroupNorm(Module):
def __init__(self, num_groups, num_channels, eps=1e-5, affine=True):
# 参数:
# num_groups:分组数(必须能将通道数整除!!!!!!!!)
# num_channels:通道数
# eps:分母修正项
# affine:是否进行affine transform,这里是对每个通道进行!!!!
? 主要参数如下:(torch.save(obj, f))
obj:要保存的对象(模型,张量,参数等);
f:保存的路径。
? 主要参数如下:(torch.load(f, map_location=None))
f:读取路径;
map_location:决定该文件放在GPU上还是cpu位置上,当想要加载的模型是GPU上的,此时机子没有GPU,则可以将map_location=‘cpu‘,将该模型放置在cpu上。
# 保存整个网络
torch.save(net, PATH)
# 保存网络中的参数
torch.save(net.state_dict(),PATH)
#对应上面的保存方式:
model_dict=torch.load(PATH)
model_dict=model.load_state_dict(torch.load(PATH))
‘‘‘保存‘‘‘
checkpoint = {"model_state_dict": net.state_dict(),
"optimizer_state_dict": optimizer.state_dict(),
"epoch": epoch}
torch.save(checkpoint, path_checkpoint)
‘‘‘加载‘‘‘
checkpoint = torch.load(path_checkpoint)
net.load_state_dict(checkpoint[‘model_state_dict‘])
optimizer.load_state_dict(checkpoint[‘optimizer_state_dict‘])
start_epoch = checkpoint[‘epoch‘]
scheduler.last_epoch = start_epoch # 用于更新优化器的学习率
? 模型finetune感觉这里对python编程较高 ( 咳咳。。。——>_——>。。。只怪本人python编程目前还比较low ),其实主要要对字典、列表等高级操作要熟悉!!
? 在这里本人就不献丑了,等后续用到finetune再来补充。大家可以先参考知乎Pytorch自由载入部分模型参数并冻结。
? to函数可以用于tensor和module:
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
‘‘‘对于张量tensor‘‘‘
# 张量不执行原位inplace操作,即必须赋值
a = torch.ones((5, 5))
a = a.to(torch.float64)
a = a.to(device)
‘‘‘对于模型moudle‘‘‘
# 模型执行inplace
net.to(device)
? 上图中设置GPU对应的os.environ.setdefault操作,可以有效防止多人使用GPU冲突问题,或者多程序在不同的GPU上跑的冲突,可用可见的GPU(逻辑GPU)与物理GPU的对应关系可以理解为:(对应图3os.environ粉色方块的操作)
? 这里一般利用torch.nn.DataParallel操作,例如batch_size=16,我们利用4个GPU并行运算,分配给每个GPU的batch_size=4该机制主要流程为:
class DataParallel(Module):
def __init__(self, module, device_ids=None, output_device=None, dim=0):
# 参数:
# module:需要处理的模型;
# device_ids:可分法的GPU,默认分发到所有可见可用的GPU;(通过设置上述os.environ.setdefault操作,即可默认)
# output_device:最后结果输出设备,默认主GPU
? 当我们加载多GPU模型参数,print load后的pkl文件,会发现较原始模型linear.0,多了一个module,即module.linear.0,因而我们需要取出module之后的参数,可以参考github上的代码:
‘‘‘state_dict_load为OrderedDict形式,无法直接操作‘‘‘
state_dict_load = torch.load(path, map_location="cpu")
from collections import OrderedDict
new_state_dict = OrderedDict()
for k, v in state_dict_load.items():
namekey = k[7:] if k.startswith(‘module.‘) else k # 重新取出module后层信息,作为新的key
new_state_dict[namekey] = v
net.load_state_dict(new_state_dict)
Pytorch框架学习---(7)常见的4大归一化、模型保存与加载、模型微调、多GPU的使用
原文:https://www.cnblogs.com/zpc1001/p/13344215.html