Esempio n. 1
0
    def fit(self, quiet=False, compute_covariance=True, n_samples=5000):
        """
        Perform a fit of the current likelihood model on the datasets

        :param quiet: If True, print the results (default), otherwise do not print anything
        :param compute_covariance:If True (default), compute and display the errors and the correlation matrix.
        :return: a dictionary with the results on the parameters, and the values of the likelihood at the minimum
                 for each dataset and the total one.
        """

        # Update the list of free parameters, to be safe against changes the user might do between
        # the creation of this class and the calling of this method

        self._update_free_parameters()

        # Empty the call recorder
        self._record_calls = {}
        self._ncalls = 0

        # Check if we have free parameters, otherwise simply return the value of the log like
        if len(self._free_parameters) == 0:

            custom_warnings.warn(
                "There is no free parameter in the current model",
                RuntimeWarning)

            # Create the minimizer anyway because it will be needed by the following code

            self._minimizer = self._get_minimizer(self.minus_log_like_profile,
                                                  self._free_parameters)

            # Store the "minimum", which is just the current value
            self._current_minimum = float(self.minus_log_like_profile())

        else:

            # Instance the minimizer

            # If we have a global minimizer, use that first (with no covariance)
            if isinstance(self._minimizer_type,
                          minimization.GlobalMinimization):

                # Do global minimization first

                global_minimizer = self._get_minimizer(
                    self.minus_log_like_profile, self._free_parameters)

                xs, global_log_likelihood_minimum = global_minimizer.minimize(
                    compute_covar=False)

                # Gather global results
                paths = []
                values = []
                errors = []
                units = []

                for par in list(self._free_parameters.values()):

                    paths.append(par.path)
                    values.append(par.value)
                    errors.append(0)
                    units.append(par.unit)

                global_results = ResultsTable(paths, values, errors, errors,
                                              units)

                if not quiet:

                    print(
                        "\n\nResults after global minimizer (before secondary optimization):"
                    )

                    global_results.display()

                    print("\nTotal log-likelihood minimum: %.3f\n" %
                          global_log_likelihood_minimum)

                # Now set up secondary minimizer
                self._minimizer = self._minimizer_type.get_second_minimization_instance(
                    self.minus_log_like_profile, self._free_parameters)

            else:

                # Only local minimization to be performed

                self._minimizer = self._get_minimizer(
                    self.minus_log_like_profile, self._free_parameters)

            # Perform the fit, but first flush stdout (so if we have verbose=True the messages there will follow
            # what is already in the buffer)
            sys.stdout.flush()

            xs, log_likelihood_minimum = self._minimizer.minimize(
                compute_covar=compute_covariance)

            if log_likelihood_minimum == minimization.FIT_FAILED:

                raise FitFailed("The fit failed to converge.")

            # Store the current minimum for the -log likelihood

            self._current_minimum = float(log_likelihood_minimum)

            # First restore best fit (to make sure we compute the likelihood at the right point in the following)
            self._minimizer.restore_best_fit()

        # Now collect the values for the likelihood for the various datasets

        # Fill the dictionary with the values of the -log likelihood (dataset by dataset)

        minus_log_likelihood_values = collections.OrderedDict()

        # Keep track of the total for a double check

        total = 0

        # sum up the total number of data points

        total_number_of_data_points = 0

        for dataset in list(self._data_list.values()):

            ml = dataset.inner_fit() * (-1)

            minus_log_likelihood_values[dataset.name] = ml

            total += ml

            total_number_of_data_points += dataset.get_number_of_data_points()

        assert (
            total == self._current_minimum
        ), "Current minimum stored after fit and current do not correspond!"

        # compute additional statistics measures

        statistical_measures = collections.OrderedDict()

        # for MLE we can only compute the AIC and BIC as they
        # are point estimates

        statistical_measures["AIC"] = aic(-total, len(self._free_parameters),
                                          total_number_of_data_points)
        statistical_measures["BIC"] = bic(-total, len(self._free_parameters),
                                          total_number_of_data_points)

        # Now instance an analysis results class
        self._analysis_results = MLEResults(
            self.likelihood_model,
            self._minimizer.covariance_matrix,
            minus_log_likelihood_values,
            statistical_measures=statistical_measures,
            n_samples=n_samples,
        )

        # Show the results

        if not quiet:

            self._analysis_results.display()

        return (
            self._analysis_results.get_data_frame(),
            self._analysis_results.get_statistic_frame(),
        )
Esempio n. 2
0
    def _build_results(self):
        """
        build the results after a fit is performed

        :returns:
        :rtype:

        """

        # set the median fit

        self.restore_median_fit()

        # Find maximum of the log posterior
        idx = self._log_probability_values.argmax()

        # Get parameter values at the maximum
        approximate_MAP_point = self._raw_samples[idx, :]

        # Sets the values of the parameters to their MAP values
        for i, parameter in enumerate(self._free_parameters):

            self._free_parameters[parameter].value = approximate_MAP_point[i]

        # Get the value of the posterior for each dataset at the MAP
        log_posteriors = collections.OrderedDict()

        log_prior = self._log_prior(approximate_MAP_point)

        # keep track of the total number of data points
        # and the total posterior

        total_n_data_points = 0

        total_log_posterior = 0

        for dataset in list(self._data_list.values()):

            log_posterior = dataset.get_log_like() + log_prior

            log_posteriors[dataset.name] = log_posterior

            total_n_data_points += dataset.get_number_of_data_points()

            total_log_posterior += log_posterior

        # compute the statistical measures

        statistical_measures = collections.OrderedDict()

        # compute the point estimates

        statistical_measures["AIC"] = aic(total_log_posterior,
                                          len(self._free_parameters),
                                          total_n_data_points)
        statistical_measures["BIC"] = bic(total_log_posterior,
                                          len(self._free_parameters),
                                          total_n_data_points)

        this_dic, pdic = dic(self)

        # compute the posterior estimates

        statistical_measures["DIC"] = this_dic
        statistical_measures["PDIC"] = pdic

        if self._marginal_likelihood is not None:

            statistical_measures["log(Z)"] = self._marginal_likelihood

        # TODO: add WAIC

        # Instance the result

        self._results = BayesianResults(
            self._likelihood_model,
            self._raw_samples,
            log_posteriors,
            statistical_measures=statistical_measures,
            log_probabilty=self._log_like_values)
Esempio n. 3
0
    def fit(self, quiet=False, compute_covariance=True, n_samples=5000):
        """
        Perform a fit of the current likelihood model on the datasets

        :param quiet: If True, print the results (default), otherwise do not print anything
        :param compute_covariance:If True (default), compute and display the errors and the correlation matrix.
        :return: a dictionary with the results on the parameters, and the values of the likelihood at the minimum
                 for each dataset and the total one.
        """

        # Update the list of free parameters, to be safe against changes the user might do between
        # the creation of this class and the calling of this method

        self._update_free_parameters()

        # Empty the call recorder
        self._record_calls = {}
        self._ncalls = 0

        # Check if we have free parameters, otherwise simply return the value of the log like
        if len(self._free_parameters) == 0:

            custom_warnings.warn("There is no free parameter in the current model", RuntimeWarning)

            # Create the minimizer anyway because it will be needed by the following code

            self._minimizer = self._get_minimizer(self.minus_log_like_profile,
                                                  self._free_parameters)

            # Store the "minimum", which is just the current value
            self._current_minimum = float(self.minus_log_like_profile())

        else:

            # Instance the minimizer

            # If we have a global minimizer, use that first (with no covariance)
            if isinstance(self._minimizer_type, minimization.GlobalMinimization):

                # Do global minimization first

                global_minimizer = self._get_minimizer(self.minus_log_like_profile, self._free_parameters)

                xs, global_log_likelihood_minimum = global_minimizer.minimize(compute_covar=False)

                # Gather global results
                paths = []
                values = []
                errors = []
                units = []

                for par in self._free_parameters.values():

                    paths.append(par.path)
                    values.append(par.value)
                    errors.append(0)
                    units.append(par.unit)

                global_results = ResultsTable(paths, values, errors, errors, units)

                if not quiet:

                    print("\n\nResults after global minimizer (before secondary optimization):")

                    global_results.display()

                    print("\nTotal log-likelihood minimum: %.3f\n" % global_log_likelihood_minimum)

                # Now set up secondary minimizer
                self._minimizer = self._minimizer_type.get_second_minimization_instance(self.minus_log_like_profile,
                                                                                        self._free_parameters)

            else:

                # Only local minimization to be performed

                self._minimizer = self._get_minimizer(self.minus_log_like_profile,
                                                      self._free_parameters)

            # Perform the fit, but first flush stdout (so if we have verbose=True the messages there will follow
            # what is already in the buffer)
            sys.stdout.flush()

            xs, log_likelihood_minimum = self._minimizer.minimize(compute_covar=compute_covariance)

            if log_likelihood_minimum == minimization.FIT_FAILED:

                raise FitFailed("The fit failed to converge.")

            # Store the current minimum for the -log likelihood

            self._current_minimum = float(log_likelihood_minimum)

            # First restore best fit (to make sure we compute the likelihood at the right point in the following)
            self._minimizer.restore_best_fit()

        # Now collect the values for the likelihood for the various datasets

        # Fill the dictionary with the values of the -log likelihood (dataset by dataset)

        minus_log_likelihood_values = collections.OrderedDict()

        # Keep track of the total for a double check

        total = 0

        # sum up the total number of data points

        total_number_of_data_points = 0

        for dataset in self._data_list.values():

            ml = dataset.inner_fit() * (-1)

            minus_log_likelihood_values[dataset.name] = ml

            total += ml

            total_number_of_data_points += dataset.get_number_of_data_points()

        assert total == self._current_minimum, "Current minimum stored after fit and current do not correspond!"

        # compute additional statistics measures

        statistical_measures = collections.OrderedDict()

        # for MLE we can only compute the AIC and BIC as they
        # are point estimates

        statistical_measures['AIC'] = aic(-total,len(self._free_parameters),total_number_of_data_points)
        statistical_measures['BIC'] = bic(-total,len(self._free_parameters),total_number_of_data_points)


        # Now instance an analysis results class
        self._analysis_results = MLEResults(self.likelihood_model, self._minimizer.covariance_matrix,
                                            minus_log_likelihood_values,statistical_measures=statistical_measures, n_samples=n_samples)

        # Show the results

        if not quiet:

            self._analysis_results.display()

        return self._analysis_results.get_data_frame(), self._analysis_results.get_statistic_frame()
Esempio n. 4
0
    def _build_results(self):

        # Find maximum of the log posterior
        idx = self._log_probability_values.argmax()

        # Get parameter values at the maximum
        approximate_MAP_point = self._raw_samples[idx, :]

        # Sets the values of the parameters to their MAP values
        for i, parameter in enumerate(self._free_parameters):

            self._free_parameters[parameter].value = approximate_MAP_point[i]

        # Get the value of the posterior for each dataset at the MAP
        log_posteriors = collections.OrderedDict()

        log_prior = self._log_prior(approximate_MAP_point)

        # keep track of the total number of data points
        # and the total posterior

        total_n_data_points = 0

        total_log_posterior = 0

        for dataset in self._data_list.values():


            log_posterior = dataset.get_log_like() + log_prior

            log_posteriors[dataset.name] = log_posterior

            total_n_data_points += dataset.get_number_of_data_points()

            total_log_posterior += log_posterior


        # compute the statistical measures

        statistical_measures = collections.OrderedDict()

        # compute the point estimates

        statistical_measures['AIC'] = aic(total_log_posterior,len(self._free_parameters),total_n_data_points)
        statistical_measures['BIC'] = bic(total_log_posterior,len(self._free_parameters),total_n_data_points)

        this_dic, pdic = dic(self)

        # compute the posterior estimates

        statistical_measures['DIC'] = this_dic
        statistical_measures['PDIC'] = pdic

        if self._marginal_likelihood is not None:

            statistical_measures['log(Z)'] = self._marginal_likelihood


        #TODO: add WAIC


        # Instance the result

        self._results = BayesianResults(self._likelihood_model, self._raw_samples, log_posteriors,statistical_measures=statistical_measures)