代码之家  ›  专栏  ›  技术社区  ›  Sam B.

vgg概率不等于1,pytorch

  •  0
  • Sam B.  · 技术社区  · 6 年前

    我训练了一个vg16模型来预测102类花。 不过,现在我正试图理解其中一个预测,我觉得它的行为不正常。

    模型布局

    # Imports here
    import os
    import numpy as np
    import torch
    
    import torchvision
    from torchvision import datasets, models, transforms
    import matplotlib.pyplot as plt
    import json
    from pprint import pprint
    from scipy import misc
    
    %matplotlib inline
    
    data_dir = 'flower_data'
    train_dir = data_dir + '/train'
    test_dir = data_dir + '/valid'
    
    json_data=open('cat_to_name.json').read()
    main_classes = json.loads(json_data)
    main_classes = {int(k):v for k,v in classes.items()}
    
    train_transform_2 = transforms.Compose([transforms.RandomResizedCrop(224), 
                                        transforms.RandomRotation(30),
                                        transforms.RandomHorizontalFlip(),
                                        transforms.ToTensor()])
    
    test_transform_2= transforms.Compose([transforms.RandomResizedCrop(224), 
                                        transforms.ToTensor()])
    
    # TODO: Load the datasets with ImageFolder
    train_data = datasets.ImageFolder(train_dir, transform=train_transform_2)
    test_data = datasets.ImageFolder(test_dir, transform=test_transform_2)
    
    # define dataloader parameters
    batch_size = 20
    num_workers=0
    
    # TODO: Using the image datasets and the trainforms, define the dataloaders
    train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, 
                                            num_workers=num_workers, shuffle=True)
    test_loader = torch.utils.data.DataLoader(test_data, batch_size=batch_size, 
                                            num_workers=num_workers, shuffle=True)
    
    vgg16 = models.vgg16(pretrained=True)
    
    # Freeze training for all "features" layers
    for param in vgg16.features.parameters():
        param.requires_grad = False
    
    import torch.nn as nn
    
    n_inputs = vgg16.classifier[6].in_features
    
    # add last linear layer (n_inputs -> 102 flower classes)
    # new layers automatically have requires_grad = True
    last_layer = nn.Linear(n_inputs, len(classes))
    
    vgg16.classifier[6] = last_layer
    
    import torch.optim as optim
    
    # specify loss function (categorical cross-entropy)
    criterion = nn.CrossEntropyLoss()
    
    # specify optimizer (stochastic gradient descent) and learning rate = 0.001
    optimizer = optim.SGD(vgg16.classifier.parameters(), lr=0.001)
    
    pre_trained_model=torch.load("model.pt")
    new=list(pre_trained_model.items())
    
    my_model_kvpair=vgg16.state_dict()
    count=0
    
    for key,value in my_model_kvpair.items():
        layer_name, weights = new[count]      
        my_model_kvpair[key] = weights
        count+=1
    
    # number of epochs to train the model
    n_epochs = 6
    
    # initialize tracker for minimum validation loss
    valid_loss_min = np.Inf # set initial "min" to infinity
    
    for epoch in range(1, n_epochs+1):
    
        # keep track of training and validation loss
        train_loss = 0.0
        valid_loss = 0.0
    
        ###################
        # train the model #
        ###################
        # model by default is set to train
        vgg16.train()
    
        for batch_i, (data, target) in enumerate(train_loader):
            # clear the gradients of all optimized variables
            optimizer.zero_grad()
            # forward pass: compute predicted outputs by passing inputs to the model
            output = vgg16(data)
            # calculate the batch loss
            loss = criterion(output, target)
            # backward pass: compute gradient of the loss with respect to model parameters
            loss.backward()
            # perform a single optimization step (parameter update)
            optimizer.step()
            # update training loss 
            train_loss += loss.item()
    
            if batch_i % 20 == 19:    # print training loss every specified number of mini-batches
                print('Epoch %d, Batch %d loss: %.16f' %
                    (epoch, batch_i + 1, train_loss / 20))
                train_loss = 0.0
    
        ######################    
        # validate the model #
        ######################
        vgg16.eval() # prep model for evaluation
        for data, target in test_loader:
            # forward pass: compute predicted outputs by passing inputs to the model
            output = vgg16(data)
            # calculate the loss
            loss = criterion(output, target)
            # update running validation loss 
            valid_loss += loss.item()
    
        # print training/validation statistics 
        # calculate average loss over an epoch
        train_loss = train_loss/len(train_loader.dataset)
        valid_loss = valid_loss/len(test_loader.dataset)
    
        print('Epoch: {} \tTraining Loss: {:.6f} \tValidation Loss: {:.6f}'.format(
            epoch+1, 
            train_loss,
            valid_loss
            ))
    
        # save model if validation loss has decreased
        if valid_loss <= valid_loss_min:
            print('Validation loss decreased ({:.6f} --> {:.6f}).  Saving model ...'.format(
            valid_loss_min,
            valid_loss))
            torch.save(vgg16.state_dict(), 'model.pt')
            valid_loss_min = valid_loss
    

    对单个图像进行测试

    tensor = torch.from_numpy(test_image)
    reshaped = tensor.permute(2, 0, 1).unsqueeze(0)
    floatified = reshaped.to(torch.float32) / 255
    vgg16(floatified)
    >>>
    tensor([[ 2.5686, -1.1964, -0.0872, -1.7010, -1.6669, -1.0638,  0.4515,  0.1124,
              0.0166,  0.3156,  1.1699,  1.5374,  1.8720,  2.5184,  2.9046, -0.8241,
             -1.1949, -0.5700,  0.8692, -1.0485,  0.0390, -1.3783, -3.4632, -0.0143,
              1.0986,  0.2667, -1.1127, -0.8515,  0.7759, -0.7528,  1.6366, -0.1170,
             -0.4983, -2.6970,  0.7545,  0.0188,  0.1094,  0.5002,  0.8838, -0.0006,
             -1.7993, -1.3706,  0.4964, -0.3251, -1.7313,  1.8731,  2.4963,  1.1713,
             -1.5726,  1.5476,  3.9576,  0.7388,  0.0228,  0.3947, -1.7237, -1.8350,
             -2.0297,  1.4088, -1.3469,  1.6128, -1.0851,  2.0257,  0.5881,  0.7498,
              0.0738,  2.0592,  1.8034, -0.5468,  1.9512,  0.4534,  0.7746, -1.0465,
             -0.7254,  0.3333, -1.6506, -0.4242,  1.9529, -0.4542,  0.2396, -1.6804,
             -2.7987, -0.6367, -0.3599,  1.0102,  2.6319,  0.8305, -1.4333,  3.3043,
             -0.4021, -0.4877,  0.9125,  0.0607, -1.0326,  1.3186, -2.5861,  0.1211,
             -2.3177, -1.5040,  1.0416,  1.4008,  1.4225, -2.7291]],
           grad_fn=<ThAddmmBackward>)
    
    sum([ 2.5686, -1.1964, -0.0872, -1.7010, -1.6669, -1.0638,  0.4515,  0.1124,
              0.0166,  0.3156,  1.1699,  1.5374,  1.8720,  2.5184,  2.9046, -0.8241,
             -1.1949, -0.5700,  0.8692, -1.0485,  0.0390, -1.3783, -3.4632, -0.0143,
              1.0986,  0.2667, -1.1127, -0.8515,  0.7759, -0.7528,  1.6366, -0.1170,
             -0.4983, -2.6970,  0.7545,  0.0188,  0.1094,  0.5002,  0.8838, -0.0006,
             -1.7993, -1.3706,  0.4964, -0.3251, -1.7313,  1.8731,  2.4963,  1.1713,
             -1.5726,  1.5476,  3.9576,  0.7388,  0.0228,  0.3947, -1.7237, -1.8350,
             -2.0297,  1.4088, -1.3469,  1.6128, -1.0851,  2.0257,  0.5881,  0.7498,
              0.0738,  2.0592,  1.8034, -0.5468,  1.9512,  0.4534,  0.7746, -1.0465,
             -0.7254,  0.3333, -1.6506, -0.4242,  1.9529, -0.4542,  0.2396, -1.6804,
             -2.7987, -0.6367, -0.3599,  1.0102,  2.6319,  0.8305, -1.4333,  3.3043,
             -0.4021, -0.4877,  0.9125,  0.0607, -1.0326,  1.3186, -2.5861,  0.1211,
             -2.3177, -1.5040,  1.0416,  1.4008,  1.4225, -2.7291])
    >>>
    5.325799999999998
    

    假设我在一张图像上测试它的方式是这样的(并且像往常一样,模型是经过训练和批量测试的),它返回一个预测矩阵,这个矩阵似乎没有被规范化或加起来是1。

    这正常吗?

    1 回复  |  直到 6 年前
        1
  •  2
  •   Fábio Perez    6 年前

    是的,PyTorch中的官方网络实现不会将SoftMax应用到最后一个线性层。 Check the code for VGG . 你可以使用 nn.softmax 为了实现你想要的:

    m = nn.Softmax()
    out = vgg16(floatified)
    out = m(out)
    

    您也可以使用 nn.functional.softmax :

    out = nn.functional.softmax(vgg16(floatified))