Exemplo n.º 1
0
    def get_errors(self, quiet=False):
        """
        Compute the errors on the parameters using the profile likelihood method.

        :return: a dictionary containing the asymmetric errors for each parameter.
        """

        # Check that the user performed a fit first

        assert (self._current_minimum is not None
                ), "You have to run the .fit method before calling errors."

        errors = self._minimizer.get_errors()

        # Set the parameters back to the best fit value
        self.restore_best_fit()

        # Print a table with the errors

        parameter_names = list(self._free_parameters.keys())
        best_fit_values = [
            x.value for x in list(self._free_parameters.values())
        ]
        negative_errors = [errors[k][0] for k in parameter_names]
        positive_errors = [errors[k][1] for k in parameter_names]
        units = [par.unit for par in list(self._free_parameters.values())]

        results_table = ResultsTable(parameter_names, best_fit_values,
                                     negative_errors, positive_errors, units)

        if not quiet:

            results_table.display()

        return results_table.frame
Exemplo n.º 2
0
    def get_errors(self, quiet=False):
        """
        Compute the errors on the parameters using the profile likelihood method.

        :return: a dictionary containing the asymmetric errors for each parameter.
        """

        # Check that the user performed a fit first

        assert self._current_minimum is not None, "You have to run the .fit method before calling errors."

        errors = self._minimizer.get_errors()

        # Set the parameters back to the best fit value
        self.restore_best_fit()

        # Print a table with the errors

        parameter_names = self._free_parameters.keys()
        best_fit_values = map(lambda x: x.value, self._free_parameters.values())
        negative_errors = [errors[k][0] for k in parameter_names]
        positive_errors = [errors[k][1] for k in parameter_names]
        units = [par.unit for par in self._free_parameters.values()]

        results_table = ResultsTable(parameter_names, best_fit_values, negative_errors, positive_errors, units)

        if not quiet:

            results_table.display()

        return results_table.frame
Exemplo 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 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(),
        )
Exemplo n.º 4
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()
Exemplo n.º 5
0
    def _get_results_table(self, error_type, cl, covariance=None):

        if error_type == "equal tail":

            errors_gatherer = RandomVariates.equal_tail_interval

        elif error_type == "hpd":

            errors_gatherer = RandomVariates.highest_posterior_density_interval

        elif error_type == "covariance":

            assert covariance is not None, "If you use error_type='covariance' you have to provide a cov. matrix"

            errors_gatherer = None

        else:

            raise ValueError(
                "error_type must be either 'equal tail' or 'hpd'. Got %s" %
                error_type)

        # Build the data frame
        parameter_paths = []
        values = []
        negative_errors = []
        positive_errors = []
        units_dict = []

        for i, this_par in enumerate(self._free_parameters.values()):

            parameter_paths.append(this_par.path)

            this_phys_q = self.get_variates(parameter_paths[-1])

            values.append(this_phys_q.value)

            units_dict.append(this_par.unit)

            if error_type != "covariance":

                low_bound, hi_bound = errors_gatherer(this_phys_q, cl)

                negative_errors.append(low_bound - values[-1])

                positive_errors.append(hi_bound - values[-1])

            else:

                std_dev = np.sqrt(covariance[i, i])

                if this_par.has_transformation():

                    best_fit_internal = this_par.transformation.forward(
                        values[-1])

                    _, neg_error = this_par.internal_to_external_delta(
                        best_fit_internal, -std_dev)
                    negative_errors.append(neg_error)

                    _, pos_error = this_par.internal_to_external_delta(
                        best_fit_internal, std_dev)
                    positive_errors.append(pos_error)

                else:

                    negative_errors.append(-std_dev)
                    positive_errors.append(std_dev)

        results_table = ResultsTable(parameter_paths, values, negative_errors,
                                     positive_errors, units_dict)

        return results_table