【问题标题】:Training neural network with Apache mxnet (gluon) causes program to crash使用 Apache mxnet (gluon) 训练神经网络会导致程序崩溃
【发布时间】:2018-01-31 12:00:47
【问题描述】:

我正在尝试使用 Gluon API 对一组我想要分类的图像使用 mxnet 训练卷积神经网络。但是,相同的网络和代码有时会为相同的数据输出截然不同的结果,有时会因为某种原因简单地崩溃并拒绝运行。这是我的代码:

附加信息:

图像全部为 131 x 131 像素大小,每类 176 个图像(2 个类),每类 40 个测试。我很困惑为什么相同数据的相同程序有时会给出输出但否则会崩溃。

进口

from __future__ import print_function
import mxnet as mx
import numpy as np
from mxnet import nd, autograd, gluon
import time
mx.random.seed(1)

设置上下文

ctx = mx.cpu()

定义回调变换函数

def transform(data, label):
    return nd.transpose(data.astype(np.float32), (2, 0, 1))/255, label

在 o/p 层定义批量大小和节点数

batch_size = 5
num_outputs = 2

加载训练和测试数据

train_data = mx.gluon.data.DataLoader(mx.gluon.data.vision.ImageFolderDataset("/somepath/train", 0, transform), batch_size, shuffle=True)
test_data = mx.gluon.data.DataLoader(mx.gluon.data.vision.ImageFolderDataset("/somepath/test", 0, transform), batch_size, shuffle=False)

使用 gluon.nn 定义 CNN

neural_net = gluon.nn.Sequential()
num_fc = 512

with neural_net.name_scope():
    neural_net.add(gluon.nn.Conv2D(channels=20, kernel_size=5, activation='relu'))
    neural_net.add(gluon.nn.MaxPool2D(pool_size=2, strides=2))
    neural_net.add(gluon.nn.Conv2D(channels=50, kernel_size=5, activation='relu'))
    neural_net.add(gluon.nn.MaxPool2D(pool_size=2, strides=2))
    neural_net.add(gluon.nn.Flatten())
    neural_net.add(gluon.nn.Dense(num_fc, activation="relu"))
    neural_net.add(gluon.nn.Dense(num_outputs))

初始化参数、损失函数和训练对象

neural_net.collect_params().initialize(mx.init.Xavier(magnitude=2.24), ctx=ctx)
cross_entropy = gluon.loss.SoftmaxCrossEntropyLoss()
trainer = gluon.Trainer(neural_net.collect_params(), 'adadelta')

训练循环

total_time = 0
for e in range(2):
    tick = time.time()
    for idx, (dpoint, label) in enumerate(train_data):
        data = dpoint.as_in_context(ctx)
        label = label.as_in_context(ctx)

        with autograd.record():
            output = neural_net(data)
            loss2 = cross_entropy(output, label)

        loss2.backward()    
        trainer.step(data.shape[0])
    tock = time.time()
    print("Epoch %s. Took %s seconds to train" %(e, tock-tick))
    total_time += tock-tick
print("Total training time: %s" %(total_time))

测量精度

acc = mx.metric.Accuracy()
for idx, (data, label) in enumerate(test_data):
    something = data.as_in_context(ctx)
    something_label = label.as_in_context(ctx)

    output2 = neural_net(something)
    predictions = nd.argmax(output2, axis=1)

    acc.update(predictions, something_label)
print(acc.get()[-1])

【问题讨论】:

  • 崩溃输出是什么?
  • @SinaAfrooze 没有输出,只是变得无响应
  • 在训练期间或在计算 Accuracy() 时是否变得无响应?
  • @SinaAfrooze 导致其无响应的特定行是“output2 = neural_net(...)”,即在评估准确性期间的前向道具
  • 这很奇怪。您能否在带有调试器(如 PyCharm)的 IDE 中运行它,并在卡住时暂停执行来查看卡在哪里?另外,您运行的是哪个版本的 MXNet?

标签: python apache deep-learning mxnet


【解决方案1】:

您的网络可能需要很长时间来计算数据的前向和后向传递。我追踪了对acc.update 呼叫的感知无响应(比neural_net(...) 稍晚)。深入挖掘此功能,我们正在等待nd.asnumpy 解决。

混淆在于 MXNet NDArray 计算是异步的。所有训练前向/后向传递操作似乎立即解决,但实际上已添加到队列中以进行处理。只有当数据被带回 python 进程(通过nd.asnumpy)时,您必须等待相关操作完成。这是acc.update第一次发生这种情况。

另一种对某些代码块的性能进行基准测试的方法是使用mx.nd.waitall(),它会阻塞代码直到计算队列为空。将此添加到您的训练周期中,您会发现它需要的时间比最初显示的要长得多。

使用 GPU 可能有助于解决这种明显的无响应问题。

【讨论】:

  • 非常感谢,这对您有很大帮助。
【解决方案2】:

Thom 的回答是正确的,您需要明确地等待工作完成,否则操作只是入队。看看这个section of the documentation

这是文档中的相关代码 sn-p,它向您展示了将 mx.nd.waitall() 放在哪里

for batch in train_data:
    train_batch(batch, dev_params, ctx, lr)
nd.waitall()  # wait all computations are finished to benchmark the time
print('Epoch %d, training time = %.1f sec'%(epoch, time()-start))

在您的示例中:

nd.waitall()
tock = time.time()
print("Epoch %s. Took %s seconds to train" %(e, tock-tick))

【讨论】:

    猜你喜欢
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 2012-04-02
    • 2018-08-19
    • 2010-11-20
    • 2019-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多