def main_run(numEpochs, lr, stepSize, decayRate, trainBatchSize, seqLen,
             evalInterval, evalMode, numWorkers, outDir, modelUsed, pretrained,
             train_test_split, directory, crossValidation, folds):

    compDataset, classCount, class_names = make_split(directory)

    if crossValidation:
        data, label = compDataset
        kFoldCrossValid(folds, data, label, numEpochs, evalMode, numWorkers,
                        lr, stepSize, decayRate, trainBatchSize, seqLen)

    else:
        (trainDataset,
         trainLabels), (validationDataset,
                        validationLabels), (testDataset,
                                            testLabels) = sampleFromClass(
                                                compDataset, classCount,
                                                train_test_split)
        model, accuracy = modelTrain(modelUsed, pretrained, trainDataset,
                                     trainLabels, validationDataset,
                                     validationLabels, numEpochs, evalInterval,
                                     evalMode, outDir, numWorkers, lr,
                                     stepSize, decayRate, trainBatchSize,
                                     seqLen, True)
        '''for printing confusion matrix'''
        mean = [0.485, 0.456, 0.406]
        std = [0.229, 0.224, 0.225]
        normalize = Normalize(mean=mean, std=std)
        if evalMode == 'centerCrop':
            test_spatial_transform = Compose(
                [Scale(256),
                 CenterCrop(224),
                 ToTensor(), normalize])
        elif evalMode == 'tenCrops':
            test_spatial_transform = Compose(
                [Scale(256),
                 TenCrops(size=224, mean=mean, std=std)])
        elif evalMode == 'fiveCrops':
            test_spatial_transform = Compose(
                [Scale(256),
                 FiveCrops(size=224, mean=mean, std=std)])
        elif evalMode == 'horFlip':
            test_spatial_transform = Compose([
                Scale(256),
                CenterCrop(224),
                FlippedImagesTest(mean=mean, std=std)
            ])

        vidSeqTest = makeDataset(testDataset,
                                 testLabels,
                                 seqLen=seqLen,
                                 spatial_transform=test_spatial_transform)

        testLoader = torch.utils.data.DataLoader(vidSeqTest,
                                                 batch_size=1,
                                                 shuffle=False,
                                                 num_workers=int(numWorkers /
                                                                 2),
                                                 pin_memory=True)

        numTestInstances = vidSeqTest.__len__()

        print('Number of test samples = {}'.format(numTestInstances))

        modelFolder = './experiments_' + outDir + '_' + modelUsed + '_' + str(
            pretrained)  # Dir for saving models and log files

        savePathClassifier = (modelFolder + '/bestModel.pth')
        torch.save(model.state_dict(), savePathClassifier)
        '''running test samples and printing confusion matrix'''
        model.train(False)
        print('Testing...')
        LossEpoch = 0
        testIter = 0
        pred = None
        targ = None
        numCorrTest = 0
        for j, (inputs, targets) in enumerate(testLoader):
            testIter += 1
            #if evalMode == 'centerCrop':
            if (torch.cuda.is_available()):
                inputVariable1 = Variable(inputs.permute(1, 0, 2, 3, 4).cuda(),
                                          requires_grad=False)
                labelVariable = Variable(targets.cuda(async=True),
                                         requires_grad=False)
            else:
                inputVariable1 = Variable(inputs.permute(1, 0, 2, 3, 4),
                                          requires_grad=False)
                labelVariable = Variable(targets, requires_grad=False)
            # else:
            #     if(torch.cuda.is_available()):
            #         inputVariable1 = Variable(inputs[0].permute(1, 0, 2, 3, 4).cuda(), requires_grad=False)
            #         labelVariable = Variable(targets.cuda(async=True), requires_grad=False)
            #     else:
            #         inputVariable1 = Variable(inputs[0].permute(1, 0, 2, 3, 4), requires_grad=False)
            #         labelVariable = Variable(targets, requires_grad=False)
            outputLabel = model(inputVariable1)
            outputProb = torch.nn.Softmax(dim=1)(outputLabel)
            _, predicted = torch.max(outputProb.data, 1)
            if pred is None:
                pred = predicted.cpu().numpy()
                targ = targets[0].cpu().numpy()
            else:
                pred = np.append(pred, predicted.cpu().numpy())
                targ = np.append(targ, targets[0].cpu().numpy())
            # if(torch.cuda.is_available()):
            #     numCorrTest += (predicted == targets[0].cuda()).sum()
            # else:
            #     numCorrTest += (predicted == targets[0]).sum()

        # Compute confusion matrix
        cnf_matrix = confusion_matrix(targ, pred)
        np.set_printoptions(precision=2)
        # Plot non-normalized confusion matrix
        plt.figure()
        plot_confusion_matrix(cnf_matrix,
                              classes=class_names,
                              title='Confusion matrix, without normalization')
        plt.savefig(modelFolder + "/no_norm_confusion_matrix.png")
        # Plot normalized confusion matrix
        plt.figure()
        plot_confusion_matrix(cnf_matrix,
                              classes=class_names,
                              normalize=True,
                              title='Normalized confusion matrix')

        plt.savefig(modelFolder + "/confusion_matrix.png")
        return True
Ejemplo n.º 2
0
def main_run(numEpochs, lr, stepSize, decayRate, trainBatchSize, seqLen,
             memSize, evalInterval, evalMode, numWorkers, outDir,
             fightsDir_train, noFightsDir_train, fightsDir_test,
             noFightsDir_test):

    train_dataset_dir_fights = fightsDir_train
    train_dataset_dir_noFights = noFightsDir_train
    test_dataset_dir_fights = fightsDir_test
    test_dataset_dir_noFights = noFightsDir_test

    trainDataset, trainLabels, trainNumFrames = make_split(
        train_dataset_dir_fights, train_dataset_dir_noFights)
    testDataset, testLabels, testNumFrames = make_split(
        test_dataset_dir_fights, test_dataset_dir_noFights)

    mean = [0.485, 0.456, 0.406]
    std = [0.229, 0.224, 0.225]
    normalize = Normalize(mean=mean, std=std)
    spatial_transform = Compose([
        Scale(256),
        RandomHorizontalFlip(),
        MultiScaleCornerCrop([1, 0.875, 0.75, 0.65625], 224),
        ToTensor(), normalize
    ])

    vidSeqTrain = VideoDataset(trainDataset,
                               trainLabels,
                               trainNumFrames,
                               spatial_transform=spatial_transform,
                               seqLen=seqLen)

    trainLoader = torch.utils.data.DataLoader(vidSeqTrain,
                                              batch_size=trainBatchSize,
                                              shuffle=True,
                                              num_workers=numWorkers,
                                              pin_memory=True,
                                              drop_last=True)

    if evalMode == 'centerCrop':
        test_spatial_transform = Compose(
            [Scale(256), CenterCrop(224),
             ToTensor(), normalize])
        testBatchSize = 1
    elif evalMode == 'tenCrops':
        test_spatial_transform = Compose(
            [Scale(256), TenCrops(size=224, mean=mean, std=std)])
        testBatchSize = 1
    elif evalMode == 'fiveCrops':
        test_spatial_transform = Compose(
            [Scale(256), FiveCrops(size=224, mean=mean, std=std)])
        testBatchSize = 1
    elif evalMode == 'horFlip':
        test_spatial_transform = Compose([
            Scale(256),
            CenterCrop(224),
            FlippedImagesTest(mean=mean, std=std)
        ])
        testBatchSize = 1

    vidSeqTest = VideoDataset(testDataset,
                              testLabels,
                              testNumFrames,
                              seqLen=seqLen,
                              spatial_transform=test_spatial_transform)

    testLoader = torch.utils.data.DataLoader(vidSeqTest,
                                             batch_size=testBatchSize,
                                             shuffle=False,
                                             num_workers=int(numWorkers / 2),
                                             pin_memory=True)

    numTrainInstances = vidSeqTrain.__len__()
    numTestInstances = vidSeqTest.__len__()

    print('Number of training samples = {}'.format(numTrainInstances))
    print('Number of testing samples = {}'.format(numTestInstances))

    modelFolder = './experiments_' + outDir  # Dir for saving models and log files
    # Create the dir
    if os.path.exists(modelFolder):
        print(modelFolder + ' exists!!!')
        sys.exit()
    else:
        os.makedirs(modelFolder)
    # Log files
    writer = SummaryWriter(modelFolder)
    trainLogLoss = open((modelFolder + '/trainLogLoss.txt'), 'w')
    trainLogAcc = open((modelFolder + '/trainLogAcc.txt'), 'w')
    testLogLoss = open((modelFolder + '/testLogLoss.txt'), 'w')
    testLogAcc = open((modelFolder + '/testLogAcc.txt'), 'w')

    model = ViolenceModel(mem_size=memSize)

    trainParams = []
    for params in model.parameters():
        params.requires_grad = True
        trainParams += [params]
    model.train(True)
    model.cuda()

    lossFn = nn.CrossEntropyLoss()
    optimizerFn = torch.optim.RMSprop(trainParams, lr=lr)
    optimScheduler = torch.optim.lr_scheduler.StepLR(optimizerFn, stepSize,
                                                     decayRate)

    minAccuracy = 50

    for epoch in range(numEpochs):
        optimScheduler.step()
        epochLoss = 0
        numCorrTrain = 0
        iterPerEpoch = 0
        model.train(True)
        print('Epoch = {}'.format(epoch + 1))
        writer.add_scalar('lr', optimizerFn.param_groups[0]['lr'], epoch + 1)
        for i, (inputs, targets) in enumerate(trainLoader):
            iterPerEpoch += 1
            optimizerFn.zero_grad()
            inputVariable1 = Variable(inputs.permute(1, 0, 2, 3, 4).cuda())
            labelVariable = Variable(targets.cuda())
            outputLabel = model(inputVariable1)
            loss = lossFn(outputLabel, labelVariable)
            loss.backward()
            optimizerFn.step()
            outputProb = torch.nn.Softmax(dim=1)(outputLabel)
            _, predicted = torch.max(outputProb.data, 1)
            numCorrTrain += (predicted == targets.cuda()).sum()
            epochLoss += loss.data[0]
        avgLoss = epochLoss / iterPerEpoch
        trainAccuracy = (numCorrTrain / numTrainInstances) * 100
        print('Training: Loss = {} | Accuracy = {}% '.format(
            avgLoss, trainAccuracy))
        writer.add_scalar('train/epochLoss', avgLoss, epoch + 1)
        writer.add_scalar('train/accuracy', trainAccuracy, epoch + 1)
        trainLogLoss.write('Training loss after {} epoch = {}\n'.format(
            epoch + 1, avgLoss))
        trainLogAcc.write('Training accuracy after {} epoch = {}\n'.format(
            epoch + 1, trainAccuracy))

        if (epoch + 1) % evalInterval == 0:
            model.train(False)
            print('Evaluating...')
            testLossEpoch = 0
            testIter = 0
            numCorrTest = 0
            for j, (inputs, targets) in enumerate(testLoader):
                testIter += 1
                if evalMode == 'centerCrop':
                    inputVariable1 = Variable(inputs.permute(1, 0, 2, 3,
                                                             4).cuda(),
                                              volatile=True)
                else:
                    inputVariable1 = Variable(inputs[0].cuda(), volatile=True)
                labelVariable = Variable(targets.cuda(async=True),
                                         volatile=True)
                outputLabel = model(inputVariable1)
                outputLabel_mean = torch.mean(outputLabel, 0, True)
                testLoss = lossFn(outputLabel_mean, labelVariable)
                testLossEpoch += testLoss.data[0]
                _, predicted = torch.max(outputLabel_mean.data, 1)
                numCorrTest += (predicted == targets[0]).sum()
            testAccuracy = (numCorrTest / numTestInstances) * 100
            avgTestLoss = testLossEpoch / testIter
            print('Testing: Loss = {} | Accuracy = {}% '.format(
                avgTestLoss, testAccuracy))
            writer.add_scalar('test/epochloss', avgTestLoss, epoch + 1)
            writer.add_scalar('test/accuracy', testAccuracy, epoch + 1)
            testLogLoss.write('Test Loss after {} epochs = {}\n'.format(
                epoch + 1, avgTestLoss))
            testLogAcc.write('Test Accuracy after {} epochs = {}%\n'.format(
                epoch + 1, testAccuracy))
            if testAccuracy > minAccuracy:
                savePathClassifier = (modelFolder + '/bestModel.pth')
                torch.save(model, savePathClassifier)
                minAccuracy = testAccuracy
    trainLogAcc.close()
    testLogAcc.close()
    trainLogLoss.close()
    testLogLoss.close()
    writer.export_scalars_to_json(modelFolder + "/all_scalars.json")
    writer.close()
    return True
def modelTrain(modelUsed, pretrained, trainDataset, trainLabels,
               validationDataset, validationLabels, numEpochs, evalInterval,
               evalMode, outDir, numWorkers, lr, stepSize, decayRate,
               trainBatchSize, seqLen, plotting):
    mean = [0.485, 0.456, 0.406]
    std = [0.229, 0.224, 0.225]
    normalize = Normalize(mean=mean, std=std)
    spatial_transform = Compose([
        Scale(256),
        RandomHorizontalFlip(),
        MultiScaleCornerCrop([1, 0.875, 0.75, 0.65625], 224),
        ToTensor(), normalize
    ])

    vidSeqTrain = makeDataset(trainDataset,
                              trainLabels,
                              spatial_transform=spatial_transform,
                              seqLen=seqLen)
    # torch iterator to give data in batches of specified size
    trainLoader = torch.utils.data.DataLoader(vidSeqTrain,
                                              batch_size=trainBatchSize,
                                              shuffle=True,
                                              num_workers=numWorkers,
                                              pin_memory=True,
                                              drop_last=True)

    if evalMode == 'centerCrop':
        test_spatial_transform = Compose(
            [Scale(256), CenterCrop(224),
             ToTensor(), normalize])
    elif evalMode == 'tenCrops':
        test_spatial_transform = Compose(
            [Scale(256), TenCrops(size=224, mean=mean, std=std)])
    elif evalMode == 'fiveCrops':
        test_spatial_transform = Compose(
            [Scale(256), FiveCrops(size=224, mean=mean, std=std)])
    elif evalMode == 'horFlip':
        test_spatial_transform = Compose([
            Scale(256),
            CenterCrop(224),
            FlippedImagesTest(mean=mean, std=std)
        ])

    vidSeqValid = makeDataset(validationDataset,
                              validationLabels,
                              seqLen=seqLen,
                              spatial_transform=test_spatial_transform)

    validationLoader = torch.utils.data.DataLoader(vidSeqValid,
                                                   batch_size=1,
                                                   shuffle=False,
                                                   num_workers=int(numWorkers /
                                                                   2),
                                                   pin_memory=True)

    numTrainInstances = vidSeqTrain.__len__()
    numValidationInstances = vidSeqValid.__len__()

    print('Number of training samples = {}'.format(numTrainInstances))
    print('Number of validation samples = {}'.format(numValidationInstances))

    modelFolder = './experiments_' + outDir + '_' + modelUsed + '_' + str(
        pretrained)  # Dir for saving models and log files
    # Create the dir
    if os.path.exists(modelFolder):
        pass
    else:
        os.makedirs(modelFolder)
    # Log files
    writer = SummaryWriter(modelFolder)
    trainLogLoss = open((modelFolder + '/trainLogLoss.txt'), 'a')
    trainLogAcc = open((modelFolder + '/trainLogAcc.txt'), 'a')
    validationLogLoss = open((modelFolder + '/validLogLoss.txt'), 'a')
    validationLogAcc = open((modelFolder + '/validLogAcc.txt'), 'a')

    model = ViolenceModel(modelUsed, pretrained)

    trainParams = []
    for params in model.parameters():
        if params.requires_grad:
            trainParams += [params]
    model.train(True)
    if (torch.cuda.is_available()):
        model.cuda()

    lossFn = nn.CrossEntropyLoss()
    optimizerFn = torch.optim.RMSprop(trainParams, lr=lr)
    optimizerFn.zero_grad()
    optimScheduler = torch.optim.lr_scheduler.StepLR(optimizerFn, stepSize,
                                                     decayRate)

    minAccuracy = 50
    train_loss = []
    val_loss = []
    train_acc = []
    val_acc = []
    bestmodel = None

    for epoch in range(numEpochs):
        optimScheduler.step()
        epochLoss = 0
        numCorrTrain = 0
        iterPerEpoch = 0
        model.train(True)
        print('Epoch = {}'.format(epoch + 1))
        writer.add_scalar('lr', optimizerFn.param_groups[0]['lr'], epoch + 1)
        for i, (inputs, targets) in enumerate(trainLoader):
            iterPerEpoch += 1
            optimizerFn.zero_grad()
            if (torch.cuda.is_available()):
                inputVariable1 = Variable(inputs.permute(1, 0, 2, 3, 4).cuda())
                labelVariable = Variable(targets.cuda())
            else:
                inputVariable1 = Variable(inputs.permute(1, 0, 2, 3, 4))
                labelVariable = Variable(targets)
            outputLabel = model(inputVariable1)
            loss = lossFn(outputLabel, labelVariable)
            loss.backward()
            optimizerFn.step()
            outputProb = torch.nn.Softmax(dim=1)(outputLabel)
            _, predicted = torch.max(outputProb.data, 1)
            if (torch.cuda.is_available()):
                numCorrTrain += (predicted == targets.cuda()).sum()
            else:
                numCorrTrain += (predicted == targets).sum()
            epochLoss += loss.item()
        avgLoss = epochLoss / iterPerEpoch
        trainAccuracy = (float(numCorrTrain) * 100) / float(numTrainInstances)
        train_loss.append(avgLoss)
        train_acc.append(trainAccuracy)
        print('Training: Loss = {} | Accuracy = {}% '.format(
            avgLoss, trainAccuracy))
        writer.add_scalar('train/epochLoss', avgLoss, epoch + 1)
        writer.add_scalar('train/accuracy', trainAccuracy, epoch + 1)
        trainLogLoss.write('Training loss after {} epoch = {}\n'.format(
            epoch + 1, avgLoss))
        trainLogAcc.write('Training accuracy after {} epoch = {}\n'.format(
            epoch + 1, trainAccuracy))

        if (epoch + 1) % evalInterval == 0:
            model.train(False)
            print('Evaluating...')
            validationLossEpoch = 0
            validationIter = 0
            numCorrTest = 0
            for j, (inputs, targets) in enumerate(validationLoader):
                validationIter += 1
                #if evalMode == 'centerCrop':
                if (torch.cuda.is_available()):
                    inputVariable1 = Variable(inputs.permute(1, 0, 2, 3,
                                                             4).cuda(),
                                              requires_grad=False)
                    labelVariable = Variable(targets.cuda(async=True),
                                             requires_grad=False)
                else:
                    inputVariable1 = Variable(inputs.permute(1, 0, 2, 3, 4),
                                              requires_grad=False)
                    labelVariable = Variable(targets, requires_grad=False)
                # else:
                #     if(torch.cuda.is_available()):
                #         inputVariable1 = Variable(inputs[0].permute(1, 0, 2, 3, 4).cuda(), requires_grad=False)
                #         labelVariable = Variable(targets.cuda(async=True), requires_grad=False)
                #     else:
                #         inputVariable1 = Variable(inputs[0].permute(1, 0, 2, 3, 4), requires_grad=False)
                #         labelVariable = Variable(targets, requires_grad=False)
                outputLabel = model(inputVariable1)
                validationLoss = lossFn(outputLabel, labelVariable)
                validationLossEpoch += validationLoss.item()
                outputProb = torch.nn.Softmax(dim=1)(outputLabel)
                _, predicted = torch.max(outputProb.data, 1)
                if (torch.cuda.is_available()):
                    numCorrTest += (predicted == targets[0].cuda()).sum()
                else:
                    numCorrTest += (predicted == targets[0]).sum()
            validationAccuracy = (float(numCorrTest) *
                                  100) / float(numValidationInstances)
            avgValidationLoss = validationLossEpoch / validationIter
            val_loss.append(avgValidationLoss)
            val_acc.append(validationAccuracy)
            print('Testing: Loss = {} | Accuracy = {}% '.format(
                avgValidationLoss, validationAccuracy))
            writer.add_scalar('test/epochloss', avgValidationLoss, epoch + 1)
            writer.add_scalar('test/accuracy', validationAccuracy, epoch + 1)
            validationLogLoss.write('valid Loss after {} epochs = {}\n'.format(
                epoch + 1, avgValidationLoss))
            validationLogAcc.write(
                'valid Accuracy after {} epochs = {}%\n'.format(
                    epoch + 1, validationAccuracy))
            if validationAccuracy > minAccuracy:
                bestmodel = model
                minAccuracy = validationAccuracy
    '''plotting the accuracy and loss curves'''
    if plotting:
        xc = range(1, numEpochs + 1)
        xv = []
        for i in xc:
            if (i % evalInterval == 0):
                xv.append(i)
        plt.figure(1, figsize=(7, 5))
        plt.plot(xc, train_loss)
        plt.plot(xv, val_loss)
        plt.xlabel('num of Epochs')
        plt.ylabel('loss')
        plt.title('train_loss vs val_loss')
        plt.grid(True)
        plt.legend(['train', 'val'])
        #print plt.style.available # use bmh, classic,ggplot for big pictures
        plt.style.use(['classic'])
        plt.savefig(modelFolder + "/lossCurve.png")

        plt.figure(2, figsize=(7, 5))
        plt.plot(xc, train_acc)
        plt.plot(xv, val_acc)
        plt.xlabel('num of Epochs')
        plt.ylabel('accuracy')
        plt.title('train_acc vs val_acc')
        plt.grid(True)
        plt.legend(['train', 'val'], loc=4)
        #print plt.style.available # use bmh, classic,ggplot for big pictures
        plt.style.use(['classic'])
        plt.savefig(modelFolder + "/accuracyCurve.png")
        #plt.show()
    trainLogAcc.close()
    validationLogAcc.close()
    trainLogLoss.close()
    validationLogLoss.close()
    writer.export_scalars_to_json(modelFolder + "/all_scalars.json")
    writer.close()
    return bestmodel, validationAccuracy