3D CNN的二分类算法,loss和acc趋势


import paddle.nn.functional as F

epoch_num = 100
batch_size = 2
batch_size_valid = 4
learning_rate = 0.0001

val_acc_history = []
val_loss_history = []

def train(model):
    print('start training ... ')
    # turn into training mode
    model.train()

    #该接口提供一种学习率按指数函数衰减的策略。
    scheduler = paddle.optimizer.lr.ExponentialDecay(learning_rate= learning_rate, gamma=0.96, verbose=True)
    opt = paddle.optimizer.Adam(learning_rate=scheduler,
                                parameters=model.parameters())

    train_loader = paddle.io.DataLoader(train_dataset,
                                        shuffle=True,
                                        batch_size=batch_size)

    valid_loader = paddle.io.DataLoader(valid_dataset, batch_size=batch_size_valid)
    
    for epoch in range(epoch_num):
        for batch_id, data in enumerate(train_loader()):
            x_data = data[0]
            y_data = paddle.to_tensor(data[1],dtype="float32")
            y_data = paddle.unsqueeze(y_data, 1)

            logits = model(x_data)
            bce_loss = paddle.nn.BCELoss()
            loss = bce_loss(logits, y_data)
            
            if batch_id % 10 == 0:
                print("epoch: {}/{}, batch_id: {}, loss is: {}".format(epoch,epoch_num, batch_id, loss.numpy()))
            loss.backward()
            opt.step()
            opt.clear_grad()

        # evaluate model after one epoch
        model.eval()
        accuracies = []
        losses = []
        for batch_id, data in enumerate(valid_loader()):
            x_data = data[0]
            y_data = paddle.to_tensor(data[1],dtype="float32")
            y_data = paddle.unsqueeze(y_data, 1)

            logits = model(x_data)
            bce_loss = paddle.nn.BCELoss()
            loss = bce_loss(logits, y_data)
            
            mask = np.float32(logits>=0.5) # 以0.5为阈值进行分类
            correct = np.sum(mask == np.float32(y_data))  # 计算正确预测的样本个数
            acc = correct / batch_size_valid  # 计算精度
            accuracies.append(acc)
            losses.append(loss.numpy())

        avg_acc, avg_loss = np.mean(accuracies), np.mean(losses)
        print("[validation] epoch: {}/{}, accuracy/loss: {}/{}".format(epoch,epoch_num,avg_acc, avg_loss))
        val_acc_history.append(avg_acc)
        val_loss_history.append(avg_loss)
        model.train()

model = Model3D()
train(model)

我的显卡显存只有8G,所以batch_size_valid最高是6,但是因为batch_size_valid设置为2的幂次可能效果更好,所以设置为4,刚开始对数据集进行反转,训练集是反转后的图片,验证集是反转的。acc/loss如下:

img


然后更换验证集,是另一个同类型数据集,结果:

img


现在再修改了batch_size,又变成如下情况:

img

建议统计一下两个数据集的标签信息,看看是不是数据集不均衡导致的

acc没有什么波动,要么是模型太简单,要么是激活函数选取不当,要么是数据量太少。