def test_nan_score(self):
     k = ff.SqExpKernel(dimension=0, lengthscale=0, sf=0)
     m1 = ff.GPModel(kernel=k, nll=np.nan, ndata=100)
     m2 = ff.GPModel(kernel=k.copy(), nll=0, ndata=100)
     (not_nan, eq_nan) = experiment.remove_nan_scored_models([m1, m2],
                                                             score='bic')
     assert (len(not_nan) == 1) and (len(eq_nan) == 1)
 def test_jitter_model(self):
     print 'jitter model'
     k = ff.SqExpKernel(dimension=0, lengthscale=0, sf=1)
     k1 = k.copy()
     k2 = k.copy()
     print[k, k1, k2]
     assert (k == k1) and (k == k2) and (k1 == k2)
     m1 = ff.GPModel(kernel=k1)
     m2 = ff.GPModel(kernel=k2)
     ff.add_jitter([m1, m2])
     assert (not k == k1) and (not k == k2) and (not k1 == k2)
     print[k, k1, k2]
 def test_simplify(self):
     m = ff.GPModel(mean=ff.MeanZero(),
                    kernel=ff.SumKernel(operands=[
                        ff.ProductKernel(operands=[
                            ff.ConstKernel(sf=0.170186999131),
                            ff.SqExpKernel(dimension=0,
                                           lengthscale=1.02215322228,
                                           sf=5.9042619611)
                        ]),
                        ff.ProductKernel(operands=[
                            ff.NoiseKernel(sf=2.43188502201),
                            ff.ConstKernel(sf=-0.368638271154)
                        ]),
                        ff.ProductKernel(operands=[
                            ff.NoiseKernel(sf=1.47110516981),
                            ff.PeriodicKernel(dimension=0,
                                              lengthscale=-1.19651800365,
                                              period=0.550394248167,
                                              sf=0.131044872864)
                        ]),
                        ff.ProductKernel(operands=[
                            ff.SqExpKernel(dimension=0,
                                           lengthscale=3.33346140605,
                                           sf=3.7579461353),
                            ff.PeriodicKernel(dimension=0,
                                              lengthscale=0.669624964607,
                                              period=0.00216264543496,
                                              sf=2.41995024965)
                        ])
                    ]),
                    likelihood=ff.LikGauss(sf=-np.inf),
                    nll=599.59757993,
                    ndata=144)
     assert not m.simplified() == m
     m = ff.GPModel(mean=ff.MeanZero(),
                    kernel=ff.SumKernel(operands=[
                        ff.ProductKernel(operands=[
                            ff.ConstKernel(sf=0.170186999131),
                            ff.SqExpKernel(dimension=0,
                                           lengthscale=1.02215322228,
                                           sf=5.9042619611)
                        ]),
                        ff.ProductKernel(operands=[
                            ff.NoiseKernel(sf=2.43188502201),
                            ff.ConstKernel(sf=-0.368638271154)
                        ])
                    ]),
                    likelihood=ff.LikGauss(sf=-np.inf),
                    nll=599.59757993,
                    ndata=144)
     assert not m.simplified() == m
 def test_expand_model(self):
     print 'expand model'
     print '2d'
     k = ff.SqExpKernel(dimension=0, lengthscale=0, sf=0)
     m = ff.GPModel(mean=ff.MeanZero(), kernel=k, likelihood=ff.LikGauss())
     expanded = grammar.expand_models(2, [m], base_kernels='SE', rules=None)
     for k in expanded:
         print '\n', k.pretty_print(), '\n'
 def test_repr(self):
     m = ff.MeanZero()
     k = ff.SqExpKernel()
     l = ff.LikGauss()
     regression_model = ff.GPModel(mean=m, kernel=k, likelihood=l)
     print regression_model
     print ff.repr_to_model(regression_model.__repr__())
     assert regression_model == ff.repr_to_model(
         regression_model.__repr__())
 def test_restarts_model(self):
     print 'restart model'
     data_shape = {
         'y_sd': 0,
         'x_sd': [0, 2],
         'x_min': [-10, -100],
         'x_max': [10, 100]
     }
     k = ff.SqExpKernel(dimension=0)
     k1 = k.copy()
     k2 = k.copy()
     print[k, k1, k2]
     assert (k == k1) and (k == k2) and (k1 == k2)
     m1 = ff.GPModel(kernel=k1)
     m2 = ff.GPModel(kernel=k2)
     model_list = ff.add_random_restarts([m1, m2],
                                         n_rand=1,
                                         data_shape=data_shape,
                                         sd=1)
     k1 = model_list[0].kernel
     k2 = model_list[1].kernel
     assert (not k == k1) and (not k == k2) and (not k1 == k2)
     print[k, k1, k2]
 def test_model(self):
     print 'model'
     m = ff.MeanZero()
     k = ff.SqExpKernel()
     l = ff.LikGauss()
     regression_model = ff.GPModel(mean=m,
                                   kernel=k,
                                   likelihood=l,
                                   nll=0,
                                   ndata=100)
     print '\n', regression_model.pretty_print(), '\n'
     print '\n', regression_model.__repr__(), '\n'
     print regression_model.bic
     print regression_model.aic
     print regression_model.pl2
     print ff.GPModel.score(regression_model, criterion='nll')
Пример #8
0
def perform_kernel_search(X, y, D, experiment_data_file_name, results_filename,
                          exp):
    '''Search for the best kernel, in parallel on fear or local machine.'''

    # Initialise random seeds - randomness may be used in e.g. data subsetting

    utils.misc.set_all_random_seeds(exp.random_seed)

    # Create location, scale and minimum period parameters to pass around for initialisations

    data_shape = {}
    data_shape['x_mean'] = [np.mean(X[:, dim]) for dim in range(X.shape[1])]
    data_shape['y_mean'] = np.mean(
        y)  #### TODO - should this be modified for non real valued data
    data_shape['x_sd'] = np.log(
        [np.std(X[:, dim]) for dim in range(X.shape[1])])
    data_shape['y_sd'] = np.log(np.std(
        y))  #### TODO - should this be modified for non real valued data
    data_shape['y_min'] = np.min(y)
    data_shape['y_max'] = np.max(y)
    data_shape['x_min'] = [np.min(X[:, dim]) for dim in range(X.shape[1])]
    data_shape['x_max'] = [np.max(X[:, dim]) for dim in range(X.shape[1])]
    data_shape['x_min_abs_diff'] = np.log(
        [utils.misc.min_abs_diff(X[:, i]) for i in range(X.shape[1])])

    # Initialise period at a multiple of the shortest / average distance between points, to prevent Nyquist problems.

    if exp.period_heuristic_type == 'none':
        data_shape['min_period'] = None
    if exp.period_heuristic_type == 'min':
        data_shape['min_period'] = np.log([
            exp.period_heuristic * utils.misc.min_abs_diff(X[:, i])
            for i in range(X.shape[1])
        ])
    elif exp.period_heuristic_type == 'average':
        data_shape['min_period'] = np.log([
            exp.period_heuristic * np.ptp(X[:, i]) / X.shape[0]
            for i in range(X.shape[1])
        ])
    elif exp.period_heuristic_type == 'both':
        data_shape['min_period'] = np.log([
            max(exp.period_heuristic * utils.misc.min_abs_diff(X[:, i]),
                exp.period_heuristic * np.ptp(X[:, i]) / X.shape[0])
            for i in range(X.shape[1])
        ])
    else:
        warnings.warn(
            'Unrecognised period heuristic type : using most conservative heuristic'
        )
        data_shape['min_period'] = np.log([
            max(exp.period_heuristic * utils.misc.min_abs_diff(X[:, i]),
                exp.period_heuristic * np.ptp(X[:, i]) / X.shape[0])
            for i in range(X.shape[1])
        ])

    data_shape['max_period'] = [
        np.log((1.0 / exp.max_period_heuristic) *
               (data_shape['x_max'][i] - data_shape['x_min'][i]))
        for i in range(X.shape[1])
    ]

    # Initialise mean, kernel and likelihood

    m = eval(exp.mean)
    k = eval(exp.kernel)
    l = eval(exp.lik)
    current_models = [ff.GPModel(mean=m, kernel=k, likelihood=l, ndata=y.size)]

    print '\n\nStarting search with this model:\n'
    print current_models[0].pretty_print()
    print ''

    # Perform the initial expansion

    current_models = grammar.expand_models(D=D,
                                           models=current_models,
                                           base_kernels=exp.base_kernels,
                                           rules=exp.search_operators)

    # Convert to additive form if desired

    if exp.additive_form:
        current_models = [model.additive_form() for model in current_models]
        current_models = ff.remove_duplicates(current_models)

    # Set up lists to record search

    all_results = []  # List of scored kernels
    results_sequence = [
    ]  # List of lists of results, indexed by level of expansion.
    nan_sequence = []  # List of list of nan scored results
    oob_sequence = []  # List of list of out of bounds results
    best_models = None

    # Other setup

    best_score = np.Inf

    # Perform search
    for depth in range(exp.max_depth):

        if exp.debug == True:
            current_models = current_models[0:4]

        # Add random restarts to kernels
        current_models = ff.add_random_restarts(current_models,
                                                exp.n_rand,
                                                exp.sd,
                                                data_shape=data_shape)

        # Print result of expansion
        if exp.debug:
            print '\nRandomly restarted kernels\n'
            for model in current_models:
                print model.pretty_print()

        # Remove any redundancy introduced into kernel expressions
        current_models = [model.simplified() for model in current_models]
        # Print result of simplification
        if exp.debug:
            print '\nSimplified kernels\n'
            for model in current_models:
                print model.pretty_print()
        current_models = ff.remove_duplicates(current_models)
        # Print result of duplicate removal
        if exp.debug:
            print '\nDuplicate removed kernels\n'
            for model in current_models:
                print model.pretty_print()

        # Add jitter to parameter values (empirically discovered to help optimiser)
        current_models = ff.add_jitter(current_models, exp.jitter_sd)
        # Print result of jitter
        if exp.debug:
            print '\nJittered kernels\n'
            for model in current_models:
                print model.pretty_print()

        # Add the previous best models - in case we just need to optimise more rather than changing structure
        if not best_models is None:
            for a_model in best_models:
                current_models = current_models + [
                    a_model.copy()
                ] + ff.add_jitter_to_models(
                    [a_model.copy()
                     for dummy in range(exp.n_rand)], exp.jitter_sd)

        # Randomise the order of the model to distribute computational load evenly
        np.random.shuffle(current_models)

        # Print current models
        if exp.debug:
            print '\nKernels to be evaluated\n'
            for model in current_models:
                print model.pretty_print()

        # Optimise parameters of and score the kernels
        new_results = jc.my_evaluate_models(
            current_models,
            X,
            y,
            verbose=exp.verbose,
            local_computation=exp.local_computation,
            zip_files=True,
            max_jobs=exp.max_jobs,
            iters=exp.iters,
            random_seed=exp.random_seed,
            subset=exp.subset,
            subset_size=exp.subset_size,
            full_iters=exp.full_iters,
            bundle_size=exp.bundle_size)

        # Remove models that were optimised to be out of bounds (this is similar to a 0-1 prior)
        new_results = [
            a_model for a_model in new_results
            if not a_model.out_of_bounds(data_shape)
        ]
        oob_results = [
            a_model for a_model in new_results
            if a_model.out_of_bounds(data_shape)
        ]
        #new_results = [a_model for a_model in new_results]
        #oob_results = [a_model for a_model in new_results]
        oob_results = sorted(
            oob_results,
            key=lambda a_model: GPModel.score(a_model, exp.score),
            reverse=True)
        oob_sequence.append(oob_results)

        # Some of the scores may have failed - remove nans to prevent sorting algorithms messing up
        (new_results,
         nan_results) = remove_nan_scored_models(new_results, exp.score)
        nan_sequence.append(nan_results)
        assert (len(new_results) > 0
                )  # FIXME - Need correct control flow if this happens

        # Sort the new results
        new_results = sorted(
            new_results,
            key=lambda a_model: GPModel.score(a_model, exp.score),
            reverse=True)

        print '\nAll new results\n'
        for result in new_results:
            print 'NLL=%0.1f' % result.nll, 'BIC=%0.1f' % result.bic, 'AIC=%0.1f' % result.aic, 'PL2=%0.3f' % result.pl2, result.pretty_print(
            )

        all_results = all_results + new_results
        all_results = sorted(
            all_results,
            key=lambda a_model: GPModel.score(a_model, exp.score),
            reverse=True)

        results_sequence.append(all_results)

        # Extract the best k kernels from the new all_results
        best_results = sorted(
            new_results,
            key=lambda a_model: GPModel.score(a_model, exp.score))[0:exp.k]

        # Print best kernels
        if exp.debug:
            print '\nBest models\n'
            for model in best_results:
                print model.pretty_print()

        # Expand the best models
        current_models = grammar.expand_models(D=D,
                                               models=best_results,
                                               base_kernels=exp.base_kernels,
                                               rules=exp.search_operators)

        # Print expansion
        if exp.debug:
            print '\nExpanded models\n'
            for model in current_models:
                print model.pretty_print()

        # Convert to additive form if desired
        if exp.additive_form:
            current_models = [
                model.additive_form() for model in current_models
            ]
            current_models = ff.remove_duplicates(current_models)

            # Print expansion
            if exp.debug:
                print '\Converted into additive\n'
                for model in current_models:
                    print model.pretty_print()

        # Reduce number of kernels when in debug mode
        if exp.debug == True:
            current_models = current_models[0:4]

        # Write all_results to a temporary file at each level.
        all_results = sorted(
            all_results,
            key=lambda a_model: GPModel.score(a_model, exp.score),
            reverse=True)
        with open(results_filename + '.unfinished', 'w') as outfile:
            outfile.write('Experiment all_results for\n datafile = %s\n\n %s \n\n' \
                          % (experiment_data_file_name, experiment_fields_to_str(exp)))
            for (i, all_results) in enumerate(results_sequence):
                outfile.write('\n%%%%%%%%%% Level %d %%%%%%%%%%\n\n' % i)
                if exp.verbose_results:
                    for result in all_results:
                        print >> outfile, result
                else:
                    # Only print top k kernels - i.e. those used to seed the next level of the search
                    i = 0
                    for result in sorted(all_results,
                                         key=lambda a_model: GPModel.score(
                                             a_model, exp.score))[0:exp.k]:
                        print >> outfile, result
                        scipy.io.savemat(
                            results_filename + 'lvl_' + str(depth) + '_' +
                            str(i) + '.mat1', result.gpml_result)
                        i += 1
        # Write nan scored kernels to a log file
        with open(results_filename + '.nans', 'w') as outfile:
            outfile.write('Experiment nan results for\n datafile = %s\n\n %s \n\n' \
                          % (experiment_data_file_name, experiment_fields_to_str(exp)))
            for (i, nan_results) in enumerate(nan_sequence):
                outfile.write('\n%%%%%%%%%% Level %d %%%%%%%%%%\n\n' % i)
                for result in nan_results:
                    print >> outfile, result
        # Write oob kernels to a log file
        with open(results_filename + '.oob', 'w') as outfile:
            outfile.write('Experiment oob results for\n datafile = %s\n\n %s \n\n' \
                          % (experiment_data_file_name, experiment_fields_to_str(exp)))
            for (i, nan_results) in enumerate(oob_sequence):
                outfile.write('\n%%%%%%%%%% Level %d %%%%%%%%%%\n\n' % i)
                for result in nan_results:
                    print >> outfile, result

        # Have we hit a stopping criterion?
        if 'no_improvement' in exp.stopping_criteria:
            new_best_score = min(
                GPModel.score(a_model, exp.score) for a_model in new_results)
            if new_best_score < best_score - exp.improvement_tolerance:
                best_score = new_best_score
            else:
                # Insufficient improvement
                print 'Insufficient improvement to score - stopping search'
                break

    # Rename temporary results file to actual results file
    os.rename(results_filename + '.unfinished', results_filename)