【问题标题】:MXNET custom loss function and eval_metricMXNET 自定义损失函数和 eval_metric
【发布时间】:2018-01-30 05:44:53
【问题描述】:

如何在 MXNET 中创建自定义损失函数?例如,不是计算一个标签的交叉熵损失(使用标准 mx.sym.SoftmaxOutput 层计算交叉熵损失并返回一个可以作为损失符号传递给拟合函数的符号),我想计算每个可能标签的加权交叉熵损失。 MXNET 教程提到使用

mx.symbol.MakeLoss(scalar_loss_symbol, normalization='batch')

但是,当我使用MakeLoss 函数时,标准的eval_metric - "acc" 不起作用(显然因为模型不知道我的预测概率向量是什么)。因此我需要写我自己的eval_metric

此外,在预测时,我还需要预测概率向量,除非我将最终概率向量与损失符号和block_grad 组合在一起,否则无法访问该概率向量。

【问题讨论】:

    标签: mxnet


    【解决方案1】:

    下面的代码是对 MXNET 教程 http://mxnet.io/tutorials/python/mnist.html 的修改,其中标准 SoftmaxOutput 损失函数被重写为自定义加权损失函数,并编写了所需的自定义 eval_metric。

    import logging
    logging.getLogger().setLevel(logging.DEBUG) 
    import mxnet as mx
    import numpy as np
    mnist = mx.test_utils.get_mnist()
    
    batch_size = 100
    weighted_train_labels =      
    np.zeros((mnist['train_label'].shape[0],np.max(mnist['train_label'])+ 1))
    weighted_train_labels[np.arange(mnist['train_label'].shape[0]),mnist['train_label']] = 1
    train_iter = mx.io.NDArrayIter(mnist['train_data'], {'label':weighted_train_labels}, batch_size, shuffle=True)
    
    weighted_test_labels = np.zeros((mnist['test_label'].shape[0],np.max(mnist['test_label'])+ 1))
    weighted_test_labels[np.arange(mnist['test_label'].shape[0]),mnist['test_label']] = 1
    val_iter = mx.io.NDArrayIter(mnist['test_data'], {'label':weighted_test_labels}, batch_size)
    
    data = mx.sym.var('data')
    # first conv layer
    conv1 = mx.sym.Convolution(data=data, kernel=(5,5), num_filter=20)
    tanh1 = mx.sym.Activation(data=conv1, act_type="tanh")
    pool1 = mx.sym.Pooling(data=tanh1, pool_type="max", kernel=(2,2), stride=(2,2))
    # second conv layer
    conv2 = mx.sym.Convolution(data=pool1, kernel=(5,5), num_filter=50)
    tanh2 = mx.sym.Activation(data=conv2, act_type="tanh")
    pool2 = mx.sym.Pooling(data=tanh2, pool_type="max", kernel=(2,2), stride=(2,2))
    # first fullc layer
    flatten = mx.sym.flatten(data=pool2)
    fc1 = mx.symbol.FullyConnected(data=flatten, num_hidden=500)
    tanh3 = mx.sym.Activation(data=fc1, act_type="tanh")
    # second fullc
    fc2 = mx.sym.FullyConnected(data=tanh3, num_hidden=10)
    # softmax loss
    #lenet = mx.sym.SoftmaxOutput(data=fc2, name='softmax')
    
    label = mx.sym.var('label')
    softmax = mx.sym.log_softmax(data=fc2)
    softmax_output = mx.sym.BlockGrad(data = softmax,name = 'softmax')
    ce = ce = -mx.sym.sum(mx.sym.sum(mx.sym.broadcast_mul(softmax,label),1))
    lenet = mx.symbol.MakeLoss(ce, normalization='batch')
    
    sym = mx.sym.Group([softmax_output,lenet])
    print sym.list_outputs 
    
    def custom_metric(label,softmax):
        return len(np.where(np.argmax(softmax,1)==np.argmax(label,1))[0])/float(label.shape[0])
    
    eval_metrics = mx.metric.CustomMetric(custom_metric,name='custom-accuracy', output_names=['softmax_output'],label_names=['label'])
    
    lenet_model = mx.mod.Module(symbol=sym, context=mx.gpu(),data_names=['data'], label_names=['label'])
    lenet_model.fit(train_iter,
                    eval_data=val_iter,
                    optimizer='sgd',
                    optimizer_params={'learning_rate':0.1},
                    eval_metric=eval_metrics,#mx.metric.Loss(),#'acc',
                    #batch_end_callback = mx.callback.Speedometer(batch_size, 100),
                    num_epoch=10)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-19
      • 2017-04-04
      • 2017-12-18
      • 2020-03-27
      • 2020-11-16
      • 2019-05-27
      • 2020-02-02
      相关资源
      最近更新 更多