Нейронная сеть XOR, потери не уменьшаются

Я использую Mxnet для обучения нейронной сети XOR, но потери не уменьшаются, они всегда выше 0,5.

Ниже мой код в Mxnet 1.1.0; Питон 3.6; ОС Х Эль-Капитан 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()

person Kun Hu    schedule 01.04.2018    source источник
comment
Пробовали ли вы уменьшить скорость обучения?   -  person Sahil    schedule 01.04.2018
comment
@Sahil Да, от 0,01 до 0,5 результирующие потери всегда выше 0,5.   -  person Kun Hu    schedule 01.04.2018


Ответы (1)


Я разобрался с этим вопросом в другом месте, поэтому я собираюсь опубликовать ответ здесь.

По сути, проблема в моем исходном коде была многомерной.

  1. Инициализация веса. Обратите внимание, что я использовал инициализацию по умолчанию

сеть.инициализировать()

что на самом деле делает

net.initialize (инициализатор. Униформа (масштаб = 0,07))

Видимо, эти начальные веса были слишком малы, и сеть никогда не могла из них выпрыгнуть. Итак, исправление

net.initialize(mx.init.Uniform(1))

После этого сеть может сходиться, используя sigmoid/tanh в качестве активации и используя L2Loss в качестве функции потерь. И это работало с sigmoid и SigmoidBCELoss. Однако с tanh и SigmoidBCELoss все равно не работало, что можно исправить вторым пунктом ниже.

  1. SigmoidBCELoss необходимо использовать в этих двух сценариях на выходном слое.

    2.1. Линейная активация и SigmoidBCELoss(from_sigmoid=False);

    2.2. Нелинейная активация и SigmoidBCELoss(from_sigmoid=True), при которых выход нелинейной функции попадает в (0, 1).

В моем исходном коде, когда я использовал SigmoidBCELoss, я использовал либо все sigmoid, либо все tanh. Так что просто нужно изменить активацию в выходном слое с tanh на sigmoid, и сеть сможет сходиться. У меня все еще может быть tanh в скрытых слоях.

Надеюсь это поможет!

person Kun Hu    schedule 03.04.2018