我在使用Mxnet训练一个XOR神经网络,但损失值没有下降,始终保持在0.5以上。
以下是我在Mxnet 1.1.0;Python 3.6;OS X El Capitan 10.11.6上的代码
我尝试了两种损失函数 – 平方损失和softmax损失,两者都不起作用。
from mxnet import ndarray as ndfrom mxnet import autogradfrom mxnet import gluonimport matplotlib.pyplot as pltX = nd.array([[0,0],[0,1],[1,0],[1,1]])y = nd.array([0,1,1,0])batch_size = 1dataset = gluon.data.ArrayDataset(X, y)data_iter = gluon.data.DataLoader(dataset, batch_size, shuffle=True)plt.scatter(X[:, 1].asnumpy(),y.asnumpy())plt.show()net = gluon.nn.Sequential()with net.name_scope(): net.add(gluon.nn.Dense(2, activation="tanh")) net.add(gluon.nn.Dense(1, activation="tanh"))net.initialize()softmax_cross_entropy = gluon.loss.SigmoidBCELoss()#SigmoidBinaryCrossEntropyLoss()square_loss = gluon.loss.L2Loss()trainer = gluon.Trainer(net.collect_params(), 'sgd', {'learning_rate': 0.3})train_losses = []for epoch in range(100): train_loss = 0 for data, label in data_iter: with autograd.record(): output = net(data) loss = square_loss(output, label) loss.backward() trainer.step(batch_size) train_loss += nd.mean(loss).asscalar() train_losses.append(train_loss)plt.plot(train_losses)plt.show()
回答:
我在其他地方找到了这个问题的解决方案,所以我将在这里发布答案。
基本上,我原始代码中的问题是多方面的。
- 权重初始化。请注意,我使用了默认初始化
net.initialize()
实际上执行的是
net.initialize(initializer.Uniform(scale=0.07))
显然,这些初始权重太小,网络无法跳出这些权重。因此,解决方法是
net.initialize(mx.init.Uniform(1))
这样做后,网络可以使用sigmoid/tanh
作为激活函数,并使用L2Loss
作为损失函数来收敛。并且它可以与sigmoid
和SigmoidBCELoss
一起工作。然而,它仍然无法与tanh
和SigmoidBCELoss
一起工作,这可以通过下面的第二项来解决。
-
SigmoidBCELoss
必须在输出层使用这两种情况。2.1. 线性激活和
SigmoidBCELoss(from_sigmoid=False)
;2.2. 非线性激活和
SigmoidBCELoss(from_sigmoid=True)
,其中非线性函数的输出落在(0, 1)之间。
在我原始的代码中,当我使用SigmoidBCELoss
时,我使用了全部sigmoid
或全部tanh
。所以只需将输出层的激活函数从tanh
更改为sigmoid
,网络就能收敛。我仍然可以在隐藏层中使用tanh
。
希望这对你有帮助!