mxnet 混合编程

  Posted by Mr.Zhang on 24 Jun, 2019

   MXNET    PYTHON   

深度学习几个python库,可以分为命令式编程符号式编程,前者以PyTorch为代表,后者主要是Tensorflow,符号式编程不易理解与调试,所以Keras成为大多数人的选择,目前官方支持中文文档。除此之外,还有一种选择,那就是mxnet,支持两类模式的混合编程,很好很强大。

在设计模型时候,可以符号式方法丢数据进去看看中间量;正式跑参数的时候可以调用hybridize函数加速性能,减少等待时间,十分适合炼丹。官方介绍地址是:

http://zh.gluon.ai/chapter_computational-performance/hybridize.html

感觉太过简略。

一个简单模型设计:

class MLP(gluon.HybridBlock):
    # 使用混合模式,必须继承与HybridBlock类
    def __init__(self, **kwargs):
        super(MLP, self).__init__(**kwargs)
        with self.name_scope():
            self.dense1_1 = nn.Dense(5, activation='sigmoid')
            self.dense1_2 = nn.Dense(66, activation='relu')
            self.dense1_3 = nn.Dense(600, activation='relu')
            self.dense2_1 = nn.Dense(30, activation='relu')
            self.dense2_2 = nn.Dense(60, activation='relu')
            self.dense3 = nn.Dense(30, activation='relu')
            self.dense4 = nn.Dense(30, activation='relu')
            self.dense5 = nn.Dense(12, activation='relu')
            self.dense6 = nn.Dense(1)

    def hybrid_forward(self, F, x):
    # 必须定义hybrid_foward方法,其中F参数类似于Keras中的K参数,基于
    # 模型是那种方式运行,来选择调用`nd`还是`sym`
        x1 = self.dense1_1(F.slice(x, begin=(None, 0), end=(None, 5)))
        # 本模型因为数据集第5~70,71~为两类数据的独热编码,所以要切片
        # 使用命令式编程可以直接[:]符号切片,但符号式编程不支持
        # 所以调用不同F下的slice函数
        x2 = self.dense1_2(F.slice(x, begin=(None, 5), end=(None, 71)))
        x3 = self.dense1_3(F.slice(x, begin=(None, 71), end=(None, None)))
        x4 = self.dense2_1(F.concat(x1,x2,dim=1))
        x5 = self.dense2_2(x3)
        x5 = self.dense3(x5)
        x6 = self.dense4(F.concat(x4,x5,dim=1))
        x7 = self.dense5(x6)
        return self.dense6(x7)

定义完模型,除了实例化和参数初始化,不要忘记调用hybridize函数,否则还是命令式方式执行,达不到符号式的效率

net = MLP()
# 使net实现符号式方法加速
net.hybridize()
# force_reinit这个参数很重要,不然除了第一次初始化,后面不刷新
net.collect_params().initialize(mx.init.Xavier(), 
                                force_reinit=True, 
                                ctx=model_ctx)