Exemple #1
0
    def sample(self, batch_size):

        sample = Variable(torch.randn(batch_size, self.z_dim))
        recon_x = self.decoder(sample).detach().numpy()
        result = descale(torch.Tensor(recon_x), self.state_low,
                         self.state_high, self.action_low, self.action_high,
                         self.reward_low, self.reward_high)

        return (torch.FloatTensor(result[:, 0:3]).to(self.device),
                torch.FloatTensor(result[:, 3]).unsqueeze(1).to(self.device),
                torch.FloatTensor(result[:, 4:7]).to(self.device),
                torch.FloatTensor(result[:, -2]).unsqueeze(1).to(self.device),
                torch.FloatTensor(
                    np.random.choice(2, batch_size,
                                     p=[1 / 200.0, 199 / 200.0
                                        ])).unsqueeze(1).to(self.device))
Exemple #2
0
def driver(inputdir,
           outputdir,
           datadir,
           plotdir,
           preddir,
           trainflag,
           validflag,
           testflag,
           normalize,
           fmean,
           fstdev,
           scale,
           fmin,
           fmax,
           scalelims,
           fsize,
           rmse_file,
           r2_file,
           inD,
           outD,
           ilog,
           olog,
           TFRfile,
           batch_size,
           ncores,
           buffer_size,
           gridsearch,
           architectures,
           layers,
           lay_params,
           activations,
           act_params,
           nodes,
           lengthscale,
           max_lr,
           clr_mode,
           clr_steps,
           epochs,
           patience,
           weight_file,
           resume,
           plot_cases,
           fxvals,
           xlabel,
           ylabel,
           filters=None,
           filtconv=1.):
    """
    Driver function to handle model training and evaluation.

    Inputs
    ------
    inputdir   : string. Path/to/directory of inputs.
    outputdir  : string. Path/to/directory of outputs.
    datadir    : string. Path/to/directory of data.
    plotdir    : string. Path/to/directory of plots.
    preddir    : string. Path/to/directory of predictions.
    trainflag  : bool.   Determines whether to train    the NN model.
    validflag  : bool.   Determines whether to validate the NN model.
    testflag   : bool.   Determines whether to test     the NN model.
    normalize  : bool.   Determines whether to normalize the data.
    fmean      : string. Path/to/file of mean  of training data.
    fstdev     : string. Path/to/file of stdev of training data.
    scale      : bool.   Determines whether to scale the data.
    fmin       : string. Path/to/file of minima of training data.
    fmax       : string. Path/to/file of maxima of training data.
    scalelims  : list, floats. [min, max] of range of scaled data.
    rmse_file  : string. Prefix for savefiles for RMSE calculations.
    r2_file    : string. Prefix for savefiles for R2 calculations.
    inD        : int.    Dimensionality of the input  data.
    outD       : int.    Dimensionality of the output data.
    ilog       : bool.   Determines whether to take the log10 of intput  data.
    olog       : bool.   Determines whether to take the log10 of output data.
    TFRfile    : string. Prefix for TFRecords files.
    batch_size : int.    Size of batches for training/validating/testing.
    ncores     : int.    Number of cores to use to load data cases.
    buffer_size: int.    Number of data cases to pre-load in memory.
    gridsearch : bool.   Determines whether to perform a grid search over 
                         `architectures`.
    architectures: list. Model architectures to consider.
    layers     : list, str.  Types of hidden layers.
    lay_params : list, ints. Parameters for the layer type 
                             E.g., kernel size
    activations: list, str.  Activation functions for each hidden layer.
    act_params : list, floats. Parameters for the activation functions.
    nodes      : list, ints. For layers with nodes, number of nodes per layer.
    lengthscale: float.  Minimum learning rat.e
    max_lr     : float.  Maximum learning rate.
    clr_mode   : string. Sets the cyclical learning rate function.
    clr_steps  : int.    Number of steps per cycle of the learning rate.
    epochs     : int.    Max number of iterations through dataset for training.
    patience   : int.    If no model improvement after `patience` epochs, 
                         halts training.
    weight_file: string. Path/to/file where NN weights are saved.
    resume     : bool.   Determines whether to resume training.
    plot_cases : list, ints. Cases from test set to plot.
    fxvals     : string. Path/to/file of X-axis values to correspond to 
                         predicted Y values.
    xlabel     : string. X-axis label for plotting.
    ylabel     : string. Y-axis label for plotting.
    filters    : list, strings.  Paths/to/filter files.  Default: None
                         If specified, will compute RMSE/R2 stats over the 
                         integrated filter bandpasses.
    filtconv   : float.  Conversion factor for filter file x-axis values to 
                         desired unit.  Default: 1.0
    """
    # Get file names, calculate number of cases per file
    print('Loading files & calculating total number of batches...')

    try:
        datsize = np.load(inputdir + fsize)
        num_train = datsize[0]
        num_valid = datsize[1]
        num_test = datsize[2]
    except:
        ftrain = glob.glob(datadir + 'train' + os.sep + '*.npy')
        fvalid = glob.glob(datadir + 'valid' + os.sep + '*.npy')
        ftest = glob.glob(datadir + 'test' + os.sep + '*.npy')
        num_train = U.data_set_size(ftrain, ncores)
        num_valid = U.data_set_size(fvalid, ncores)
        num_test = U.data_set_size(ftest, ncores)
        np.save(inputdir + fsize,
                np.array([num_train, num_valid, num_test], dtype=int))
        del ftrain, fvalid, ftest

    print("Data set sizes")
    print("Training   data:", num_train)
    print("Validation data:", num_valid)
    print("Testing    data:", num_test)
    print("Total      data:", num_train + num_valid + num_test)

    train_batches = num_train // batch_size
    valid_batches = num_valid // batch_size
    test_batches = num_test // batch_size

    # Update `clr_steps`
    if clr_steps == "range test":
        clr_steps = train_batches * epochs
        rng_test = True
    else:
        clr_steps = train_batches * int(clr_steps)
        rng_test = False

    # Get mean/stdev for normalizing
    if normalize:
        print('\nNormalizing the data...')
        try:
            mean = np.load(inputdir + fmean)
            stdev = np.load(inputdir + fstdev)
        except:
            print("Calculating the mean and standard deviation of the data " +\
                  "using Welford's method.")
            # Compute stats
            ftrain = glob.glob(datadir + 'train' + os.sep + '*.npy')
            mean, stdev, datmin, datmax = S.mean_stdev(ftrain, inD, ilog, olog)
            np.save(inputdir + fmean, mean)
            np.save(inputdir + fstdev, stdev)
            np.save(inputdir + fmin, datmin)
            np.save(inputdir + fmax, datmax)
            del datmin, datmax, ftrain
        print("mean :", mean)
        print("stdev:", stdev)
        # Slice desired indices
        x_mean, y_mean = mean[:inD], mean[inD:]
        x_std, y_std = stdev[:inD], stdev[inD:]
        # Memory cleanup -- no longer need full mean/stdev arrays
        del mean, stdev
    else:
        x_mean = 0.
        x_std = 1.
        y_mean = 0.
        y_std = 1.

    if olog:
        # To properly calculate RMSE & R2 for log-scaled output
        try:
            y_mean_delog = np.load(inputdir +
                                   fmean.replace(".npy", "_delog.npy"))
        except:
            ftrain = glob.glob(datadir + 'train' + os.sep + '*.npy')
            mean_delog = S.mean_stdev(ftrain, inD, ilog, False)[0]
            del ftrain
            y_mean_delog = mean_delog[inD:]
            np.save(inputdir + fmean.replace(".npy", "_delog.npy"),
                    y_mean_delog)
    else:
        y_mean_delog = y_mean

    # Get min/max values for scaling
    if scale:
        print('\nScaling the data...')
        try:
            datmin = np.load(inputdir + fmin)
            datmax = np.load(inputdir + fmax)
        except:
            ftrain = glob.glob(datadir + 'train' + os.sep + '*.npy')
            mean, stdev, datmin, datmax = S.mean_stdev(ftrain, inD, ilog, olog)
            np.save(inputdir + fmean, mean)
            np.save(inputdir + fstdev, stdev)
            np.save(inputdir + fmin, datmin)
            np.save(inputdir + fmax, datmax)
            del mean, stdev, ftrain
        print("min  :", datmin)
        print("max  :", datmax)
        # Slice desired indices
        x_min, y_min = datmin[:inD], datmin[inD:]
        x_max, y_max = datmax[:inD], datmax[inD:]
        # Memory cleanup -- no longer need min/max arrays
        del datmin, datmax

        # Normalize min/max values
        if normalize:
            x_min = U.normalize(x_min, x_mean, x_std)
            x_max = U.normalize(x_max, x_mean, x_std)
            y_min = U.normalize(y_min, y_mean, y_std)
            y_max = U.normalize(y_max, y_mean, y_std)
    else:
        x_min = 0.
        x_max = 1.
        y_min = 0.
        y_max = 1.
        scalelims = [0., 1.]

    # Get TFRecord file names
    print('\nLoading TFRecords file names...')
    TFRpath = inputdir + 'TFRecords' + os.sep + TFRfile
    ftrain_TFR = glob.glob(TFRpath + 'train*.tfrecords')
    fvalid_TFR = glob.glob(TFRpath + 'valid*.tfrecords')
    ftest_TFR = glob.glob(TFRpath + 'test*.tfrecords')

    if len(ftrain_TFR) == 0 or len(fvalid_TFR) == 0 or len(ftest_TFR) == 0:
        # Doesn't exist -- make them
        print("\nSome TFRecords files do not exist yet.")
        ftrain = glob.glob(datadir + 'train' + os.sep + '*.npy')
        fvalid = glob.glob(datadir + 'valid' + os.sep + '*.npy')
        ftest = glob.glob(datadir + 'test' + os.sep + '*.npy')
        if len(ftrain_TFR) == 0:
            print("Making TFRecords for training data...")
            U.make_TFRecord(
                inputdir + 'TFRecords' + os.sep + TFRfile + 'train.tfrecords',
                ftrain, inD, ilog, olog, batch_size, train_batches)
        if len(fvalid_TFR) == 0:
            print("\nMaking TFRecords for validation data...")
            U.make_TFRecord(
                inputdir + 'TFRecords' + os.sep + TFRfile + 'valid.tfrecords',
                fvalid, inD, ilog, olog, batch_size, valid_batches)
        if len(ftest_TFR) == 0:
            print("\nMaking TFRecords for test data...")
            U.make_TFRecord(
                inputdir + 'TFRecords' + os.sep + TFRfile + 'test.tfrecords',
                ftest, inD, ilog, olog, batch_size, test_batches)
        print("\nTFRecords creation complete.")
        # Free memory
        del ftrain, fvalid, ftest
        # Get TFR file names for real this time
        ftrain_TFR = glob.glob(TFRpath + 'train*.tfrecords')
        fvalid_TFR = glob.glob(TFRpath + 'valid*.tfrecords')
        ftest_TFR = glob.glob(TFRpath + 'test*.tfrecords')

    # Load the xvals
    if fxvals is not None:
        xvals = np.load(fxvals)
    else:
        xvals = None

    # Perform grid search
    if gridsearch:
        # Train a model for each architecture, w/ unique directories
        print("\nPerforming a grid search.\n")
        maxlen = 0
        for i, arch in enumerate(architectures):
            if len(arch) > maxlen:
                maxlen = len(arch)
            archdir = os.path.join(outputdir, arch, '')
            wsplit = weight_file.rsplit(os.sep, 1)[1].rsplit('.', 1)
            wfile = ''.join([archdir, wsplit[0], '_', arch, '.', wsplit[1]])
            U.make_dir(archdir)
            nn = NNModel(ftrain_TFR,
                         fvalid_TFR,
                         ftest_TFR,
                         inD,
                         outD,
                         olog,
                         x_mean,
                         x_std,
                         y_mean,
                         y_std,
                         x_min,
                         x_max,
                         y_min,
                         y_max,
                         scalelims,
                         ncores,
                         buffer_size,
                         batch_size,
                         [train_batches, valid_batches, test_batches],
                         layers[i],
                         lay_params[i],
                         activations[i],
                         act_params[i],
                         nodes[i],
                         lengthscale,
                         max_lr,
                         clr_mode,
                         clr_steps,
                         wfile,
                         stop_file='./STOP',
                         resume=resume,
                         train_flag=True,
                         shuffle=True)
            nn.train(train_batches, valid_batches, epochs, patience)
            P.loss(nn, archdir)
        # Print/save out the minmium validation loss for each architecture
        minvl = np.ones(len(architectures)) * np.inf
        print('Grid search summary')
        print('-------------------')
        with open(outputdir + 'gridsearch.txt', 'w') as foo:
            foo.write('Grid search summary\n')
            foo.write('-------------------\n')
        for i, arch in enumerate(architectures):
            archdir = os.path.join(outputdir, arch, '')
            history = np.load(archdir + 'history.npz')
            minvl[i] = np.amin(history['val_loss'])
            print(arch.ljust(maxlen, ' ') + ': ' + str(minvl[i]))
            with open(outputdir + 'gridsearch.txt', 'a') as foo:
                foo.write(arch.ljust(maxlen, ' ') + ': ' \
                          + str(minvl[i]) + '\n')
        return

    # Train a model
    if trainflag:
        print('\nBeginning model training.\n')
        nn = NNModel(ftrain_TFR,
                     fvalid_TFR,
                     ftest_TFR,
                     inD,
                     outD,
                     olog,
                     x_mean,
                     x_std,
                     y_mean,
                     y_std,
                     x_min,
                     x_max,
                     y_min,
                     y_max,
                     scalelims,
                     ncores,
                     buffer_size,
                     batch_size, [train_batches, valid_batches, test_batches],
                     layers,
                     lay_params,
                     activations,
                     act_params,
                     nodes,
                     lengthscale,
                     max_lr,
                     clr_mode,
                     clr_steps,
                     weight_file,
                     stop_file='./STOP',
                     train_flag=True,
                     shuffle=True,
                     resume=resume)
        nn.train(train_batches, valid_batches, epochs, patience)
        # Plot the loss
        P.loss(nn, plotdir)

    # Call new model with shuffle=False
    nn = NNModel(ftrain_TFR,
                 fvalid_TFR,
                 ftest_TFR,
                 inD,
                 outD,
                 olog,
                 x_mean,
                 x_std,
                 y_mean,
                 y_std,
                 x_min,
                 x_max,
                 y_min,
                 y_max,
                 scalelims,
                 ncores,
                 buffer_size,
                 batch_size, [train_batches, valid_batches, test_batches],
                 layers,
                 lay_params,
                 activations,
                 act_params,
                 nodes,
                 lengthscale,
                 max_lr,
                 clr_mode,
                 clr_steps,
                 weight_file,
                 stop_file='./STOP',
                 train_flag=False,
                 shuffle=False,
                 resume=False)
    if '.h5' in weight_file or '.hdf5' in weight_file:
        nn.model.load_weights(weight_file)  # Load the model
        # Save in ONNX format
        try:
            onnx_model = keras2onnx.convert_keras(nn.model)
            onnx.save_model(onnx_model,
                            nn.weight_file.rsplit('.', 1)[0] + '.onnx')
        except Exception as e:
            print("Unable to convert the Keras model to ONNX:")
            print(e)
    else:
        nn.model = onnx_to_keras(onnx.load_model(weight_file), ['input_1'])

    # Validate model
    if (validflag or trainflag) and not rng_test:
        print('\nValidating the model...\n')
        # Y values
        print('  Predicting...')
        fvalpred = nn.Yeval('pred',
                            'valid',
                            preddir,
                            denorm=(normalize == False and scale == False))
        fvalpred = glob.glob(fvalpred + '*')

        print('  Loading the true Y values...')
        fvaltrue = nn.Yeval('true',
                            'valid',
                            preddir,
                            denorm=(normalize == False and scale == False))
        fvaltrue = glob.glob(fvaltrue + '*')
        ### RMSE & R2
        print('\n Calculating RMSE & R2...')
        if not normalize and not scale:
            val_stats = S.rmse_r2(fvalpred,
                                  fvaltrue,
                                  y_mean,
                                  olog=olog,
                                  y_mean_delog=y_mean_delog,
                                  x_vals=xvals,
                                  filters=filters,
                                  filtconv=filtconv)
        else:
            val_stats = S.rmse_r2(fvalpred, fvaltrue, y_mean, y_std, y_min,
                                  y_max, scalelims, olog, y_mean_delog, xvals,
                                  filters, filtconv)
        # RMSE
        if np.any(val_stats[0] != -1) and np.any(val_stats[1] != -1):
            print('  Normalized RMSE       : ', val_stats[0])
            print('  Mean normalized RMSE  : ', np.mean(val_stats[0]))
            print('  Denormalized RMSE     : ', val_stats[1])
            print('  Mean denormalized RMSE: ', np.mean(val_stats[1]))
            np.savez(outputdir + rmse_file + '_val_norm.npz',
                     rmse=val_stats[0],
                     rmse_mean=np.mean(val_stats[0]))
            saveRMSEnorm = True
            saveRMSEdenorm = True
        elif np.any(val_stats[0] != -1):
            print('  RMSE     : ', val_stats[0])
            print('  Mean RMSE: ', np.mean(val_stats[0]))
            saveRMSEnorm = True
            saveRMSEdenorm = False
        elif np.any(val_stats[1] != -1):
            print('  RMSE     : ', val_stats[1])
            print('  Mean RMSE: ', np.mean(val_stats[1]))
            saveRMSEnorm = False
            saveRMSEdenorm = True
        else:
            print("  No files passed in to compute RMSE.")
            saveRMSEnorm = False
            saveRMSEdenorm = False
        if saveRMSEnorm:
            P.plot(''.join([plotdir, rmse_file, '_val_norm.png']), xvals,
                   val_stats[0], xlabel, 'RMSE')
            np.savez(outputdir + rmse_file + '_val_norm.npz',
                     rmse=val_stats[0],
                     rmse_mean=np.mean(val_stats[0]))
        if saveRMSEdenorm:
            P.plot(''.join([plotdir, rmse_file, '_val_denorm.png']), xvals,
                   val_stats[1], xlabel, 'RMSE')
            np.savez(outputdir + rmse_file + '_val_denorm.npz',
                     rmse=val_stats[1],
                     rmse_mean=np.mean(val_stats[1]))
        # R2
        if np.any(val_stats[2] != -1) and np.any(val_stats[3] != -1):
            print('  Normalized R2       : ', val_stats[2])
            print('  Mean normalized R2  : ', np.mean(val_stats[2]))
            print('  Denormalized R2     : ', val_stats[3])
            print('  Mean denormalized R2: ', np.mean(val_stats[3]))
            saveR2norm = True
            saveR2denorm = True
        elif np.any(val_stats[2] != -1):
            print('  R2     : ', val_stats[2])
            print('  Mean R2: ', np.mean(val_stats[2]))
            saveR2norm = True
            saveR2denorm = False
        elif np.any(val_stats[3] != -1):
            print('  R2     : ', val_stats[3])
            print('  Mean R2: ', np.mean(val_stats[3]))
            saveR2norm = False
            saveR2denorm = True
        else:
            print("  No files passed in to compute R2.")
            saveR2norm = False
            saveR2denorm = False
        if saveR2norm:
            P.plot(''.join([plotdir, r2_file, '_val_norm.png']), xvals,
                   val_stats[2], xlabel, '$R^2$')
            np.savez(outputdir + r2_file + '_val_norm.npz',
                     r2=val_stats[2],
                     r2_mean=np.mean(val_stats[2]))
        if saveR2denorm:
            P.plot(''.join([plotdir, r2_file, '_val_denorm.png']), xvals,
                   val_stats[3], xlabel, '$R^2$')
            np.savez(outputdir + r2_file + '_val_denorm.npz',
                     r2=val_stats[3],
                     r2_mean=np.mean(val_stats[3]))

    # Evaluate model on test set
    if testflag and not rng_test:
        print('\nTesting the model...\n')
        # Y values
        print('  Predicting...')
        ftestpred = nn.Yeval('pred',
                             'test',
                             preddir,
                             denorm=(normalize == False and scale == False))
        ftestpred = glob.glob(ftestpred + '*')

        print('  Loading the true Y values...')
        ftesttrue = nn.Yeval('true',
                             'test',
                             preddir,
                             denorm=(normalize == False and scale == False))
        ftesttrue = glob.glob(ftesttrue + '*')
        ### RMSE & R2
        print('\n Calculating RMSE & R2...')
        if not normalize and not scale:
            test_stats = S.rmse_r2(ftestpred,
                                   ftesttrue,
                                   y_mean,
                                   olog=olog,
                                   y_mean_delog=y_mean_delog,
                                   x_vals=xvals,
                                   filters=filters,
                                   filtconv=filtconv)
        else:
            test_stats = S.rmse_r2(ftestpred, ftesttrue, y_mean, y_std, y_min,
                                   y_max, scalelims, olog, y_mean_delog, xvals,
                                   filters, filtconv)
        # RMSE
        if np.any(test_stats[0] != -1) and np.any(test_stats[1] != -1):
            print('  Normalized RMSE       : ', test_stats[0])
            print('  Mean normalized RMSE  : ', np.mean(test_stats[0]))
            print('  Denormalized RMSE     : ', test_stats[1])
            print('  Mean denormalized RMSE: ', np.mean(test_stats[1]))
            np.savez(outputdir + rmse_file + '_val_norm.npz',
                     rmse=test_stats[0],
                     rmse_mean=np.mean(test_stats[0]))
            saveRMSEnorm = True
            saveRMSEdenorm = True
        elif np.any(test_stats[0] != -1):
            print('  RMSE     : ', test_stats[0])
            print('  Mean RMSE: ', np.mean(test_stats[0]))
            saveRMSEnorm = True
            saveRMSEdenorm = False
        elif np.any(test_stats[1] != -1):
            print('  RMSE     : ', test_stats[1])
            print('  Mean RMSE: ', np.mean(test_stats[1]))
            saveRMSEnorm = False
            saveRMSEdenorm = True
        else:
            print("  No files passed in to compute RMSE.")
            saveRMSEnorm = False
            saveRMSEdenorm = False
        if saveRMSEnorm:
            P.plot(''.join([plotdir, rmse_file, '_test_norm.png']), xvals,
                   test_stats[0], xlabel, 'RMSE')
            np.savez(outputdir + rmse_file + '_test_norm.npz',
                     rmse=test_stats[0],
                     rmse_mean=np.mean(test_stats[0]))
        if saveRMSEdenorm:
            P.plot(''.join([plotdir, rmse_file, '_test_denorm.png']), xvals,
                   test_stats[1], xlabel, 'RMSE')
            np.savez(outputdir + rmse_file + '_test_denorm.npz',
                     rmse=test_stats[1],
                     rmse_mean=np.mean(test_stats[1]))
        # R2
        if np.any(test_stats[2] != -1) and np.any(test_stats[3] != -1):
            print('  Normalized R2       : ', test_stats[2])
            print('  Mean normalized R2  : ', np.mean(test_stats[2]))
            print('  Denormalized R2     : ', test_stats[3])
            print('  Mean denormalized R2: ', np.mean(test_stats[3]))
            saveR2norm = True
            saveR2denorm = True
        elif np.any(test_stats[2] != -1):
            print('  R2     : ', test_stats[2])
            print('  Mean R2: ', np.mean(test_stats[2]))
            saveR2norm = True
            saveR2denorm = False
        elif np.any(test_stats[3] != -1):
            print('  R2     : ', test_stats[3])
            print('  Mean R2: ', np.mean(test_stats[3]))
            saveR2norm = False
            saveR2denorm = True
        else:
            print("  No files passed in to compute R2.")
            saveR2norm = False
            saveR2denorm = False
        if saveR2norm:
            P.plot(''.join([plotdir, r2_file, '_test_norm.png']), xvals,
                   test_stats[2], xlabel, '$R^2$')
            np.savez(outputdir + r2_file + '_test_norm.npz',
                     r2=test_stats[2],
                     r2_mean=np.mean(test_stats[2]))
        if saveR2denorm:
            P.plot(''.join([plotdir, r2_file, '_test_denorm.png']), xvals,
                   test_stats[3], xlabel, '$R^2$')
            np.savez(outputdir + r2_file + '_test_denorm.npz',
                     r2=test_stats[3],
                     r2_mean=np.mean(test_stats[3]))

    # Plot requested cases
    if not rng_test:
        predfoo = sorted(glob.glob(preddir + 'test' + os.sep + 'pred*'))
        truefoo = sorted(glob.glob(preddir + 'test' + os.sep + 'true*'))
        if len(predfoo) > 0 and len(truefoo) > 0:
            print("\nPlotting the requested cases...")
            nplot = 0
            for v in plot_cases:
                fname = plotdir + 'spec' + str(v) + '_pred-vs-true.png'
                predspec = np.load(predfoo[v // batch_size])[v % batch_size]
                predspec = U.denormalize(
                    U.descale(predspec, y_min, y_max, scalelims), y_mean,
                    y_std)
                truespec = np.load(truefoo[v // batch_size])[v % batch_size]
                truespec = U.denormalize(
                    U.descale(truespec, y_min, y_max, scalelims), y_mean,
                    y_std)
                if olog:
                    predspec[olog] = 10**predspec[olog]
                    truespec[olog] = 10**truespec[olog]
                P.plot_spec(fname, predspec, truespec, xvals, xlabel, ylabel)
                nplot += 1
                print("  Plot " + str(nplot) + "/" + str(len(plot_cases)),
                      end='\r')
            print("")
        else:
            raise Exception("No predictions found in " + preddir + "test.")

    return
Exemple #3
0
    def Yeval(self, mode, dataset, preddir, denorm=False):
        """
        Saves out .NPY files of the true or predicted Y values for a 
        specified data set.

        Inputs
        ------
        mode   : string. 'pred' or 'true'. Specifies whether to save the true 
                         or predicted Y values of  `dataset`.
        dataset: string. 'train', 'valid', or 'test'. Specifies the data set to 
                         make predictions on.
        preddir: string. Path/to/directory where predictions will be saved.
        denorm : bool.   Determines whether to denormalize the predicted values.
        """
        if self.shuffle:
            raise ValueError("This model has shuffled TFRecords.\nCreate a " +\
                        "new NNModel object with shuffle=False and try again.")

        if dataset == 'train':
            X = self.X
            Y = self.Y
            num_batches = self.train_batches
        elif dataset == 'valid':
            X = self.Xval
            Y = self.Yval
            num_batches = self.valid_batches
        elif dataset == 'test':
            X = self.Xte
            Y = self.Yte
            num_batches = self.test_batches
        else:
            raise ValueError("Invalid specification for `dataset` parameter " +\
                    "of NNModel.Yeval().\nAllowed options: 'train', 'valid'," +\
                    " or 'test'\nPlease correct this and try again.")

        # Prefix for the savefiles
        if mode == 'pred' or mode == 'true':
            fname = ''.join([preddir, dataset, os.sep, mode])
        else:
            raise ValueError("Invalid specification for `mode` parameter of " +\
                             "NNModel.Yeval().\nAllowed options: 'pred' or "  +\
                             "'true'\nPlease correct this and try again.")

        if denorm:
            fname = ''.join([fname, '-denorm_'])
        else:
            fname = ''.join([fname, '-norm_'])

        U.make_dir(preddir + dataset)  # Ensure the directory exists

        # Save out the Y values
        y_batch = np.zeros((self.batch_size, self.outD))
        for i in range(num_batches):
            foo = ''.join([fname, str(i).zfill(len(str(num_batches))), '.npy'])
            if mode == 'pred':  # Predicted Y values
                x_batch = K.eval(X)
                y_batch = self.model.predict(x_batch)
            else:  # True Y values
                y_batch = K.eval(Y)
            if denorm:
                y_batch = U.denormalize(
                    U.descale(y_batch, self.y_min, self.y_max, self.scalelims),
                    self.y_mean, self.y_std)
                if self.olog:
                    y_batch[:, self.olog] = 10**y_batch[:, self.olog]
            np.save(foo, y_batch)
            print(''.join(['  Batch ',
                           str(i + 1), '/',
                           str(num_batches)]),
                  end='\r')
        print('')

        return fname
Exemple #4
0
def eval(params,
         nn,
         x_mean,
         x_std,
         y_mean,
         y_std,
         x_min,
         x_max,
         y_min,
         y_max,
         scalelims,
         xvals=None,
         starspec=None,
         factor=None,
         filters=None,
         ifilt=None,
         ilog=False,
         olog=False,
         kll=None,
         count=0,
         burnin=0):
    """
    Evaluates the model for given inputs. 
    Integrates the output according to filters.

    Inputs
    ------
    params   : array. Parameters to be predicted on.
    nn       : object. Trained NN model.
    x_mean   : array. Mean of inputs.
    x_std    : array. Standard deviation of inputs.
    y_mean   : array. Mean of outputs.
    y_std    : array. Standard deviation of outputs.
    x_min    : array. Minima of inputs.
    x_max    : array. Maxima of inputs.
    y_min    : array. Minima of outputs.
    y_max    : array. Maxima of outputs.
    scalelims: list.  [Lower, upper] bounds for scaling.
    xvals    : array. (filler) X-axis values associated with the NN output.
    starspec : array. (optional) Stellar spectrum at `xvals`.
    factor   : float. (optional) Multiplication factor to convert the 
                      de-normalized NN output.
    filters  : list, arrays. (filler) Transmission of filters.
    ifilt    : array. (filler) `xvals` indices where the filters are nonzero.
    ilog     : bool. True if the NN input  is the log10 of the inputs.
    olog     : bool. True if the NN output is the log10 of the outputs.
    kll      : object. (optional) Streaming quantiles calculator.
    count    : array.  Ensures that burned iterations do not 
                       contribute to quantiles.
                       Must be specified if KLL is not None.
    burnin   : int.    Number of burned iterations. 
                       Must be specified if KLL is not None.

    Outputs
    -------
    results: array. Integrated predicted values.
    """
    # Input must be 2D
    if len(params.shape) == 1:
        params = np.expand_dims(params, 0)

    # Log-scale
    if ilog:
        params[:, ilog] = np.log10(params[:, ilog])

    # Normalize & scale
    pars = U.scale(U.normalize(params, x_mean, x_std), x_min, x_max, scalelims)

    # Predict
    pred = nn.predict(pars)

    # Post-process
    # Descale & denormalize
    pred = U.denormalize(U.descale(pred, y_min, y_max, scalelims), y_mean,
                         y_std)
    # De-log
    if olog:
        pred[:, olog] = 10**pred[:, olog]

    # Divide by stellar spectrum
    if starspec is not None:
        pred = pred / starspec

    # Multiply by any conversion factors, e.g., R_p/R_s, unit conversion
    if factor is not None:
        pred *= factor

    # Update the streaming quantiles
    if kll is not None:
        count += 1
        if count[0] > burnin:
            kll.update(pred)

    return pred
Exemple #5
0
def rmse_r2(fpred,
            ftrue,
            y_mean,
            y_std=None,
            y_min=None,
            y_max=None,
            scalelims=None,
            olog=False,
            y_mean_delog=None,
            filters=None,
            x_vals=None,
            filt2um=1.0):
    """
    Calculates the root mean squared error (RMSE) and R-squared for a data set.
    Data must be saved in .NPY file(s), and `fpred` and `ftrue` must exactly 
    correspond.

    Default behavior: compute RMSE/R2 for the raw predictions.

    If y_std, y_min, y_max, scalelims, and olog are specified, 
    it will compute RMSE/R2 for both the raw and denormalized predictions.

    If filters and x_vals are specified, then the RMSE/R2 will be computed on  
    the integrated filter bandpasses, rather than for each output parameter.

    Inputs
    ------
    fpred: list, strings. .NPY files to compute RMSE, predicted values.
    ftrue: list, strings. .NPY files to compute RMSE, true      values.
    y_mean: array. Training set mean value of each output parameter.
    y_std : array. Training set standard deviation of each output parameter.
    y_min : array. Training set minimum of each output parameter.
    y_max : array. Training set maximum of each output parameter.
    scalelims: tuple/list/array. Min/max that the normalized data was scaled to.
    olog  : bool.  Determines if the denormalized values are the log10 of the 
                   true output parameters.
    y_mean_delog: array. Mean of the training set, not log-scaled.
    filters: list, strings. Filter bandpasses to integrate over.
                            Must be 2-column file: wavelength then transmission.
    x_vals : array.         X values corresponding to the Y values.
    filt2um: float.         Conversion factor for filter's wavelengths to 
                            microns.

    Outputs
    -------
    rmse_norm  : array. RMSE for each parameter,   normalized data.
    rmse_denorm: array. RMSE for each parameter, denormalized data.
    r2_norm    : array. R2   for each parameter,   normalized data.
    r2_denorm  : array. R2   for each parameter, denormalized data.

    Notes
    -----
    Data will only be denormalized if y_std, y_min, y_max, scalelims, and olog 
    are all not None.
    """
    if len(fpred) != len(ftrue):
        raise Exception("The prediction/true file structures do not match.\n" +\
                        "Ensure that each set of files follows the same "     +\
                        "exact structure and order.\nSee NNModel.Yeval().")

    # Integrate over filter bandpasses?
    if filters is not None and x_vals is not None:
        integ = True
        # Load filters
        nfilters = len(filters)
        filttran = []
        ifilt = np.zeros((nfilters, 2), dtype=int)
        meanwn = []
        for i in range(nfilters):
            datfilt = np.loadtxt(filters[i])
            # Convert filter wavelenths to microns, then convert um -> cm-1
            finterp = si.interp1d(10000. / (filt2um * datfilt[:, 0]),
                                  datfilt[:, 1],
                                  bounds_error=False,
                                  fill_value=0)
            # Interpolate and normalize
            tranfilt = finterp(x_vals)
            tranfilt = tranfilt / np.trapz(tranfilt, x_vals)
            meanwn.append(np.sum(x_vals * tranfilt) / sum(tranfilt))
            # Find non-zero indices for faster integration
            nonzero = np.where(tranfilt != 0)
            ifilt[i, 0] = max(nonzero[0][0] - 1, 0)
            ifilt[i, 1] = min(nonzero[0][-1] + 1, len(x_vals) - 1)
            filttran.append(tranfilt[ifilt[i, 0]:ifilt[i, 1]])  # Store filter
    else:
        integ = False

    if not olog:
        y_mean_delog = y_mean
    else:
        if y_mean_delog is None:
            raise ValueError("Must give the non-log-scaled training set mean.")

    if all(v is not None for v in [y_std, y_min, y_max, scalelims]) or olog:
        denorm = True
    else:
        denorm = False

    # Variables for computing RMSE & R2
    n = 0  # number of cases seen
    mss = 0  # Model sum of squares
    tss = 0  # True  sum of squares
    rss = 0  # Residual sum of squares -- squared error
    if denorm:
        mss_denorm = 0
        tss_denorm = 0
        rss_denorm = 0
    # By definition, R2 = 1 - rss / tss
    # If mss + rss = tss then R2 = mss / tss

    ### Helper functions to avoid repeating code
    def squared_diffs(pred, true, y_mean):
        """
        Computes squared differences for RMSE/R2 calculations.
        """
        mss = np.sum((pred - y_mean)**2, axis=0)
        tss = np.sum((true - y_mean)**2, axis=0)
        rss = np.sum((true - pred)**2, axis=0)
        return mss, tss, rss

    def integ_spec(pred, true, y_mean, x_vals, filttran, ifilt):
        """
        Integrates and predicted and true spectrum according to filter 
        bandpasses.
        """
        nfilters = len(filttran)
        pred_res = np.zeros((pred.shape[0], nfilters))
        true_res = np.zeros((true.shape[0], nfilters))
        y_mean_res = np.zeros(nfilters)
        for i in range(nfilters):
            pred_spec = pred[:, ifilt[i, 0]:ifilt[i, 1]]
            true_spec = true[:, ifilt[i, 0]:ifilt[i, 1]]
            xval_spec = x_vals[ifilt[i, 0]:ifilt[i, 1]]
            y_mean_spec = y_mean[ifilt[i, 0]:ifilt[i, 1]]
            pred_res[:, i] = np.trapz(pred_spec * filttran[i],
                                      xval_spec,
                                      axis=-1)
            true_res[:, i] = np.trapz(true_spec * filttran[i],
                                      xval_spec,
                                      axis=-1)
            y_mean_res[i] = np.trapz(y_mean_spec * filttran[i], xval_spec)
        return pred_res, true_res, y_mean_res

    # Compute RMSE & R2
    for j in range(len(fpred)):
        # Load batch
        pred = np.load(fpred[j])
        true = np.load(ftrue[j])
        # Add contributions to RMSE/R2
        if integ:
            pred_res, true_res, y_mean_res = integ_spec(
                pred, true, y_mean, x_vals, filttran, ifilt)
            contribs = squared_diffs(pred_res, true_res, y_mean_res)

        else:
            contribs = squared_diffs(pred, true, y_mean)
        n += pred.shape[0]
        mss += contribs[0]
        tss += contribs[1]
        rss += contribs[2]

        if denorm:
            # Calculate this for the denormalized values
            pred = U.denormalize(U.descale(pred, y_min, y_max, scalelims),
                                 y_mean, y_std)
            true = U.denormalize(U.descale(true, y_min, y_max, scalelims),
                                 y_mean, y_std)
            if olog:
                pred[:, olog] = 10**pred[:, olog]
                true[:, olog] = 10**true[:, olog]
            if integ:
                pred_res, true_res, y_mean_res = integ_spec(
                    pred, true, y_mean_delog, x_vals, filttran, ifilt)
                contribs = squared_diffs(pred_res, true_res, y_mean_res)
            else:
                contribs = squared_diffs(pred, true, y_mean_delog)
            mss_denorm += contribs[0]
            tss_denorm += contribs[1]
            rss_denorm += contribs[2]
        print("  Batch " + str(j + 1) + "/" + str(len(fpred)), end='\r')
    print('')
    rmse = (rss / n)**0.5
    r2 = 1 - rss / tss

    if denorm:
        rmse_denorm = (rss_denorm / n)**0.5
        r2_denorm = 1 - rss_denorm / tss_denorm
    else:
        rmse_denorm = -1
        r2_denorm = -1

    return rmse, rmse_denorm, r2, r2_denorm
Exemple #6
0
def eval_Smith_bandinteg(params,
                         nn,
                         x_mean,
                         x_std,
                         y_mean,
                         y_std,
                         x_min,
                         x_max,
                         y_min,
                         y_max,
                         scalelims,
                         wavenum=None,
                         starspec=None,
                         factor=None,
                         filters=None,
                         ifilt=None,
                         ilog=False,
                         olog=False,
                         kll=None,
                         count=0,
                         burnin=0):
    """
    Evaluates the model for given inputs. 
    Integrates the output according to filters.

    Inputs
    ------
    params   : array. Parameters to be predicted on.
    nn       : object. Trained NN model.
    x_mean   : array. Mean of inputs.
    x_std    : array. Standard deviation of inputs.
    y_mean   : array. Mean of outputs.
    y_std    : array. Standard deviation of outputs.
    x_min    : array. Minima of inputs.
    x_max    : array. Maxima of inputs.
    y_min    : array. Minima of outputs.
    y_max    : array. Maxima of outputs.
    scalelims: list.  [Lower, upper] bounds for scaling.
    wavenum  : array. (filler) Wavenumbers (cm-1) associated with the NN output.
    starspec : array. (optional) Stellar spectrum at `wavenum`.
    factor   : float. (optional) Multiplication factor to convert the 
                      de-normalized NN output.
    filters  : list, arrays. (filler) Transmission of filters.
    ifilt    : array. (filler) `wavenum` indices where the filters are nonzero.
    ilog     : bool. True if the NN input  is the log10 of the inputs.
    olog     : bool. True if the NN output is the log10 of the outputs.
    kll      : object. (optional) Streaming quantiles calculator.
    count    : array.  Ensures that burned iterations do not 
                       contribute to quantiles.
                       Must be specified if KLL is not None.
    burnin   : int.    Number of burned iterations. 
                       Must be specified if KLL is not None.

    Outputs
    -------
    results: array. Integrated predicted values.
    """
    # Input must be 2D
    if len(params.shape) == 1:
        params = np.expand_dims(params, 0)
    if ilog:
        params = np.log10(params)
    # Normalize & scale
    pars = U.scale(U.normalize(params, x_mean, x_std), x_min, x_max, scalelims)

    # Predict
    pred = nn.predict(pars)

    # Post-process
    # Descale & denormalize
    pred = U.denormalize(U.descale(pred, y_min, y_max, scalelims), y_mean,
                         y_std)
    # De-log
    if olog:
        pred = 10**pred

    # Enforce cloudtop pressure < surface pressure
    pred[params[:, -1] >= params[:, 3]] = -100
    # Update the streaming quantiles for valid models
    if kll is not None:
        count += 1
        if count[0] > burnin:
            kll.update(pred[params[:, -1] < params[:, 3]])

    if filters is not None and wavenum is not None:
        nfilters = len(filters)
        results = np.zeros((pars.shape[0], nfilters))
        for i in range(nfilters):
            results[:, i] = np.trapz(pred[:, ifilt[i, 0]:ifilt[i, 1]] *
                                     filters[i],
                                     wavenum[ifilt[i, 0]:ifilt[i, 1]],
                                     axis=-1)

        return results
    else:
        return pred