异或神经网络,损失不下降
XOR neural network, the losses don't go down
我正在使用 Mxnet 训练 XOR 神经网络,但损失并没有下降,它们始终高于 0.5。
下面是我在 Mxnet 1.1.0 中的代码; Python3.6; OS X 埃尔卡皮坦 10.11.6
我尝试了 2 个损失函数——平方损失和 softmax 损失,都没有用。
from mxnet import ndarray as nd
from mxnet import autograd
from mxnet import gluon
import matplotlib.pyplot as plt
X = nd.array([[0,0],[0,1],[1,0],[1,1]])
y = nd.array([0,1,1,0])
batch_size = 1
dataset = 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()
我在其他地方找到了这个问题,所以我要 post 在这里回答。
基本上,我的原始代码中的问题是 multi-dimensional。
- 权重初始化。请注意,我使用了默认初始化
net.initialize()
实际上是这样
net.initialize(initializer.Uniform(scale=0.07))
显然这些初始权重太小了,网络永远跳不出来。所以修复是
net.initialize(mx.init.Uniform(1))
这样做之后,网络可以收敛使用 sigmoid/tanh
作为 激活 ,并使用 L2Loss
作为 损失函数。它适用于 sigmoid
和 SigmoidBCELoss
。但是,它仍然无法与 tanh
和 SigmoidBCELoss
一起使用,可以通过下面的第二项修复。
SigmoidBCELoss
输出层这2个场景必须用到
2.1。 线性激活和SigmoidBCELoss(from_sigmoid=False)
;
2.2。 Non-linear激活和SigmoidBCELoss(from_sigmoid=True)
,其中non-linear函数的输出落在(0, 1).
在我的原始代码中,当我使用 SigmoidBCELoss
时,我要么使用所有 sigmoid
,要么使用所有 tanh
。所以只需要将输出层的激活值从tanh
改为sigmoid
,网络就可以收敛了。我仍然可以在隐藏层中有 tanh
。
希望对您有所帮助!
我正在使用 Mxnet 训练 XOR 神经网络,但损失并没有下降,它们始终高于 0.5。
下面是我在 Mxnet 1.1.0 中的代码; Python3.6; OS X 埃尔卡皮坦 10.11.6
我尝试了 2 个损失函数——平方损失和 softmax 损失,都没有用。
from mxnet import ndarray as nd
from mxnet import autograd
from mxnet import gluon
import matplotlib.pyplot as plt
X = nd.array([[0,0],[0,1],[1,0],[1,1]])
y = nd.array([0,1,1,0])
batch_size = 1
dataset = 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()
我在其他地方找到了这个问题,所以我要 post 在这里回答。
基本上,我的原始代码中的问题是 multi-dimensional。
- 权重初始化。请注意,我使用了默认初始化
net.initialize()
实际上是这样
net.initialize(initializer.Uniform(scale=0.07))
显然这些初始权重太小了,网络永远跳不出来。所以修复是
net.initialize(mx.init.Uniform(1))
这样做之后,网络可以收敛使用 sigmoid/tanh
作为 激活 ,并使用 L2Loss
作为 损失函数。它适用于 sigmoid
和 SigmoidBCELoss
。但是,它仍然无法与 tanh
和 SigmoidBCELoss
一起使用,可以通过下面的第二项修复。
SigmoidBCELoss
输出层这2个场景必须用到2.1。 线性激活和
SigmoidBCELoss(from_sigmoid=False)
;2.2。 Non-linear激活和
SigmoidBCELoss(from_sigmoid=True)
,其中non-linear函数的输出落在(0, 1).
在我的原始代码中,当我使用 SigmoidBCELoss
时,我要么使用所有 sigmoid
,要么使用所有 tanh
。所以只需要将输出层的激活值从tanh
改为sigmoid
,网络就可以收敛了。我仍然可以在隐藏层中有 tanh
。
希望对您有所帮助!