程序员的资源宝库

网站首页 > gitee 正文

#MXNet# SoftmaxOutput 和 LogisticRegressionOutput

sanyeah 2024-04-05 13:06:55 gitee 4 ℃ 0 评论

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)

就是这样。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表