예제 #1
0
    def __maybe_cross_val_lr(self, test_every, num_epochs_cv=8):
        if not num_epochs_cv:
            self.num_epochs_cv = 0
            return self.learning_rate
        elif self.num_epochs < num_epochs_cv:
            self.num_epochs_cv = self.num_epochs
        else:
            self.num_epochs_cv = num_epochs_cv

        if self.settings.BATCH_NORM:  #i.e. generally larger learning_rate with BN
            lrs = [0.006, 0.003, 0.015, 0.0015]
        else:
            lrs = [0.003, 0.001, 0.006, 0.0006]

        res = []
        optimizers = []

        for idx, lr in enumerate(lrs):
            print("lr:", lr)

            ML_utils.set_seeds()  #set seeds before init model
            self.model = self.settings.AE_MODEL_TYPE(
                **self.settings.get_kwargs())
            self.optimizer = optim.Adam(self.model.parameters(), lr)
            test_losses = []
            train_losses = []

            for epoch in range(self.num_epochs_cv):
                train, test = self.train_one_epoch(epoch, 1, test_every,
                                                   self.num_epochs_cv)
                if test:
                    test_losses.append(test)
                train_losses.append(train)

            df = pd.DataFrame(train_losses,
                              columns=[
                                  "epoch", "reconstruction_err", "DA_MAE",
                                  "DA_ratio_improve_MAE"
                              ])
            train_final = df.tail(1).reconstruction_err

            res.append(train_final.values[0])
            optimizers.append(self.optimizer)

            #save model if best so far

            if res[-1] == min(res):
                best_test = test_losses
                best_train = train_losses
                best_idx = idx
                model_fp_new = "{}{}-{}.pth".format(self.model_dir, epoch, lr)
                torch.save(self.model.state_dict(), model_fp_new)
                best_model = self.model

        self.learning_rate = lrs[best_idx]
        self.optimizer = optimizers[best_idx]
        self.model = best_model
        test_loss = best_test
        train_loss = best_train
        return self.learning_rate, train_loss, test_loss
예제 #2
0
    def __init__(self, AE_settings, expdir, calc_DA_MAE=False, batch_sz=BATCH):
        """Initilaizes the AE training class.

        ::AE_settings - a settings.config.Config class with the DA settings
        ::expdir - a directory of form `experiments/<possible_path>` to keep logs
        ::calc_DA_MAE - boolean. If True, training will evaluate DA Mean Absolute Error
            during the training cycle. Note: this is *MUCH* slower
        """

        self.settings = AE_settings

        err_msg = """AE_settings must be an AE configuration class"""
        assert self.settings.COMPRESSION_METHOD == "AE", err_msg

        self.expdir = self.__init_expdir(expdir)

        self.test_fp = self.expdir + "test.csv"
        self.train_fp = self.expdir + "train.csv"
        self.settings_fp = self.expdir + "settings.txt"
        self.calc_DA_MAE = calc_DA_MAE

        self.batch_sz = batch_sz
        self.settings.batch_sz = batch_sz

        ML_utils.set_seeds()  #set seeds before init model

        self.model = AE_settings.AE_MODEL_TYPE(**AE_settings.get_kwargs())
        print("Number of parameters:",
              sum(p.numel() for p in self.model.parameters()))

        self.device = ML_utils.get_device()
예제 #3
0
def main():
    dir = "/data/home/jfm1118/DA/experiments/train_DA_Pressure/2-l4NBN/" # 299.pth"
    model, settings = ML_utils.load_model_and_settings_from_dir(dir)

    settings.TOL = 1e-3
    settings.SAVE = False
    settings.export_env_vars()

    #Load data
    loader, splitter = GetData(), SplitData()
    X = loader.get_X(settings)
    train_X, test_X, u_c, X, mean, std = splitter.train_test_DA_split_maybe_normalize(X, settings)

    L1 = torch.nn.L1Loss(reduction='sum')
    L2 = torch.nn.MSELoss(reduction="sum")


    datasets = {"train": train_X,
                "test": test_X,
                "u_c": u_c,
                "mean": mean,
                "u_0": np.zeros_like(u_c)}
    # datasets = {
    #             "train1": train_X[:1],
    #             "train2": train_X[:2],
    #             "train3": train_X[:3],
    #             "train4": train_X[:4],
    #             "train5": train_X[:5],
    #             "train6": train_X[:6],
    #             }

    for name, data in datasets.items():

        if len(data.shape) in [1, 3]:
            num_states = 1
        else:
            num_states = data.shape[0]

        device = ML_utils.get_device()
        data_tensor = torch.Tensor(data)
        data_tensor = data_tensor.to(device)


        DA_pipeline = DAPipeline(settings, model)


        encoder = DA_pipeline.data.get("encoder")
        decoder = DA_pipeline.data.get("decoder")

        data_hat = decoder(encoder(data))
        data_hat = torch.Tensor(data_hat)
        data_hat = data_hat.to(device)

        
        l1 = L1(data_hat, data_tensor)
        l2 = L2(data_hat, data_tensor)

        print("name: {}, \nL1: {:.2f}\nL2: {:.2f}\n".format(name, l1 / num_states, l2 / num_states,))
        print()
def main():

    model, settings = ML_utils.load_model_and_settings_from_dir(
        DIR, device_idx=GPU_DEVICE)
    device = ML_utils.get_device(device_idx=GPU_DEVICE)

    initializer = VDAInit(settings, model)
    vdadata = initializer.run()
    encoder = vdadata.get("encoder")

    loader, splitter = GetData(), SplitData()
    X = loader.get_X(settings)

    train_X, test_X, u_c, X, mean, std = splitter.train_test_DA_split_maybe_normalize(
        X, settings)
    settings.AUGMENTATION = False

    train_loader, test_loader = loader.get_train_test_loaders(settings,
                                                              32,
                                                              num_workers=6)

    Z = []
    for Bidx, x in enumerate(test_loader):
        x, = x
        z = encoder(x)
        Z.append(z)
    Z_test = np.concatenate(Z, axis=0)
    print(Z_test.shape)
    #Compare all test data with all other test data
    tot, tot_abs = 0, 0
    number = 0
    for idx1 in range(Z_test.shape[0]):
        for idx2 in range(Z_test.shape[0]):
            if idx2 <= idx1:
                continue
            res = compare_overlap(Z_test[idx1], Z_test[idx2])
            tot_abs += np.abs(res)
            tot += res
            number += 1
            if number % 10000 == 0 and number != 0:
                print(number, tot_abs / number, tot / number)
    print("Final", tot_abs / number, tot / number)
    def select_obs(self, mode, vec, frac=None):
        """Selects and return a subset of observations and their indexes
        from vec according to a user selected mode"""
        npoints = self.get_npoints_from_shape(vec.shape)

        if mode == "rand":
            # Define observations as a random subset of the control state.
            nobs = int(frac * npoints)  #number of observations

            ML_utils.set_seeds(
                seed=self.settings.SEED
            )  #set seeds so that the selected subset is the same every time
            obs_idx = random.sample(
                range(npoints), nobs)  #select nobs integers w/o replacement
            observations = np.take(vec, obs_idx)
        elif mode == "single_max":
            nobs = 1
            obs_idx = np.argmax(vec)
            obs_idx = [obs_idx]
            observations = np.take(vec, obs_idx)
        return observations, obs_idx, nobs
예제 #6
0
    def training_loop_AE(self,
                         start_epoch,
                         num_epoch,
                         device=None,
                         print_every=2,
                         test_every=5,
                         save_every=5,
                         model_dir=None):
        """Runs a torch AE model training loop.
        NOTE: Ensure that the loss_fn is in mode "sum"
        """
        model = self.model
        self.model_dir = model_dir

        if device == None:
            device = ML_utils.get_device()
        self.device = device

        ML_utils.set_seeds()
        train_losses = []
        test_losses = []
        epoch = num_epoch - 1  #for case where no training occurs

        for epoch in range(start_epoch, num_epoch):

            train_loss, test_loss = self.train_one_epoch(
                epoch, print_every, test_every, num_epoch)
            train_losses.append(train_loss)
            if test_loss:
                test_losses.append(test_loss)

        if epoch % save_every != 0 and self.model_dir != None:
            #Save model (if new model hasn't just been saved)
            model_fp_new = "{}{}.pth".format(self.model_dir, epoch)
            torch.save(model.state_dict(), model_fp_new)

        return train_losses, test_losses
    def vda_setup(self, settings):
        """Generates matrices for VarDA. All returned matrices are in the
        (n X M) format (as typical in VarDA) although when
        settings.THREE_DIM = True, some are 4-dimensional"""
        data = {}
        loader = GetData()
        splitter = SplitData()
        X = loader.get_X(settings)

        train_X, test_X, u_c, X, mean, std = splitter.train_test_DA_split_maybe_normalize(
            X, settings)

        V = self.create_V_from_X(train_X, settings)

        #Deal with dimensions:
        #currently dim are: (M x n ) or (M x nx x ny x nz)
        #change to (n x M) or (nx x ny x nz x M)
        if not settings.THREE_DIM:
            X = X.T
            train_X = train_X.T
            test_X = test_X.T
            V = V.T

        else:
            # can flatten V as it will only be used for SVD (which ignores 3D location)
            V = V.reshape((V.shape[0], -1)).T

            X = np.moveaxis(X, 0, 3)
            train_X = np.moveaxis(train_X, 0, 3)
            test_X = np.moveaxis(test_X, 0, 3)

        # We will take initial condition u_0, as mean of historical data
        if settings.NORMALIZE:
            u_0 = np.zeros(settings.get_n())  #since the data is mean centred
        else:
            u_0 = mean

        #flatten 3D vectors:
        u_c = u_c.flatten()
        std = std.flatten()
        mean = mean.flatten()
        u_0 = u_0.flatten()

        observations, obs_idx, nobs = self.select_obs(
            settings.OBS_MODE, u_c,
            settings.OBS_FRAC)  #options are specific for rand

        #Now define quantities required for 3D-VarDA - see Algorithm 1 in Rossella et al (2019)
        H_0 = self.create_H(obs_idx, settings.get_n(), nobs,
                            settings.THREE_DIM)
        d = observations - H_0 @ u_0  #'d' in literature
        #R_inv = self.create_R_inv(OBS_VARIANCE, nobs)

        device = ML_utils.get_device(False)

        data = {
            "d": d,
            "G": H_0,
            "V": V,
            "observations": observations,
            "u_c": u_c,
            "u_0": u_0,
            "X": X,
            "train_X": train_X,
            "test_X": test_X,
            "std": std,
            "mean": mean,
            "device": device
        }

        return data, std, mean
예제 #8
0
    def train(self,
              num_epoch=100,
              learning_rate=0.00025,
              print_every=2,
              test_every=5):

        self.learning_rate = learning_rate
        self.num_epochs = num_epoch

        settings = self.settings

        if settings.SAVE == True:
            self.model_dir = self.expdir
        else:
            self.model_dir = None

        #data
        loader = GetData()
        splitter = SplitData()
        X = loader.get_X(settings)

        self.train_X, self.test_X, DA_u_c, X_norm, mean, std = splitter.train_test_DA_split_maybe_normalize(
            X, settings)

        #Add Channel if we are in 3D case
        if settings.THREE_DIM:
            self.train_X = np.expand_dims(self.train_X, 1)
            self.test_X = np.expand_dims(self.test_X, 1)

        #Dataloaders
        train_dataset = TensorDataset(torch.Tensor(self.train_X))
        self.train_loader = DataLoader(train_dataset,
                                       self.batch_sz,
                                       shuffle=True,
                                       num_workers=6)
        test_dataset = TensorDataset(torch.Tensor(self.test_X))
        test_batch_sz = min(self.test_X.shape[0], self.batch_sz)
        self.test_loader = DataLoader(test_dataset, test_batch_sz)

        device = ML_utils.get_device()

        self.loss_fn = torch.nn.L1Loss(reduction='sum')

        self.learning_rate, train_losses, test_losses = self.__maybe_cross_val_lr(
            test_every=test_every)

        settings.learning_rate = self.learning_rate  #for logging

        train_losses_, test_losses_ = self.training_loop_AE(
            self.num_epochs_cv,
            self.num_epochs,
            device,
            print_every=print_every,
            test_every=test_every,
            model_dir=self.model_dir)
        if train_losses_:
            train_losses.extend(train_losses_)
        if test_losses_:
            test_losses.extend(test_losses_)

        #Save results and settings file (so that it can be exactly reproduced)
        if settings.SAVE == True:
            self.to_csv(train_losses, self.train_fp)
            self.to_csv(test_losses, self.test_fp)
            with open(self.settings_fp, "wb") as f:
                pickle.dump(settings, f)

        return self.model