使用 Apache mxnet (gluon) 训练神经网络导致程序崩溃
Training neural network with Apache mxnet (gluon) causes program to crash
我正在尝试使用 Gluon API 在一组我想要 class 化的图像上使用 mxnet 训练卷积神经网络。然而,相同的网络和代码有时会针对相同的数据输出截然不同的结果,并且有时会因某种原因而崩溃并拒绝 运行。这是我的代码:
附加信息:
图像均为 131 x 131 像素大小,每个 class 176 张图像(2 classes)和每个 class 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))
初始化参数、损失 fn 和训练对象
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])
您的网络可能需要很长时间来计算数据的前向和后向传递。我追踪了对 acc.update
调用(比 neural_net(...)
晚一点)的感知无响应。深入研究此功能,我们正在等待 nd.asnumpy
解决。
混淆在于 MXNet NDArray 计算是异步的。所有训练 forward/backward 传递操作似乎立即解决,但实际上已添加到队列中进行处理。只有当数据被带回 python 进程(通过 nd.asnumpy
)时,您才需要等待相关操作完成。这在 acc.update
.
中首次发生
另一种对某些代码块进行基准测试的方法是使用mx.nd.waitall()
,它会阻塞代码直到计算队列为空。将此添加到您的训练周期中,您会发现它花费的时间比最初出现的时间长得多。
使用 GPU 可能有助于缓解这种明显的无响应。
Thom 的回答是正确的,您需要明确等待工作完成,否则操作只会排队。看看这个section of the documentation
这是文档中的相关代码片段,向您展示了放置 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))
我正在尝试使用 Gluon API 在一组我想要 class 化的图像上使用 mxnet 训练卷积神经网络。然而,相同的网络和代码有时会针对相同的数据输出截然不同的结果,并且有时会因某种原因而崩溃并拒绝 运行。这是我的代码:
附加信息:
图像均为 131 x 131 像素大小,每个 class 176 张图像(2 classes)和每个 class 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
定义 CNNneural_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))
初始化参数、损失 fn 和训练对象
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])
您的网络可能需要很长时间来计算数据的前向和后向传递。我追踪了对 acc.update
调用(比 neural_net(...)
晚一点)的感知无响应。深入研究此功能,我们正在等待 nd.asnumpy
解决。
混淆在于 MXNet NDArray 计算是异步的。所有训练 forward/backward 传递操作似乎立即解决,但实际上已添加到队列中进行处理。只有当数据被带回 python 进程(通过 nd.asnumpy
)时,您才需要等待相关操作完成。这在 acc.update
.
另一种对某些代码块进行基准测试的方法是使用mx.nd.waitall()
,它会阻塞代码直到计算队列为空。将此添加到您的训练周期中,您会发现它花费的时间比最初出现的时间长得多。
使用 GPU 可能有助于缓解这种明显的无响应。
Thom 的回答是正确的,您需要明确等待工作完成,否则操作只会排队。看看这个section of the documentation
这是文档中的相关代码片段,向您展示了放置 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))