python - 神经网络 pytorch

标签 python machine-learning conv-neural-network pytorch

我对 pytorch 非常陌生,正在实现我自己的图像分类器网络。然而,我发现每个 epoch 的训练精度都非常好,但验证精度为 0。我注意到直到第 5 个 epoch。我正在使用 Adam 优化器,学习率为 0.001。还在每个时期之后将整个数据集重新采样到训练 n 验证集中。请帮助我哪里出错了。

这是我的代码:

### where is data?
data_dir_train = '/home/sup/PycharmProjects/deep_learning/CNN_Data/training_set'
data_dir_test = '/home/sup/PycharmProjects/deep_learning/CNN_Data/test_set'

# Define your batch_size
batch_size = 64

allData = datasets.ImageFolder(root=data_dir_train,transform=transformArr)


# We need to further split our training dataset into training and validation sets.
def split_train_validation():
    # Define the indices
    num_train = len(allData)
    indices = list(range(num_train)) # start with all the indices in training set
    split = int(np.floor(0.2 * num_train)) # define the split size
    #train_idx, valid_idx = indices[split:], indices[:split]

    # Random, non-contiguous split
    validation_idx = np.random.choice(indices, size=split, replace=False)
    train_idx = list(set(indices) - set(validation_idx))
    # define our samplers -- we use a SubsetRandomSampler because it will return
    # a random subset of the split defined by the given indices without replacement
    train_sampler = SubsetRandomSampler(train_idx)
    validation_sampler = SubsetRandomSampler(validation_idx)

    #train_loader = DataLoader(allData,batch_size=batch_size,sampler=train_sampler,shuffle=False,num_workers=4)
    #validation_loader = DataLoader(dataset=allData,batch_size=1, sampler=validation_sampler)

    return (train_sampler,validation_sampler)

培训

from torch.optim import Adam
import torch
import createNN
import torch.nn as nn
import loadData as ld
from torch.autograd import  Variable
from torch.utils.data import DataLoader

# check if cuda - GPU support available
cuda = torch.cuda.is_available()

#create model, optimizer and loss function
model = createNN.ConvNet(class_num=2)
optimizer = Adam(model.parameters(),lr=.001,weight_decay=.0001)
loss_func = nn.CrossEntropyLoss()

if cuda:
    model.cuda()

# function to save model
def save_model(epoch):
    torch.save(model.load_state_dict(),'imageClassifier_{}.model'.format(epoch))
    print('saved model at epoch',epoch)

def exp_lr_scheduler (  epoch , init_lr = args.lr, weight_decay = args.weight_decay, lr_decay_epoch = cf.lr_decay_epoch):
 lr = init_lr * ( 0.5 ** (epoch // lr_decay_epoch))

def train(num_epochs):
    best_acc = 0.0

    for epoch in range(num_epochs):
        print('\n\nEpoch {}'.format(epoch))
        train_sampler, validation_sampler = ld.split_train_validation()
        train_loader = DataLoader(ld.allData, batch_size=30, sampler=train_sampler, shuffle=False)
        validation_loader = DataLoader(dataset=ld.allData, batch_size=1, sampler=validation_sampler)
        model.train()
        acc = 0.0
        loss = 0.0
        total = 0
        # train model with training data
        for i,(images,labels) in enumerate(train_loader):
            # if cuda then move to GPU
            if cuda:
                images = images.cuda()
                labels = labels.cuda()
            # Variable class wraps a tensor and we can calculate grad
            images = Variable(images)
            labels = Variable(labels)
            # reset accumulated gradients for each batch
            optimizer.zero_grad()
            # pass images to model which returns preiction
            output = model(images)
            #calculate the loss based on prediction and actual
            loss = loss_func(output,labels)
            # backpropagate the loss and compute gradient
            loss.backward()
            # update weights as per the computed gradients
            optimizer.step()

            # prediction class
            predVal , predClass = torch.max(output.data, 1)
            acc += torch.sum(predClass == labels.data)
            loss += loss.cpu().data[0]
            total += labels.size(0)
        # print the statistics
        train_acc = acc/total
        train_loss = loss / total
        print('Mean train acc = {} over epoch = {}'.format(epoch,acc))
        print('Mean train loss = {} over epoch = {}'.format(epoch, loss))

        # Valid model with validataion data
        model.eval()
        acc = 0.0
        loss = 0.0
        total = 0
        for i,(images,labels) in enumerate(validation_loader):
            # if cuda then move to GPU
            if cuda:
                images = images.cuda()
                labels = labels.cuda()
            # Variable class wraps a tensor and we can calculate grad
            images = Variable(images)
            labels = Variable(labels)
            # reset accumulated gradients for each batch
            optimizer.zero_grad()
            # pass images to model which returns preiction
            output = model(images)
            #calculate the loss based on prediction and actual
            loss = loss_func(output,labels)
            # backpropagate the loss and compute gradient
            loss.backward()
            # update weights as per the computed gradients
            optimizer.step()

            # prediction class
            predVal, predClass = torch.max(output.data, 1)
            acc += torch.sum(predClass == labels.data)
            loss += loss.cpu().data[0]
            total += labels.size(0)
        # print the statistics
        valid_acc = acc / total
        valid_loss = loss / total
        print('Mean train acc = {} over epoch = {}'.format(epoch, valid_acc))
        print('Mean train loss = {} over epoch = {}'.format(epoch, valid_loss))

        if(best_acc<valid_acc):
            best_acc = valid_acc
            save_model(epoch)

        # at 30th epoch we save the model
        if (epoch == 30):
            save_model(epoch)


train(20)

最佳答案

我认为您没有考虑到 acc += torch.sum(predClass == labels.data) 返回张量而不是浮点值。根据您使用的 pytorch 版本,我认为您应该将其更改为:

acc += torch.sum(predClass == labels.data).cpu().data[0] #pytorch 0.3
acc += torch.sum(predClass == labels.data).item() #pytorch 0.4

虽然您的代码似乎适用于旧的 pytorch 版本,但我建议您升级到 0.4 版本。

此外,我还提到了您的代码中的其他问题/拼写错误。

您正在加载每个时期的数据集。

for epoch in range(num_epochs):
    print('\n\nEpoch {}'.format(epoch))
    train_sampler, validation_sampler = ld.split_train_validation()
    train_loader = DataLoader(ld.allData, batch_size=30, sampler=train_sampler, shuffle=False)
    validation_loader = DataLoader(dataset=ld.allData, batch_size=1, sampler=validation_sampler)
    ...

这种情况不应该发生,加载一次就足够了

train_sampler, validation_sampler = ld.split_train_validation()
train_loader = DataLoader(ld.allData, batch_size=30, sampler=train_sampler, shuffle=False)
validation_loader = DataLoader(dataset=ld.allData, batch_size=1, sampler=validation_sampler)
for epoch in range(num_epochs):
    print('\n\nEpoch {}'.format(epoch))
    ...

在训练部分中(这不会在验证中发生):

train_acc = acc/total
train_loss = loss / total
print('Mean train acc = {} over epoch = {}'.format(epoch,acc))
print('Mean train loss = {} over epoch = {}'.format(epoch, loss))

您在哪里打印 acc 而不是 train_acc

此外,在验证部分中,我提到您正在打印 print('Mean train acc = {} over epoch = {}'.format(epoch, valid_acc)) ,而它应该是这样的就像'Mean val acc'

更改这行代码,使用我创建的标准模型和 CIFAR 数据集,训练似乎收敛了,每个时期的准确性都会增加,而平均损失值会减少。

希望能帮到你!

关于python - 神经网络 pytorch,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51234035/

相关文章:

c++ - Blas 看起来很慢

Python 正则表达式 - 忽略括号作为索引?

python - python docstring中参数描述的多行描述

encoding - 决策树中的香农熵度量

python - tensorflow VGG16网络精度和损失没有改变

python - 合并多个 CNN

python - 在自行设计的GUI中将用户输入解析为python代码

python - 以下xgboost模型 TreeMap 中 'leaf'的值是什么意思?

python - 为什么 fit_generator 的精度与 Keras 中的 evaluate_generator 的精度不同?

machine-learning - 无法在 pylearn2 上编译 cuda_convnet 错误