zoukankan      html  css  js  c++  java
  • 逐层指定学习率

    为不同的层指定相应的学习率可能会有些用处,印象中,这个在caffe里面是在定义网络时指定的,用mxnet后一直没用到过。这放一些字符,以备查。

    接口

    思路来自于官网
    但在optimizer.py中,相应的接口为set_lr_mult(self, args_lr_mult)
    其思路是:在 mod._optimizer 内部定义一个字典以记录每个参数的学习率乘子。
    值得注意的是,从程序上来看,这个接口并不是按照层为单位进行学习率设定,而是对具体的参数进行设置(比如:conv1_weight)。


    Nov 5, 2017

    试验的几次都把怀疑目标指向了这个地方,今早测试了下。问题出在set_lr_mult传入的dictionary上,其内容应当包括所有要调整的参数,不能使用单个多次指定的方式


    测试

    # updated on Nov 5, 2017
    import mxnet as mx
    
    M,N=3,3
    num_filter=1
    kernel=mx.nd.array([ [1,2,3],[1,2,3],[1,2,3] ])
    d=mx.sym.Variable('data')
    conv1=mx.sym.Convolution(data=d,kernel=(3,3),num_filter=num_filter,no_bias=False,name='conv1')
    loss=mx.sym.MakeLoss(data=conv1)
    bch_kernel=kernel.reshape((1,1,M,N))
    arg_params={'conv1_weight': bch_kernel}
    mod=mx.mod.Module(symbol=loss,data_names=('data',),label_names=None)
    mod.bind(data_shapes=[ ('data',[1,1,M,N]),])
    mod.init_params()   
    mod.init_optimizer()  
    
    ###################################################
    ################   Solution I  #########################
    ###################################################
    mod._optimizer.set_lr_mult({'conv1_weight':0})              # 单个多次指定->失败
    mod._optimizer.set_lr_mult({'conv1_bias':0})  
    mod._optimizer.sym.list_arguments()
    #['data', 'conv1_weight']
    mod._optimizer.sym.attr_dict()
    #{'conv1': {'no_bias': 'True', 'kernel': '(3, 3)', 'num_filter': '1'}, 'conv1_weight': {'no_bias': 'True', 'kernel': '(3, 3)', 'num_filter': '1'}}
    
    ###   test   ###############
    mod.forward(mx.io.DataBatch([bch_kernel]))
    mod.get_outputs()[0].asnumpy()
    #array([[[[ 0.06028102]]]], dtype=float32)
    
    mod.backward()
    mod.update()
    mod.backward()
    mod.update()
    mod.backward()
    mod.update()
    mod.backward()
    mod.update()
    
    mod.forward(mx.io.DataBatch([bch_kernel]))
    mod.get_outputs()[0].asnumpy()
    #array([[[[-1.61971903]]]], dtype=float32)    !test failed
    
    ###################################################
    ################   Solution II  #########################
    ###################################################
    mod._optimizer.set_lr_mult({'conv1_bias':0,'conv1_weight':0})  # 一次指定完成
    mod._optimizer.sym.list_arguments()
    #['data', 'conv1_weight']
    mod._optimizer.sym.attr_dict()
    #{'conv1': {'no_bias': 'True', 'kernel': '(3, 3)', 'num_filter': '1'}, 'conv1_weight': {'no_bias': 'True', 'kernel': '(3, 3)', 'num_filter': '1'}}
    
    ###   test   ###############
    mod.forward(mx.io.DataBatch([bch_kernel]))
    mod.get_outputs()[0].asnumpy()
    #array([[[[ 0.06028102]]]], dtype=float32)
    
    mod.backward()
    mod.update()
    mod.backward()
    mod.update()
    mod.backward()
    mod.update()
    mod.backward()
    mod.update()
    
    mod.forward(mx.io.DataBatch([bch_kernel]))
    mod.get_outputs()[0].asnumpy()
    #array([[[[ 0.06028102]]]], dtype=float32)    !test OK~
    

    Jul 31, 2018
    最近又要用到这方面的借口了,现在是gluon的江湖,一切向之看齐。
    gluon推出了两个关于优化的接口,一个是固有的 optimizer,另一个是新加入的Trainer
    通常同Trainer作为训练时的接口,但这两个类都接受Opt的参数,于是要检查下之前的设置是否合适。

    1. Trainer在step时调用optimizer中的updater,在update中,首先调用_get_lr获得Paramlr*:
    #  _get_lr(self, index):  from optimizer.py
        ¦   if index in self.param_dict:                                          
        ¦   ¦   lr *= self.param_dict[index].lr_mult 
        ¦   elif index in self.lr_mult:                                           
        ¦   ¦   lr *= self.lr_mult[index]                                                                                                                        
        ¦   elif index in self.idx2name:                                          
        ¦   ¦   lr *= self.lr_mult.get(self.idx2name[index], 1.0)
    

    所以直接在ParamDict里面设置就好:
    用这个:

    import mxnet as mx
    model = mx.gluon.nn.Sequential()
    with model.name_scope():
        model.add(mx.gluon.nn.Embedding(30, 10))
        ¦   model.add(mx.gluon.rnn.LSTM(20))
        ¦   ¦   model.add(mx.gluon.nn.Dense(5, flatten=False))
    d1 = model.collect_params()
    
    model = mx.gluon.rnn.SequentialRNNCell()
    with model.name_scope():
        model.add(mx.gluon.rnn.LSTMCell(20))
        ¦   model.add(mx.gluon.rnn.LSTMCell(20))
    d2 = model.collect_params()
    
    d =  mx.gluon.ParamDict()
    
    d1.setattr('lr_mult',.01)    # 直接设置 lr_mult
    d2.setattr('lr_mult',10)
    d.update(d1)
    d.update(d1)
    
    d['sequential0_dense0_weight'].lr_mult   #  合并后无影响
    d['sequentialrnncell0_lstm0_i2h_weight'].lr_mult
    

    推测mxnet一贯使用引用手法,所以直接合并几个model的ParamDict,不会影响,但合并对于使用统一的Trainer接口却是必要的(不然会需要多个Trainer对应不同的model part)。

  • 相关阅读:
    网络流24题 餐巾计划(DCOJ8008)
    网络流24题 负载平衡(DCOJ8013)
    tyvj1982 武器分配
    bzoj1877 晨跑
    bzoj1834 网络扩容
    草地排水 改了又改(DCOJ6013)
    codevs1033 蚯蚓的游戏问题
    codevs1227 方格取数2
    bzoj1412 狼和羊的故事
    codevs1839 洞穴勘测
  • 原文地址:https://www.cnblogs.com/chenyliang/p/7451824.html
Copyright © 2011-2022 走看看