1.num_worker
num_workers>0 表示只有指定数量的worker进程去加载数据,主进程不参与。增加num_works也同时会增加cpu内存的消耗。所以num_workers的值依赖于 batch size和机器性能。
一般开始是将num_workers设置为等于计算机上的CPU数量
最好的办法是缓慢增加num_workers,直到训练速度不再提高,就停止增加num_workers的值。
2.worker_init_fn
创建DataLoader需要传入Dataset对象,如果在Dataset中实现了worker_init_fn成员函数,则把这个函数也一并传给DataLoader。
不管传给DataLoader的num_workers等于几,Dataset的构造函数都只会被创建一次,即不同的worker是使用同一个Dataset;但是worker_init_fn会被调用num_workers次,用于初始化每个worker自己独有的数据,避免了和其他worker使用公用的数据,进而加快数据加载速度。
3.sys.stdout=Logger(“日志地址”)
sys.stdout标准输出将控制台(run结果显示的那里面)所有信息输出打印到文件
sys.stdout = Logger("D:\\1.txt") #这里我将Log输出到D盘
4.model=model.to(device)
device = 'cuda' if torch.cuda.is_available else 'cpu'
当我们指定了设备之后,就需要将模型加载到相应设备中,此时需要使用model=model.to(device),将模型加载到相应的设备中。将由GPU保存的模型加载到CPU上。
4.保存加载模型
torch.save(model,'save.pt')#保存整个模型
torch.save(model.state_dict(), 'save.pt')#只保存权重(一般是这个)
加载模型:
if model_path is not None:
model.load_state_dict(torch.load("save.pt")) #model.load_state_dict()函数把加载的权重复制到模型的权重中去
print(f'resume model from {model_path}')
else:
print('No model found, initializing random model.')
加载模型和model.to(device)先后顺序无所谓
5.多卡分布式训练DP,torch.nn.DataParallel()
model = model.cuda()
device_ids = [0, 1] # id为0和1的两块显卡
model = torch.nn.DataParallel(model, device_ids=device_ids)
关于分布式训练中的BN:(例如三卡,Batchsize为8)
nn.DataParallel,简称DP,是单进程多卡parameter server模型,不支持同步BN。每次计算BN时,DP会把0号卡(也就是主卡)上的单卡小batch mean和单卡小batch varaince 广播给其他卡。所以,对BN来说,batch size就是单卡的batch size = 8。你看到的tensor batch size是24,不代表BN的真实batch size就是24。
同步BN,也就是SyncBN,只在DataDistributedParallel(DDP)中支持。可以实现真正的多卡BN。有没有必要使用SyncBN,要看你的单卡batch size的数量大小。如果单卡batch size太小,使用SyncBN确实可以提高性能。
6.torch.optim.Adam()优化器
class torch.optim.Adam(params, lr=0.001, betas=(0.9, 0.999), eps=1e-08, weight_decay=0)
例:optimizer =torch.optim.Adam(model.module.params(), lr=learning_rate, betas=(beta1,beta2))
##参数:
params(iterable):可用于迭代优化的参数或者定义参数组的dicts。
lr (float, optional) :学习率(默认: 1e-3)
betas (Tuple[float, float], optional):用于计算梯度的平均和平方的系数(默认: (0.9, 0.999))
eps (float, optional):为了提高数值稳定性而添加到分母的一个项(默认: 1e-8)
weight_decay (float, optional):权重衰减(如L2惩罚)(默认: 0)
7.学习率衰减
scheduler = lr_scheduler.StepLR(optimizer, step_size=step_size, gamma=gamma)
8.在代码中哪些东西需要上传到GPU(model,loss,数据标签xy,输出结果)
(1)判断GPU是否可用
if torch.cuda.is_available():
device = torch.device('cuda')
cudnn.benchmark = True
else:
device = torch.device('cpu')
(2)构建网络时,把网络,与损失函数转换到GPU上
model = CNN().to(device)
loss = nn.CrossEntropyLoss().to(device)
(3)训练网络时,把数据转换到GPU上
x, y = x.to(device), y.to(device)
# 注,只有tensor类型才能上传到GPU上,故需要对numpy数据进行转换成tensor类型
# torch.tensor(x) 或 torch.from_numpy(x)
#两者的区别见 https://blog.csdn.net/github_28260175/article/details/105382060
(4)对训练的输出结果有些需要使用np的函数进行操作,需先将输出结果转到CPU上,并转成numpy类型,再使用np的函数
output = (model(x)).cpu().numpy()
9.model.train()和model.eval()
model.train()和eval()用于控制模型是训练模式还是验证模式,主要是控制dropout和BN层
eval()时dropout失活,BN使用训练阶段的mean()和val值,且此阶段不更新权重
10.torch.utils.data.Dataloader()
构建可迭代的数据装载器,训练时,每一个for循环,每一次iteration,就是从DataLoader中获取一个batch——size大小的数据。
例:train_dataloader = data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=8,worker_init_fn=worker_init_fn)
参数:dataset--Dataset类,决定数据从哪读取以及如何读取
batchsiz--批大小 num_works--进程个数
shuffle--每个epoch是否乱序
drop_last:当样本数不能被batchsize整除时,是否舍弃最后一批数据
11.清除梯度
pytorch默认会对梯度进行累加,因此为了不使得之前计算的梯度影响到当前当前计算,需要手动清除梯度
model.zero_grad()
optimizer.zero_grad()
首先,这两种方式都是把模型中参数的梯度设为0.当optimizer = optim.Optimizer(net.parameters())时,二者等效,其中Optimizer可以是Adam、SGD等优化器,net为model。
12.计算梯度并更新
梯度计算:
grads = torch.autograd.grad(cost, (model.params()),create_graph=True)
或者loss.backward()
网络参数更新:
model.update_params(lr_inner=lr, source_params=grads,solver = 'adam')
或者optimizer.step()
13.pytorch中.item()
官方文档解释.item()用法是:一个元素张量可以用x.item()得到元素值,我理解的就是一个是张量,一个是元素。
一般在计算acc时用到