使用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
相关产品推荐
相关产品推荐

