先来看一下该函数的源码
class AverageMeter(object):
"""Computes and stores the average and current value"""
def __init__(self):
self.reset()
def reset(self):
self.val = 0
self.avg = 0
self.sum = 0
self.count = 0
def update(self, val, n=1):
self.val = val
self.sum += val * n
self.count += n
self.avg = self.sum / self.count if self.count != 0 else 0
这个函数好像是大家常用的一个函数,但是却没有被收录在某个package里,所以一般都是在自己的项目里重新定义一遍,而不是从某个现有的包里导入,anyway,它很好用。
接下来根据一段代码,看一下它的用处
def train(Net, train_data_loader, val_data_loader, criterion, optimizer, lr_scheduler,device, args):
# Training the model
for epoch_idx in range(args.n_epochs): # loop over the dataset multiple times
if args.is_neptune:
run['train/epoch/learning_Rate'].log(optimizer.param_groups[0]["lr"])
Net.train() # 声明当前为训练模式,每个mini-batch进行BN和dropout两个参数的调整
losses = AverageMeter()
train_accuracy = AverageMeter()
for batch_idx, data_input in enumerate(train_data_loader):
data1, data2, labels = data_input
cur_batch_size = len(data1)
optimizer.zero_grad()
outputs, _, _ = Net(data1.float().to(device), data2.float().to(device), finetune=True)
loss = criterion(outputs.cpu(), labels)
loss.backward()
optimizer.step()
losses.update(loss.data.item())
train_accuracy.update(accuracy(outputs.cpu(), labels))
进入train函数开始训练,参数中的Net表示模型
第3行进行epoch迭代,每次训练一个epoch
第6行Net.train() 声明当前为训练模式
第8行来到了AverageMeter()函数
该函数用来管理一些需要更新的变量,比如loss、accuracy、mAP等度量指标。使用方式即为第8行所示,直接用其定义一个待更新的变量。初始化时会调用AverageMeter函数中的reset方法,调用该函数的update方法时会对相应的变量进行更新,如第24行所示。
从第11行开始按批次读取训练集中的数据,
首先执行enumerate(train_data_loader),会先调用DataLoader类的__iter__方法,在该方法里面再调用DataLoaderIter类的初始化操作__init__。
而当执行for循环时,调用DataLoaderIter类的__next__方法,在该方法中通过self.collate_fn接口读取self.dataset数据时就会调用TSNDataSet类的__getitem__方法,从而完成数据的迭代读取。
读取到数据后就将数据从Tensor转换成Variable格式,然后执行接下来的操作。
第12行将读取的数据解包为数据与label
第17行将数据送入模型进行前向计算,得到输出outputs, 其shape为[batch_size, num_class]
第19行为损失函数的计算
第21行为损失回传
第22行optimizer.step()进行模型参数更新
接下来是loss和accuracy的更新
更新完参数之后,进行下一个batch的训练,以此类推,直至完成整个训练。