Machine learning Pytorch CCNN的周期/振荡损耗函数

Machine learning Pytorch CCNN的周期/振荡损耗函数,machine-learning,neural-network,computer-vision,conv-neural-network,pytorch,Machine Learning,Neural Network,Computer Vision,Conv Neural Network,Pytorch,我在ImageNet上训练一个CNN,我在损失函数中看到一些奇怪的周期性振荡。曲线看起来基本正确,但随着曲线变平,可以看到明显的振荡。我每100个小批量捕获一次损失,因为我的批量大小是128,我的训练集是~100k个图像,这意味着需要10个步骤来检查数据。所以我在这里看到的周期性是,损失在10个步骤中增加,然后在新纪元开始时突然下降,然后逐渐增加,直到到达下一个纪元 我在下面展示了我的大部分培训代码(为了简洁起见,没有完整地展示)。我在每个历元的开始和每套100个小批量的结束时将“运行损耗”重置

我在ImageNet上训练一个CNN,我在损失函数中看到一些奇怪的周期性振荡。曲线看起来基本正确,但随着曲线变平,可以看到明显的振荡。我每100个小批量捕获一次损失,因为我的批量大小是128,我的训练集是~100k个图像,这意味着需要10个步骤来检查数据。所以我在这里看到的周期性是,损失在10个步骤中增加,然后在新纪元开始时突然下降,然后逐渐增加,直到到达下一个纪元

我在下面展示了我的大部分培训代码(为了简洁起见,没有完整地展示)。我在每个历元的开始和每套100个小批量的结束时将“运行损耗”重置为零。这里有人有什么看法吗?我不知道我计算/收集损失的方式是否有问题,或者我的模型是否有更根本的问题

train_data = ImageDataset(train_file_list, transform=transform)        
train_data_loader = DataLoader(train_data, batch_size=128, shuffle=True, num_workers=4)

alexnet = AlexNetPyTorch(NUM_CLASSES)
alexnet = alexnet.to(device)
loss_fn = nn.CrossEntropyLoss()
optimizer = optim.Adam(params=alexnet.parameters(), lr=3.0e-4, weight_decay=5.0e-4)

history = {}
history['loss'] = []
history['val_loss'] = []
history['accuracy'] = []
history['val_accuracy'] = []
step_increment = 100
for epoch in range(30):

    running_loss = 0.0
    running_val_loss = 0.0

    for step, data in enumerate(train_data_loader):
        alexnet.train()
        X_train, y_train = data
        X_train = X_train.to(device)
        y_train = y_train.to(device)

        # forward + backward + optimize
        y_pred = alexnet(X_train)
        loss = loss_fn(y_pred, y_train)

        # zero the parameter gradients
        optimizer.zero_grad()

        loss.backward()
        optimizer.step()

        # print statistics
        running_loss += loss.item()

        if step % step_increment == step_increment-1:    # print every 100 mini-batches

            # Compute validation loss
            with torch.no_grad():
                alexnet.eval()

                _, preds = torch.max(y_pred,1)
                train_accuracy = torch.sum(preds == y_train).item()/len(y_train)

                X_val, y_val = validation_data
                X_val = X_val.to(device)
                y_val = y_val.to(device)
                y_pred = alexnet(X_val)
                val_loss = loss_fn(y_pred, y_val).item()

                _, preds = torch.max(y_pred,1)
                val_accuracy = torch.sum(preds == y_val).item()/len(y_val)

                history['loss'].append(np.mean(running_loss/step_increment))
                history['accuracy'].append(train_accuracy)
                history['val_accuracy'].append(val_accuracy)
                history['val_loss'].append(val_loss)

                print('[%d, %5d] loss: %.3f acc: %.3f val loss: %.3f val acc: %.3f' %
                      (epoch + 1, step+1, running_loss/step_increment, train_accuracy, val_loss, val_accuracy))

                running_loss = 0.0

由于您正在绘制运行损失图(它会增加(因为您添加),直到您达到100个小批次的末尾),因此它会振荡。你可以试着在每一个时代结束时绘制损失图。也可以看到这个关于神经网络中的振荡损失。这可能会有帮助,真的对吗?我正在绘制每100个小批量的损失图。在每100个小批次结束时-和/或在每个历元开始时-我将运行损耗重置为零。所以在我看来,在任何一个给定的时期,运行损耗从一个小批量连续增加到另一个小批量,只有当到达下一个时期时,损耗函数的值才会发生阶跃变化。运行损耗当然会增加,因为它涉及加法。最好在每个纪元之后查看损失(用于绘图目的)。或者,您应该绘制每100个小批次的实际损失,而不是运行损失。感谢您继续在这里进行对话。我认为这里的混乱是,我正在将每100个小批量的运行损耗设置回零。因此,在我看来,在给定的历元内,我计算前100个小批量的平均损耗(运行损耗/100),记录一个值,然后重置为零,计算下100个小批量的平均损耗,并在该历元的过程中获得连续更大的结果…如此类推。因为您正在绘制运行损耗(它会增加(自您添加后),直到您达到100个小批量的末尾)它会振荡。你可以试着只在每个历元结束时绘制损耗图。也可以在神经网络中看到这个关于振荡损耗的图。这可能会有帮助。这是真的吗?我在每100个小批量结束时绘制损耗图。在每100个小批量结束时-和/或在每个历元开始时-我重置运行损耗所以在我看来,在任何一个给定的时期,运行损耗从一个小批量连续增加到另一个小批量,只有在下一个时期达到时,损耗函数的值才会发生阶跃变化。运行损耗当然会增加,因为它涉及加法。最好在ev之后再看看损耗(用于绘图目的)。或者,您应该在每100个小批量之后绘制实际损失,而不是运行损失。感谢您继续在这里进行对话。我认为这里的混乱之处在于,我在每100个小批量结束时将运行损失设置为零。因此,在我看来,在给定的时间内,我计算平均损失(运行损失/100)对于前100个小批量,记录一个值,然后重置为零,计算下100个小批量的平均损失,并在该时期内连续获得更大的结果……以此类推。