optim 的基本使用
for do:
 1. 计算loss
 2. 清空梯度
 3. 反传梯度
 4. 更新参数
cifiron = nn.MSELoss()
optimiter = torch.optim.SGD(net.parameters(),lr=0.01,momentum=0.9)
for i in range(iters):
    out = net(inputs)
    loss = cifiron(out,label)
    optimiter.zero_grad()  # 清空之前保留的梯度信息
    loss.backward()   # 将mini_batch 的loss 信息反传回去
	optimiter.step()  # 根据 optim参数 和 梯度 更新参数 w.data -= w.grad*lr
  如何将网络参数分组设置学习策略
如下代码就将optimizer的可更新参数分为不同的三组,每组使用不同的策略
   optimizer = torch.optim.SGD([
            {'params': other_params}, 
            {'params': first_params, 'lr': 0.01*args.learning_rate},
            {'params': second_params, 'weight_decay': args.weight_decay}],
            lr=args.learning_rate,
            momentum=args.momentum,
    )
  具体实现
- 我们拿SGD举例,首先看一下,optim.step 更新函数的具体操作
 - 可见,
for group in self.param_groups,optim中存在一个param_groups的东西,其实它就是我们传进去的param_list,比如我们上面传进去一个长度为3的param_list,那么len(optimizer.param_groups)==3, 而每一个group又是一个dict, 其中包含了 每组参数所需的必要参数optimizer.param_groups:长度2的list,optimizer.param_groups[0]:长度6的字典 - 然后取回每组 所需更新的参数
for p in group['params'],根据设置 计算其 正则化 及 动量累积,然后更新参数w.data -= w.grad*lr
optimizer.param_groups[0]的组成字典,当前组没有专门设置lr等信息,则使用默认的optim初始化设置 
def step(self, closure=None):
        loss = None
        if closure is not None:
            loss = closure()
        for group in self.param_groups:
        	# 本组参数更新所必需的 参数设置
            weight_decay = group['weight_decay']
            momentum = group['momentum']
            dampening = group['dampening']
            nesterov = group['nesterov']
            for p in group['params']:  # 本组所有需要更新的参数 params
                if p.grad is None:  # 如果没有梯度 则直接下一步
                    continue
                d_p = p.grad.data
                # 正则化 及 动量累积 操作
                if weight_decay != 0:
                    d_p.add_(weight_decay, p.data)
                if momentum != 0:
                    param_state = self.state[p]
                    if 'momentum_buffer' not in param_state:
                        buf = param_state['momentum_buffer'] = torch.clone(d_p).detach()
                    else:
                        buf = param_state['momentum_buffer']
                        buf.mul_(momentum).add_(1 - dampening, d_p)
                    if nesterov:
                        d_p = d_p.add(momentum, buf)
                    else:
                        d_p = buf
				# 当前组 学习参数 更新 w.data -= w.grad*lr
                p.data.add_(-group['lr'], d_p)
        return loss
  如何获取指定参数
- 可以使用
model.named_parameters()取回所有参数,然后设定自己的筛选规则,将参数分组 - 取回分组参数的id 
map(id, weight_params_list) - 取回剩余分特殊处置参数的id 
other_params = list(filter(lambda p: id(p) not in params_id, all_params)) 
    all_params = model.parameters()
    weight_params = []
    quant_params = []
    # 根据自己的筛选规则 将所有网络参数进行分组
    for pname, p in model.named_parameters():
        if any([pname.endswith(k) for k in ['cw', 'dw', 'cx', 'dx', 'lamb']]):
            quant_params += [p]
        elif ('conv' or 'fc' in pname and 'weight' in pname):
            weight_params += [p]    
	# 取回分组参数的id
    params_id = list(map(id, weight_params)) + list(map(id, quant_params))
    # 取回剩余分特殊处置参数的id
    other_params = list(filter(lambda p: id(p) not in params_id, all_params))
	# 构建不同学习参数的优化器
	optimizer = torch.optim.SGD([
            {'params': other_params}, 
            {'params': quant_params, 'lr': 0.1*args.learning_rate},
            {'params': weight_params, 'weight_decay': args.weight_decay}],
            lr=args.learning_rate,
            momentum=args.momentum,
    )
  获取指定层的参数id
# # 以层为单位,为不同层指定不同的学习率
# ## 提取指定层对象
special_layers = t.nn.ModuleList([net.classifiter[0], net.classifiter[3]])
# ## 获取指定层参数id
special_layers_params = list(map(id, special_layers.parameters()))
print(special_layers_params)
# ## 获取非指定层的参数id
base_params = filter(lambda p: id(p) not in special_layers_params, net.parameters())
optimizer = t.optim.SGD([{'params': base_params},
                         {'params': special_layers.parameters(), 'lr': 0.01}], lr=0.001)



京公网安备 11010502036488号