• #MXNet# SoftmaxOutput 和 LogisticRegressionOutput


    Introduction

    已经有一段时间了,Softmax的问题没有解决。比如分类的时候,看大家似乎都用的SoftmaxOutput作为Loss Op,传入了两个参数(i.e.: datalabel),照理说应该输出loss的值;也就是说作为Loss应该输出的是一个标量(bachsize=1的时候),然后我常会去想这样做后期进行predict要花些功夫把原本的预测值找出来。但发现最后做Metric 的时候却把output直接拿来和label对比,比如下面这段:

    # python/mxnet/module/module.py     update_metric()
    # --->
    # python/build/lib.linux-x86_64-2.7/mxnet/module/executor_group.py
        def update_metric(self, eval_metric, labels):                                                                                             
            for texec, islice in zip(self.execs, self.slices):
                labels_slice = []
                for label, axis in zip(labels, self.label_layouts):
                    if axis == 0:
                        # slicing NDArray along axis 0 can avoid copying
                        labels_slice.append(label[islice])
                    elif axis > 0:
                        # pylint: disable=no-member
                        label_my_slice = nd.slice_axis(label, axis=axis, begin=islice.start,
                                                       end=islice.stop).as_in_context(label.context)
                        # pylint: enable=no-member
                        labels_slice.append(label_my_slice)
                    else:
                        labels_slice.append(label)
    
                eval_metric.update(labels_slice, texec.outputs)
    
    #   eval_metric   与  python/mxnet/metric.py  有关
    
    class CustomMetric(EvalMetric):   # 随机选一个参考
        ...
        def update(self, labels, preds):
            if not self._allow_extra_outputs:
                check_label_shapes(labels, preds)
    
            for pred, label in zip(preds, labels):
                label = label.asnumpy()
                pred = pred.asnumpy()
    
                if pred.shape[1] == 2:
                    pred = pred[:, 1]
    
                reval = self._feval(label, pred)
                if isinstance(reval, tuple):
                    (sum_metric, num_inst) = reval
                    self.sum_metric += sum_metric
                    self.num_inst += num_inst
                else:
                    self.sum_metric += reval                                                                                                     
                    self.num_inst += 1
    
    
    

    最近又遇到了也走这条道的LogisticRegressionOutput,终于要打算解决了。
    现在解决这个问题的一个优势是,之前从MakeLoss中参到了一些,后面又发现了BlockGrad的功用。

    Assumption

    从这两个Op可以大致猜到两个Output

    1. data的值做处理,结果作为output
    2. 然后又对datalabel的distancee进行了计算,目的是得到grad,这就是说真正的标量loss被掩盖了,要的只是由此产生的gradient

    Experiments

    做个验证:

    
    import mxnet as mx
    import numpy as np
    m=mx.nd.ones((3,4))
    n=mx.nd.zeros((3,4))
    
    vm=mx.sym.Variable('m')
    vn=mx.sym.Variable('n')
    
    
    out=mx.nd.LogisticRegressionOutput(m,n)   # 顺手做下 NDArray 类型
    out.asnumpy()
    #array([[ 0.7310586,  0.7310586,  0.7310586,  0.7310586],
    #       [ 0.7310586,  0.7310586,  0.7310586,  0.7310586],
    #       [ 0.7310586,  0.7310586,  0.7310586,  0.7310586]], dtype=float32)            exp(1)  /  ( 1+exp(1) )
    
    
    out=mx.sym.LogisticRegressionOutput(data=vm,label=vn)
    exec_ = out.bind(mx.cpu(),{'m':m,'n':n})
    exec_.forward()
    exec_.outputs[0].asnumpy() 
    #array([[ 0.7310586,  0.7310586,  0.7310586,  0.7310586],
    #       [ 0.7310586,  0.7310586,  0.7310586,  0.7310586],
    #       [ 0.7310586,  0.7310586,  0.7310586,  0.7310586]], dtype=float32)
    
    
    
    m=mx.nd.ones((3,4))+.3
    n=mx.nd.zeros((3,4))+0.2
    out=mx.sym.LogisticRegressionOutput(data=vm,label=vn)
    exec_ = out.bind(mx.cpu(),{'m':m,'n':n})
    exec_.forward()
    exec_.outputs[0].asnumpy()
    #array([[ 0.78583497,  0.78583497,  0.78583497,  0.78583497],
    #       [ 0.78583497,  0.78583497,  0.78583497,  0.78583497],
    #       [ 0.78583497,  0.78583497,  0.78583497,  0.78583497]], dtype=float32)       exp(1.3) / (1+exp(1.3))
    
    
    
    ##########################
    #   看看  SoftmaxOutput       这编辑器 orz...
    ##########################
    
    m=mx.nd.ones((3,4))
    n=mx.nd.zeros((3,4))+0.7        
    
    
    out=mx.sym.SoftmaxOutput(data=vm,label=vn)
    exec_ = out.bind(mx.cpu(),{'m':m,'n':n})
    exec_.forward()
    exec_.outputs[0].asnumpy()
    #array([[ 0.25,  0.25,  0.25,  0.25],
    #       [ 0.25,  0.25,  0.25,  0.25],
    #       [ 0.25,  0.25,  0.25,  0.25]], dtype=float32)
    
    
    
    
    m=mx.nd.ones((3,4))
    n=mx.nd.zeros((3,4))+0.2                                       #  改变 label 的值
    out=mx.sym.SoftmaxOutput(data=vm,label=vn)
    exec_ = out.bind(mx.cpu(),{'m':m,'n':n})
    exec_.forward()
    exec_.outputs[0].asnumpy()   
    #array([[ 0.25,  0.25,  0.25,  0.25],
    #       [ 0.25,  0.25,  0.25,  0.25],
    #       [ 0.25,  0.25,  0.25,  0.25]], dtype=float32)          输出没变
    
    
    
    m=mx.nd.uniform(0,1,(3,4))                                    # 随机数
    n=mx.nd.zeros((3,4))+0.2                                       
    out=mx.sym.SoftmaxOutput(data=vm,label=vn)
    exec_ = out.bind(mx.cpu(),{'m':m,'n':n})
    exec_.forward()
    exec_.outputs[0].asnumpy()   
    #array([[ 0.24227935,  0.21061647,  0.38156345,  0.16554071],
    #       [ 0.37370193,  0.1872514 ,  0.20918882,  0.22985782],
    #       [ 0.28395435,  0.28981918,  0.21832471,  0.20790176]], dtype=float32)
    
    

    就是这样。

  • 相关阅读:
    FileItem类的常用方法
    spring mvc(注解)上传文件的简单例子
    Linux下安装Tomcat服务器和部署Web应用
    防止表单重复提交的几种策略
    Rancher 2.0 学习目录
    Prometheus 学习目录
    k8s学习目录
    python之路——目录
    Mac OS X生成RSA公钥和私钥
    Django设置 DEBUG=False后静态文件无法加载解决
  • 原文地址:https://www.cnblogs.com/chenyliang/p/6795031.html
Copyright © 2020-2023  润新知