美文网首页
mxnet module 解析

mxnet module 解析

作者: 迷途的Go | 来源:发表于2018-01-31 23:54 被阅读0次

    mxnet module.py类

    module.py是一个重要的类,一个完整的训练过程都要经过这个类

    构建模型

    >>> data = mx.sym.Variable('data')
    >>> fc1  = mx.sym.FullyConnected(data, name='fc1', num_hidden=128)
    >>> act1 = mx.sym.Activation(fc1, name='relu1', act_type="relu")
    >>> fc2  = mx.sym.FullyConnected(act1, name='fc2', num_hidden=10)
    >>> out  = mx.sym.SoftmaxOutput(fc2, name = 'softmax')
    >>> mod = mx.mod.Module(out)
    >>> out
    <Symbol softmax>
    >>> mod
    <mxnet.module.module.Module object at 0x7f52df417c50>
    >>>
    

    上述使用符号式编程构建了一个计算图,SoftmaxOutput带了loss

    bind

    假设这里已经加载出imagenet的数据集data_set, 包含两个MXDataIter的数据,一个train,一个val,

    >>> mod.bind(data_shapes=train.provide_data, label_shapes=train.provide_label)
    
    >>> data_shapes
    [DataDesc[data,(128L, 3L, 224L, 224L),<type 'numpy.float32'>,NCHW]]
    >>> mod.bind(data_shapes=train.provide_data, label_shapes=train.provide_label)
    >>> label_shapes = train.provide_label
    >>> label_shapes
    [DataDesc[softmax_label,(128L,),<type 'numpy.float32'>,NCHW]]
    

    把初始化module时候的symbols绑定到construct executors,并初始化内存

    bind首先得到DataDesc类型的_data_shape,_label_shape(通过参数传递进来),_symbol,_context(初始化的时候得到),这些参数传给DataParallelExecutorGroup, 得到_exec_group对象,这是个重要的对象,如果参数已经初始化,就将初始化后参数和辅助参数设置给_exec_group对象

    下面整理一下executor_group.py这个类及其所对应的对象DataParallelExecutorGroup

    接收参数:

    • symbol,构建的模型计算图
    • context,设备,mx.cpu(),mx.gpu(0),mx.gpu(1)...
    • data_shapes,DataDesc类型,包括了数据的形状
    • label_shape,同上
    • param_names,详情见下方的解释
    • 其他参数...

    全局变量:

    • param_names,参数的名称,用户定义模型的时候如果写了name,系统会自动在name后加上weight,bias,gamma,beta等参数,可以理解为卷积核的名称
     000 = {str} 'bn_data_gamma'
     001 = {str} 'bn_data_beta'
     002 = {str} 'conv0_weight'
     003 = {str} 'bn0_gamma'
     004 = {str} 'bn0_beta'
     005 = {str} 'stage1_unit1_bn1_gamma'
     006 = {str} 'stage1_unit1_bn1_beta'
     007 = {str} 'stage1_unit1_conv1_weight'
     008 = {str} 'stage1_unit1_bn2_gamma'
     009 = {str} 'stage1_unit1_bn2_beta'
     010 = {str} 'stage1_unit1_conv2_weight'
     011 = {str} 'stage1_unit1_bn3_gamma'
     .
     .
     .
     151 = {str} 'stage4_unit3_bn3_beta'
     152 = {str} 'stage4_unit3_conv3_weight'
     153 = {str} 'bn1_gamma'
     154 = {str} 'bn1_beta'
     155 = {str} 'fc1_weight'
     156 = {str} 'fc1_bias'
    
    • arg_names-从symbol拿出所有的参数的名称,这个和param_names应该是一模一样的,不知道为什么会重复来一个
    • aux_names
    self.aux_names = {list} <type 'list'>: ['bn_data_moving_mean', 'bn_data_moving_var', 'bn0_moving_mean', 'bn0_moving_var', 'stage1_unit1_bn1_moving_mean', 'stage1_unit1_bn1_moving_var', 'stage1_unit1_bn2_moving_mean', 'stage1_unit1_bn2_moving_var', 'stage1_unit1_bn3_moving_mean', 
     __len__ = {int} 102
     000 = {str} 'bn_data_moving_mean'
     001 = {str} 'bn_data_moving_var'
     002 = {str} 'bn0_moving_mean'
     003 = {str} 'bn0_moving_var'
     004 = {str} 'stage1_unit1_bn1_moving_mean'
     005 = {str} 'stage1_unit1_bn1_moving_var'
     006 = {str} 'stage1_unit1_bn2_moving_mean'
     007 = {str} 'stage1_unit1_bn2_moving_var'
     098 = {str} 'stage4_unit3_bn3_moving_mean'
     099 = {str} 'stage4_unit3_bn3_moving_var'
     100 = {str} 'bn1_moving_mean'
     101 = {str} 'bn1_moving_var'
    
    • symbol,计算图
    • workload,不明白是个什么,可能是设备相关吧,打印出来
    self.workload = {list} <type 'list'>: [1, 1, 1, 1]
     __len__ = {int} 4
     0 = {int} 1
     1 = {int} 1
     2 = {int} 1
     3 = {int} 1
    
    • for_training,是否训练
    • 输入数据是否需要梯度
    • _total_exec_bytes每个设备所占的显存,一个工具变量,profiler会用到
    • fixed_param_names,指定哪些操作的参数固定住不动
    • slices,数据被分成多少分,最外层所有的batch_size被分成GPU个数的等分,在batch_size的维度划分
    • execs, Executor对象,有多少个设备就有多少个该对象
    • _default_execs,默认的executor对象,默认是空
    • data_array,输入的数据,但是这里全是0,应该是一个占位符,根据shape初始化内存用的
    • label_arrays,同上
    • param_arrays,参数被全部初始化为0,这些参数在executor_group.py的bind_exec执行完后得以初始化
    • state_arrays,不知道是啥
    • grad_arrays,形状与param_arrays一样,grad_arrays更新param_arrays
    • aux_arrays
    • input_grad_arrays
    • self.data_shapes,输入数据的大小
    • label_shapes,同上
    • data_names,输入数据的名称,一般是'data'
    • label_names,输入label的名称,一般是'softmax_label'
    • data_layouts
    • label_layouts
    • output_names
    • output_layouts
    • num_outputs, resnet50是一个,应该是输出,可能是最终的输出,目前不知道

    execs-mxnet.executor.Executor对象,有几个设备就有几个对象,比如四个GPU,就四个这样对象的列表

    grad_arrays-也绑定在各个设备上,目测是用于更新参数的梯度,每个GPU计算自己的梯度

    param_names-参数列表名称,比如每个卷积的卷积核weight, bias

    有计算图symbol,data_shape,label_shape,那么整个网络的细节就已经清楚

    • _bind_ith_exec方法

    grad_requirement, 'write', 'add'或'null',add是把所有的梯度加起来,wirte是什么操作?

    symbol.py的check_call(_LIB.MXExecutorSimpleBind())这个函数干了什么?

    该方法内部根据设备的个数得到executor,初始化一个executor会初始化参数和辅助参数

    执行完bind_exec的_collect_arrays,executor_group的data_arrays得到初始化

    init_params

    执行完init_params函数,module对象的_exec_group变量的param_arrays对象就不再全部是0,而是用户传递进来的, init_params直接调用_exec_group对象的set_params方法,然后对每个executor执行初始化

    init_optimizer

    module的init_optimizer方法根据用户传递进来的optimier的字符串和参数,通过optimizer.py创建一个optimizer对象

    此外该方法初始化了kvstore,_initialize_kvstore,这个还没有弄明白

    forward

    module.py->forward()->executor_group.py->forward->为每一个设备的Executor执行forward->executor.py->forward,这里调用C++的MXExecutorForward,执行后,executor.py的self.outputs得到输出,每个输出的大小是32x1000,每一张图片一次前向计算得到1000个概率值,代表该次计算是某一个类的概率

    backword

    module.py->backward->executor_group.py->backward()->executor.py->MXExecutorBackwardEx(),执行反向计算,反向计算得到梯度self.grad_arrays,存储在每一个executor对象

    update

    通过optimizer更新梯度到参数,梯度是之前前向-后向计算得到的张量,DataParallelExecutorGroup对象持有设备数量个Executor,每个executor对象持有一个分grad_arrays,这个地方有些疑惑,update方法传递进去的是_exec_group.grad_arrays, 将每一个executor上的梯度传递给_exec_group.grad_arrays的方法_collect_arrays只有bind_exec的时候执行过一次,backward方法完了并没有看到_exec_group去收集各个executor的梯度。--这个问题的可能解释是bind执行的那次把每一个executor的梯度给 exec_group的梯度是指针或者引用,那每次更新了每个executor的梯度,exec_group的梯度值自然就得到了更新

    最终梯度聚合在kvstore_dist.h的Push_方法里将梯度相加

    和C++怎么交互的还没看明白,看明白的大神请给我留个文章链接,我来研究研究

    参考http://www.cnblogs.com/heguanyou/p/7604326.html

    相关文章

      网友评论

          本文标题:mxnet module 解析

          本文链接:https://www.haomeiwen.com/subject/qmjrzxtx.html