PyTorch中的优化器的构建: torch.optim.Optimizer

前言:

Pytoch中用来优化模型权重的类是torch.optim.Optimizer, 其他各种我们所熟知的优化器都是Optimizer这个基类的子类, 我们今天就来谈谈如何构建一个模型的优化器对象实例.

先用一段代码来看看整体的步骤:

class trainer:
	def __init__(self, args):
		self.model = model  #构建模型
		if args.cuda:
			self.model = self.model.cuda() #如果有可用的gpu,在构建模型的优化器之前要先把模型导入到gpu之中
		self.optimizer  = torch.optim.SGD(params=self.model.parameters(), lr=args.lr)   #构建一个SDG类的实例
		self.loss = torch.nn.nn.CrossEntropyLoss()   #构建一个损失函数类实例
		if args.cuda:
			self.loss = self.loss.cuda()  #同理导入近gpu
	
	def traing(self):
	#下面是一个训练过程,主要的步骤包括:
	"""
	1. 清空梯度
	2. 动态调整学习率(非必须)
	3. 前向传播
	4. 计算loss
	5. 反向传播
	6. 更新参数
	"""
	self.optimizer.zero_grad()
	output = self.model(input)
	loss = sefl.loss(output, label)
	loss.backward()
	self.optimizer.step()

今天我们主要关注优化器optimizer这一块的内容.


优化器实例的构建:

一. 在构建优化器之前一定要将模型的参数导入到gpu之中(加入有gpu的话)
二.构建优化器实例时模型参数的传入

所有的优化都继承torch.optim.Optimizer类

	CLASS torch.optim.Optimizer(params, defaults)

我们重点关注params的传入, 其传入的数据类型有两种:

  1. 可迭代的torch.tensor
  2. 字典(dict), 字典中的键(key)为"params"那一项的值(value)必须为可迭代的torch.tensor
  3. 需要强调的是如果有多个dict要传入, 则要放入一个列表容器中.

因此可以有两种传入参数的方式:
1.模型的权重共享同一个学习率, 直接将模型的参数全部传入进去:

self.optimizer  = torch.optim.SGD(params=self.model.parameters(), lr=args.lr) 
#这种方式下模型所有参数将用同一个学习率(learning_rate)来调整.

2.我们希望模型的权重不全都共享同一个学习率, 这个时候就需要用到第二种方式了:

1).首先将模型的参数分类,每一类都有不同的学习率!!!
def get_1x_lr_params(self):
    modules = [self.backbone]
    for i in range(len(modules)):
        for m in modules[i].named_modules():
            if isinstance(m[1], nn.Conv2d) or isinstance(m[1], SynchronizedBatchNorm2d) \
                    or isinstance(m[1], nn.BatchNorm2d):
                for p in m[1].parameters():
                    if p.requires_grad:
                        yield p

def get_10x_lr_params(self):
    modules = [self.aspp, self.decoder]
    for i in range(len(modules)):
        for m in modules[i].named_modules():
            if isinstance(m[1], nn.Conv2d) or isinstance(m[1], SynchronizedBatchNorm2d) \
                    or isinstance(m[1], nn.BatchNorm2d):
                for p in m[1].parameters():
                    if p.requires_grad:
                        yield p
                        
2).构建一个优化参数列表
def optim_parameters(self, args):
    return [{'params': self.get_1x_lr_params_NOscale(), 'lr': args.learning_rate},
            {'params': self.get_10x_lr_params(), 'lr': 10 * args.learning_rate}]

3).传入模型的参数, 构建优化器
self.optimizer  = torch.optim.SGD(params = self.model.optim_parameters(args))

动态调整优化器的学习率

大多数情况下, 我们还需要动态地调整优化器的学习率,那么该如何操作了:

每一个optimizer的实例都存在一个optimizer.param_groups的属性, 其是一个list类型, 列表中的每个元素都以dict的类型存放. 只需要调整dict中的’lr’项的值即可!!!

构建一个动态调整学习率的函数方法

#计算学习率
def lr_poly(base_lr, iter, max_iter, power):
	return base_lr * ((1 - float(iter) / max_iter) ** (power))
	
#调整学习率, 将optimizer优化器实例传进来即可
def adjust_learning_rate(optimizer, i_iter):
	lr = lr_poly(args.learning_rate, i_iter, args.num_steps, args.power)
	# 修改优化器中的学习率超参数
	optimizer.param_groups[0]['lr'] = lr
	optimizer.param_groups[1]['lr'] = lr * 10

你可能感兴趣的:(PyTorch,深度学习,pytorch)