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

使用Neuroph实现神经网络多分类时输出概率和不为1的问题排查

问题:Neuroph实现SoftMax输出和不为1的问题

我是神经网络领域的新手,尝试使用Java的Neuroph库实现一个基于Multilayer Perceptron的基础多分类神经网络。参考谷歌机器学习指南,我在输出层前添加了SoftMax层,期望输出为概率分布(和为1),但实际输出的概率和略大于或小于1。

实现代码

public static void main(String[] args) {
        final MultiLayerPerceptron neuralNetwork = new MultiLayerPerceptron(2, 3, 3, 3);
        
        final BackPropagation rule = new BackPropagation();
        rule.setLearningRate(0.1);
        rule.setMaxError(0.001);
        rule.setMaxIterations(10000);
        
        neuralNetwork.setLearningRule(rule);
        
        final Layer softMaxLayer = neuralNetwork.getLayerAt(neuralNetwork.getLayersCount() - 2);
        final SoftMax max = new SoftMax(softMaxLayer);

        for (Neuron n : softMaxLayer.getNeurons()) 
            n.setTransferFunction(max);
        
//      for (Neuron n : this.getOutputNeurons())
//          n.setTransferFunction(new Linear());

        DataSet trainingSet = new DataSet(2, 3);
        
        // Output contains only one instance of "1" to represent the class it belongs to
        trainingSet.add(new double[]{0, 0}, new double[]{1, 0, 0});
        trainingSet.add(new double[]{0, 0}, new double[]{1, 0, 0});
        trainingSet.add(new double[]{0, 0}, new double[]{1, 0, 0});
        trainingSet.add(new double[]{0, 1}, new double[]{0, 1, 0});
        trainingSet.add(new double[]{0, 1}, new double[]{1, 0, 0});
        trainingSet.add(new double[]{1, 0}, new double[]{0, 0, 1});
        trainingSet.add(new double[]{1, 1}, new double[]{0, 0, 1});
        trainingSet.add(new double[]{1, 1}, new double[]{0, 1, 0});
        trainingSet.add(new double[]{1, 1}, new double[]{0, 1, 0});
        
        // Train the neural network on the training set
        neuralNetwork.learn(trainingSet);

        // Test the neural network on a new example
        neuralNetwork.setInput(0, 1);
        neuralNetwork.calculate();
        double[] output = neuralNetwork.getOutput();
        
        System.out.println(output[0]); // prints the probability of class 0
        System.out.println(output[1]); // prints the probability of class 1
        System.out.println(output[2]); // prints the probability of class 2
        
        System.out.println("\n\nTotal (=1?): " + (output[0] + output[1] + output[2]));
        System.out.println(neuralNetwork.getLearningRule().getTotalNetworkError());
    }

示例输出

0.8514345496167552
0.23687369660618554
0.001890247376537854


Total (=1?): 1.0901984935994786
0.17265593270797627

(前三行是三个输出神经元的值,随后是它们的总和,最后是网络总误差)

我猜测自己犯了基础错误,恳请指出问题所在。


问题分析与解决办法
  • SoftMax层位置错误
    你把SoftMax设置在了倒数第二层,而非输出层。SoftMax的作用是将输出层的原始得分转换为和为1的概率分布,必须直接作为输出层的激活函数。当前结构中,输出层仍使用默认激活函数(如Sigmoid),会破坏SoftMax的归一化效果,导致输出和偏离1。

  • 输出层激活函数未正确配置
    不需要保留注释的Linear激活函数代码,直接将SoftMax应用到输出层即可。Neuroph的SoftMax是层级关联的,需要绑定到输出层后再设置给每个神经元。

修正后的关键代码:

// 获取输出层(最后一层)
final Layer outputLayer = neuralNetwork.getLayerAt(neuralNetwork.getLayersCount() - 1);
final SoftMax softMax = new SoftMax(outputLayer);

for (Neuron n : outputLayer.getNeurons()) 
    n.setTransferFunction(softMax);
  • 训练数据存在矛盾样本
    你的训练数据中有输入对应多个不同标签的情况(比如{0,1}同时对应类别0和类别1),这种矛盾会导致网络无法收敛到低误差,输出不稳定,进一步放大SoftMax的偏差。建议清理数据,确保每个输入对应明确的标签,或为冲突样本设置权重。

  • 浮点数精度偏差
    即使配置正确,浮点数计算的精度限制可能会让输出和有微小偏差(如1.0000001),但不会出现示例中0.09的大幅偏差,这种情况主要还是层位置错误导致的。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 02:50:28