You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Apache MXNet(Gluon)训练CNN时程序崩溃且结果异常求助

看起来你遇到了两个挺闹心的问题:同一套代码跑同一批数据,结果波动大不说,还偶尔直接崩溃。我来帮你拆解下可能的原因,一步步解决:

1. 数据加载的致命bug(崩溃的大概率元凶)

你在创建ImageFolderDataset的时候传参错了!mx.gluon.data.vision.ImageFolderDataset的正确参数顺序是:根目录、图像转换函数、标签转换函数。但你写的代码里:

mx.gluon.data.vision.ImageFolderDataset("/somepath/train", 0, transform)

把整数0当成了图像转换函数传给了第二个参数,第三个参数才是你自定义的transform——这相当于让Dataset去调用0(data, label),不出错才怪!至于为什么有时能运行,可能是你实际代码里的写法有出入,但不管怎样,正确的写法应该是:

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

如果是想设置图像加载模式(比如转灰度图),应该在transform函数里处理,比如:

def transform(data, label):
    # 转灰度图
    data = mx.image.rgb_to_grayscale(data)
    return nd.transpose(data.astype(np.float32), (2, 0, 1))/255, label

2. 随机种子没固定全(结果波动大的核心原因)

你已经设置了mx.random.seed(1),但训练中还有其他随机源会影响结果:

  • numpy的随机数:数据处理或初始化可能用到它,得加np.random.seed(1)
  • Python标准库的random:DataLoader的shuffle逻辑依赖它,得加import random; random.seed(1)

把种子设置放在代码最开头,确保所有随机操作都基于同一个起点:

from __future__ import print_function
import mxnet as mx
import numpy as np
import random
from mxnet import nd, autograd, gluon
import time

# 固定所有随机源,保证每次训练的初始条件一致
random.seed(1)
np.random.seed(1)
mx.random.seed(1)

3. 其他小细节优化(让结果更稳定)

  • 增加训练轮数:你原来只训练2个epoch,模型还没来得及收敛,结果自然波动大,建议加到10-50个epoch,同时在训练循环里监控损失和准确率,方便观察收敛情况。
  • 统一变量命名:你评估测试集的时候用了something这种模糊的变量名,改成data更清晰,也避免潜在的笔误。

修复后的完整代码

整合了所有修复点的代码如下,你可以直接测试:

from __future__ import print_function
import mxnet as mx
import numpy as np
import random
from mxnet import nd, autograd, gluon
import time

# 固定所有随机种子
random.seed(1)
np.random.seed(1)
mx.random.seed(1)

# 设置计算上下文
ctx = mx.cpu()

# 定义回调转换函数
def transform(data, label):
    return nd.transpose(data.astype(np.float32), (2, 0, 1))/255, label

# 定义批量大小与输出层节点数
batch_size = 5
num_outputs = 2

# 修复后的数据集加载
train_data = mx.gluon.data.DataLoader(
    mx.gluon.data.vision.ImageFolderDataset("/somepath/train", transform=transform),
    batch_size, shuffle=True
)
test_data = mx.gluon.data.DataLoader(
    mx.gluon.data.vision.ImageFolderDataset("/somepath/test", transform=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')

# 训练循环(增加到10个epoch,加入损失和准确率监控)
total_time = 0
epochs = 10
for e in range(epochs):
    tick = time.time()
    train_loss = 0.0
    train_acc = mx.metric.Accuracy()
    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)
            loss = cross_entropy(output, label)
            loss.backward()
        trainer.step(data.shape[0])
        # 累计训练损失和准确率
        train_loss += nd.mean(loss).asscalar()
        predictions = nd.argmax(output, axis=1)
        train_acc.update(predictions, label)
    tock = time.time()
    print(f"Epoch {e+1}/{epochs} | Train Loss: {train_loss/len(train_data):.4f} | Train Acc: {train_acc.get()[1]:.4f} | Time: {tock-tick:.2f}s")
    total_time += tock-tick
print(f"\nTotal training time: {total_time:.2f} seconds")

# 评估测试集准确率
test_acc = mx.metric.Accuracy()
for idx, (data, label) in enumerate(test_data):
    data = data.as_in_context(ctx)
    label = label.as_in_context(ctx)
    output = neural_net(data)
    predictions = nd.argmax(output, axis=1)
    test_acc.update(predictions, label)
print(f"Test Accuracy: {test_acc.get()[1]:.4f}")

内容的提问来源于stack exchange,提问作者dntk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:53:57