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

生成式神经网络:求替代Softmax的输出和为1的归一化层

解决方案:自定义总和归一化层替代连续Softmax

嘿,完全懂你的需求——既要靠ReLU拿到真实的零值稀疏性,又要让输出总和为1,还得避开连续用Softmax导致的输出极端化问题对吧?

先说说为什么你原来的做法会出问题:第一次Softmax已经把输出压缩到0-1区间且总和为1了,接着用ReLU其实不会改变任何值(因为Softmax输出本来就非负),再套一次Softmax的话,会把原本就小的数值进一步压到几乎为0,大数值则被放大到接近1,直接导致输出极端化,完全背离了你想要保留稀疏性同时温和归一化的目标。

那该怎么解决?其实你需要的就是一个简单的总和归一化层——直接让每个输出元素除以所有输出的总和,这样既保留ReLU带来的真实零值,又能让输出总和为1,而且不会引入Softmax的指数运算带来的极端化问题。

下面是在TensorFlow/Keras里实现这个自定义层的代码:

from tensorflow.keras.layers import Layer
import tensorflow as tf

class SumNormalization(Layer):
    def __init__(self, epsilon=1e-8, **kwargs):
        self.epsilon = epsilon  # 防止总和为0时除零错误
        super().__init__(**kwargs)
    
    def call(self, inputs):
        # 计算最后一维的总和(假设你的输出是(batch_size, 200))
        sum_total = tf.reduce_sum(inputs, axis=-1, keepdims=True) + self.epsilon
        # 每个元素除以总和实现归一化
        return inputs / sum_total
    
    def get_config(self):
        # 保存层的配置,方便模型序列化
        config = super().get_config()
        config['epsilon'] = self.epsilon
        return config

然后把你原来的代码改成这样就可以了:

outputs = Dense(200, activation='softmax', activity_regularizer=l1(1e-5))(x)
outputs = Activation('relu')(outputs)  # 得到真实的零值稀疏性
outputs = SumNormalization()(outputs)  # 归一化到总和为1,完美保留零值

这个层的优势很明显:

  • 完全保留ReLU后的真实零值,不会像Softmax那样把接近0的值变成非零
  • 只是线性的除法操作,不会放大输出之间的差异,避免极端化
  • 简单易懂,没有复杂的运算,训练时数值稳定性更好

如果你的输出总和有可能为0(比如ReLU把所有元素都变成0了),可以调整epsilon参数的大小,默认的1e-8已经足够应对绝大多数情况啦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:32:28