基于R语言的MxNet:简易XOR神经网络无法训练
解决MxNet中XOR神经网络训练失败的问题
你遇到的XOR训练失败问题,大多是因为XOR是典型的非线性问题,单层线性模型根本无法拟合,再加上可能的激活函数、损失函数或训练参数设置不当导致的。我给你整理了一个可直接运行的MxNet版本XOR神经网络脚本,同时拆解关键调整点:
可运行的完整代码
import mxnet as mx from mxnet import gluon, nd, autograd # 准备XOR数据集 X = nd.array([[0, 0], [0, 1], [1, 0], [1, 1]]) y = nd.array([[0], [1], [1], [0]]) # 定义带隐藏层的神经网络 net = gluon.nn.Sequential() with net.name_scope(): # 隐藏层:2个神经元,用sigmoid引入非线性(ReLU也可以) net.add(gluon.nn.Dense(2, activation='sigmoid')) # 输出层:1个神经元,sigmoid输出0-1之间的概率值 net.add(gluon.nn.Dense(1, activation='sigmoid')) # 初始化网络参数(用正态分布初始化) net.initialize(mx.init.Normal(sigma=0.01)) # 定义损失函数和优化器 # 因为输出已经过sigmoid激活,所以设置from_sigmoid=True避免重复计算 loss_fn = gluon.loss.SigmoidBinaryCrossEntropyLoss(from_sigmoid=True) # 用SGD优化器,学习率设为0.5(这个值在XOR任务中收敛效果不错) trainer = gluon.Trainer(net.collect_params(), 'sgd', {'learning_rate': 0.5}) # 开始训练 epochs = 10000 for epoch in range(epochs): with autograd.record(): # 前向传播计算输出 output = net(X) # 计算损失 loss = loss_fn(output, y) # 反向传播求梯度 loss.backward() # 更新参数(传入批量大小,这里是4) trainer.step(X.shape[0]) # 每1000轮打印一次损失 if epoch % 1000 == 0: print(f"第{epoch}轮训练,损失值:{loss.mean().asscalar():.4f}") # 测试训练好的模型 print("\n测试结果:") predictions = net(X) for idx in range(4): input_data = X[idx].asnumpy() pred = predictions[idx].asscalar() true_label = y[idx].asscalar() print(f"输入:{input_data},预测值:{pred:.4f},真实值:{true_label}")
关键调整点说明
- 必须加隐藏层:XOR是非线性问题,单层感知器(没有隐藏层)完全无法拟合,所以我们加入了一个带非线性激活的隐藏层,这是解决问题的核心。
- 非线性激活函数:隐藏层和输出层都用了
sigmoid(你也可以换成relu,效果类似),只有引入非线性,模型才能学习到XOR的逻辑关系。 - 匹配的损失函数:因为是二分类任务,用
SigmoidBinaryCrossEntropyLoss比MSE损失更合适,而且我们已经在输出层用了sigmoid,所以设置from_sigmoid=True来优化计算。 - 合适的训练参数:
- 学习率设为0.5:这个值既能保证收敛速度,又不会因为太大导致参数震荡。如果用Adam优化器,可以把学习率调低到0.01。
- 训练轮数设为10000:XOR需要足够多的迭代才能让参数收敛,几百轮可能还看不到明显效果。
- 数据格式正确:确保输入和输出都是MxNet的
NDArray,形状匹配(输入是(4,2),输出是(4,1))。
运行这个脚本后,你会看到损失值逐渐下降,最终测试时的预测值会非常接近真实标签(比如输入[0,0]的预测值接近0,[0,1]接近1)。
内容的提问来源于stack exchange,提问作者vaka
相关产品推荐
相关产品推荐

