You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MXNet中SoftmaxOutput加权版本的实现问题

如何在MXNet中为SoftmaxOutput实现类别加权的交叉熵损失?

你的思路是对的——给特定类别赋予更高损失权重来让模型更关注它,但之前的实现方式搞错了方向。SoftmaxOutput本身就支持类别加权,不需要手动去乘输出张量,而且你之前的变量初始化和操作逻辑也有问题,导致了类型错误。

错误原因解析

你之前尝试用broadcast_mul去乘SoftmaxOutput的输出,但SoftmaxOutput是一个集成了损失计算的层:它的前向输出是softmax概率,但损失的计算是在内部完成的。直接修改它的输出不仅不会影响损失权重,反而会因为数据类型不匹配(你用列表初始化Variable的方式不符合要求)抛出错误。更关键的是,这种操作逻辑上就不是在给损失加权,而是在修改模型的预测输出,完全偏离了你的目标。

正确实现方式

SoftmaxOutput提供了专门的weight参数,用来指定每个类别的损失权重。你只需要在创建这个层的时候传入权重数组即可,它会自动在交叉熵损失计算时应用这些权重。

修改后的完整代码

首先是网络定义部分:

import mxnet as mx
mnist = mx.test_utils.get_mnist()
batch_size = 100
train_iter = mx.io.NDArrayIter(mnist['train_data'], mnist['train_label'], batch_size, shuffle=True)
val_iter = mx.io.NDArrayIter(mnist['test_data'], mnist['test_label'], batch_size)

data = mx.sym.var('data')
data = mx.sym.flatten(data=data)
fc1 = mx.sym.FullyConnected(data=data, num_hidden=15)
act1 = mx.sym.Activation(data=fc1, act_type="relu")
fc2 = mx.sym.FullyConnected(data=act1, num_hidden=10)

# 定义类别权重:给数字0设置权重5,其余类别权重1
class_weights = mx.nd.array([5, 1, 1, 1, 1, 1, 1, 1, 1, 1])
# 初始化带权重的SoftmaxOutput层
mlp = mx.sym.SoftmaxOutput(data=fc2, name='softmax', weight=class_weights)

训练代码可以保持你原来的不变:

import logging
logging.getLogger().setLevel(logging.DEBUG) # logging to stdout
# create a trainable module on CPU
mlp_model = mx.mod.Module(symbol=mlp, context=mx.cpu())
mlp_model.fit(train_iter, # train data
eval_data=val_iter, # validation data
optimizer='sgd', # use SGD to train
optimizer_params={'learning_rate':0.1}, # use fixed learning rate
eval_metric='acc', # report accuracy during training
batch_end_callback = mx.callback.Speedometer(batch_size, 100), # output progress for each 100 data batches
num_epoch=1) # train for at most 10 dataset passes

另一种初始化方式(动态权重)

如果你需要后续调整权重,也可以用初始化器来定义权重变量:

# 用Constant初始化器定义类别权重
weight_init = mx.init.Constant([5, 1, 1, 1, 1, 1, 1, 1, 1, 1])
# 创建带权重变量的SoftmaxOutput
mlp = mx.sym.SoftmaxOutput(data=fc2, name='softmax', weight=mx.sym.Variable('class_weights', init=weight_init))

原理说明

当你给SoftmaxOutput传入weight参数后,它在计算交叉熵损失时,会将每个样本的损失值乘以对应类别的权重。比如,当模型错误分类一个数字0的样本时,这个错误带来的损失会是其他类别的5倍,这样模型在训练时会更优先纠正这类错误,从而提升对数字0类别的分类性能。

内容的提问来源于stack exchange,提问作者Miriam Farber

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:51:28