def main():
    df = pd.read_csv('./data/train.csv')
    (df, label_encoder) = utility.encode_labels(df)
    num_classes = len(df['label'].value_counts())
    np.save('./data/label_encoder_classes.npy', label_encoder.classes_)
    for image_size in IMAGE_SIZES:
        if APPLY_ZCA_TRANS:
            print('Making ZCA matrix ...')
            data_loader = dl.get_full_data_loader(df, data_dir=DATA_DIR, batch_size=BATCH_SIZE, image_size=image_size)
            train_dataset_arr = next(iter(data_loader))[0].numpy()
            zca = utility.ZCA()
            zca.fit(train_dataset_arr)
            zca_dic = {'zca_matrix': zca.ZCA_mat, 'zca_mean': zca.mean}
            savemat('./data/zca_data.mat', zca_dic)
            print('Completed making ZCA matrix')
        normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
        train_transform = transforms.Compose([utility.AddPadding(), transforms.Resize((image_size, image_size)), transforms.RandomHorizontalFlip(p=0.5), transforms.RandomRotation(degrees=((- 90), 90)), transforms.RandomVerticalFlip(p=0.5), transforms.ColorJitter(0.4, 0.4, 0.4), transforms.ToTensor(), normalize])
        valid_transform = transforms.Compose([utility.AddPadding(), transforms.Resize((image_size, image_size)), transforms.ToTensor(), normalize])
        train_dataset = dl.HotelImagesDataset(df, root_dir=DATA_DIR, transform=train_transform)
        valid_dataset = dl.HotelImagesDataset(df, root_dir=DATA_DIR, transform=valid_transform)
        (train_loader, valid_loader) = dl.get_train_valid_loader(train_dataset, valid_dataset, batch_size=BATCH_SIZE, random_seed=0)
        for net_type in NETS:
            model = utility.initialize_net(num_classes, net_type, feature_extract=FEATURE_EXTRACT)
            if path.exists(f'./models/model_{net_type}.pt'):
                print('Resuming training on trained model ...')
                model = utility.load_latest_model(model, f'./models/model_{net_type}.pt')
            params_to_update = utility.get_model_params_to_train(model, FEATURE_EXTRACT)
            device = torch.device(('cuda' if torch.cuda.is_available() else 'cpu'))
            model = model.to(device)
            criterion = nn.CrossEntropyLoss()
            optimizer = torch.optim.SGD(params_to_update, lr=0.01, momentum=0.9)
            scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.01, patience=3)
            trained_model = trainer.train_model(device=device, model=model, optimizer=optimizer, criterion=criterion, train_loader=train_loader, valid_loader=valid_loader, scheduler=scheduler, net_type=net_type, epochs=EPOCHS, apply_zca_trans=APPLY_ZCA_TRANS)
            utility.save_current_model(trained_model, f'./models/model_{net_type}.pt')
def main():
    df = pd.read_csv('./data/train.csv')
    (df, label_encoder) = utility.encode_labels(df)
    num_classes = len(df['label'].value_counts())
    np.save('./data/label_encoder_classes.npy', label_encoder.classes_)
    for image_size in IMAGE_SIZES:
        if APPLY_ZCA_TRANS:
            print('Making ZCA matrix ...')
            data_loader = dl.get_full_data_loader(df, data_dir=DATA_DIR, batch_size=BATCH_SIZE, image_size=image_size)
            train_dataset_arr = next(iter(data_loader))[0].numpy()
            zca = utility.ZCA()
            zca.fit(train_dataset_arr)
            zca_dic = {'zca_matrix': zca.ZCA_mat, 'zca_mean': zca.mean}
            savemat('./data/zca_data.mat', zca_dic)
            print('Completed making ZCA matrix')
        normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
        train_transform = transforms.Compose([utility.AddPadding(), transforms.Resize((image_size, image_size)), transforms.RandomHorizontalFlip(p=0.5), transforms.RandomRotation(degrees=((- 90), 90)), transforms.RandomVerticalFlip(p=0.5), transforms.ColorJitter(0.4, 0.4, 0.4), transforms.ToTensor(), normalize])
        valid_transform = transforms.Compose([utility.AddPadding(), transforms.Resize((image_size, image_size)), transforms.ToTensor(), normalize])
        train_dataset = dl.HotelImagesDataset(df, root_dir=DATA_DIR, transform=train_transform)
        valid_dataset = dl.HotelImagesDataset(df, root_dir=DATA_DIR, transform=valid_transform)
        (train_loader, valid_loader) = dl.get_train_valid_loader(train_dataset, valid_dataset, batch_size=BATCH_SIZE, random_seed=0)
        for net_type in NETS:
            model = utility.initialize_net(num_classes, net_type, feature_extract=FEATURE_EXTRACT)
            if path.exists(f'./models/model_{net_type}.pt'):
                print('Resuming training on trained model ...')
                model = utility.load_latest_model(model, f'./models/model_{net_type}.pt')
            params_to_update = utility.get_model_params_to_train(model, FEATURE_EXTRACT)
            device = torch.device(('cuda' if torch.cuda.is_available() else 'cpu'))
            model = model.to(device)
            criterion = nn.CrossEntropyLoss()
            optimizer = torch.optim.SGD(params_to_update, lr=0.01, momentum=0.9)
            scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.01, patience=3)
            trained_model = trainer.train_model(device=device, model=model, optimizer=optimizer, criterion=criterion, train_loader=train_loader, valid_loader=valid_loader, scheduler=scheduler, net_type=net_type, epochs=EPOCHS, apply_zca_trans=APPLY_ZCA_TRANS)
            utility.save_current_model(trained_model, f'./models/model_{net_type}.pt')