Notes on fits

Below are some notes, details and advices about the fits. Most of the fits methods relies on scipy. While several algorithms are implemented, see here, pyLIMA relies mainly of three main fitting methods.

Differential Evolution (DE)

DE is a population-based algorithm for global optimization of complex functions by Storn & Price. There are plenty of litterature discussing the remarkable performance about DE and its derivatives.

DE is the workhorse of pyLIMA fits and it has proven its reliability and effectiveness on many fits.

Gradient-Like methods

There are two methods to performs gradient-like fits in pyLIMA, the Trust-Reflective Function (TRF) and Levenberg-Marquardt (LM). They are almost identical, but the former accounts of parameters boundaries (which is desirable when the event is not very well constrained). They are very efficient to find the best models as soon as a minima is found. Jacobian are implemented for simplest models (i.e. PSPL and FSPL without second-order effects).

MCMC

MCMC is implemeented via the awesome emcee package. The number of walkers and links can be adjusted. Uniform priors at the parameters boundaries are set by default.

Fancy parameters

Modeling performance can be significantly improved by exploring the parameter space in log-space. This is especially recommended for the modeling of binary lenses. While users can pass their own fancy parameters, pyLIMA includes an option to use \(log_{10}(t_E)\), \(log_{10}(\rho)\), \(log_{10}(s)\) and \(log_{10}(q)\):

from pyLIMA.models import USBL_model, pyLIMA_fancy_parameters
from pyLIMA.fits import DE_fit

fancy_parameters = pyLIMA_fancy_parameters.standard_fancy_parameters

usbl = USBL_model.USBLmodel(current_event, fancy_parameters=fancy_parameters)

de = DE_fit.DEfit(usbl)
de.fit()

The boundaries are automatically adjusted to the new parameters. However, the parameters guess (for gradient-like and MCMC methods) needs to be given in the new scale:

from pyLIMA.models import USBL_model, pyLIMA_fancy_parameters
from pyLIMA.fits import TRF_fit

fancy_parameters = pyLIMA_fancy_parameters.standard_fancy_parameters.copy()

usbl = USBL_model.USBLmodel(current_event, fancy_parameters=fancy_parameters)

trf = TRF_fit.TRFfit(usbl)
# t0, u0, log10(tE),log10(rho),log10(s),log10(q),alpha
trf.model_parameters_guess = [ 2.45986449e+06,  -1.81080674e-01,  2.63277601e+00, -1.45312165e+00, -1.85934608e-01,-3.12504456e+00,  5.42587262e+00]
trf.fit()

Parallelization

DE and MCMC methods can significantly be speed-up by implementing a pool of workers via multiprocessing:

import multiprocessing as mul
pool = mul.Pool(processes = 4)

my_fit.fit(computational_pool = pool)

Priors

pyLIMA now includes the possibility to add user-defined priors. While they are no priors by default, uniform and gaussian priors are available. Users can also define their own functions as long as they return a pdf for a given parameters as well as a rvs method, for example with a Cauchy distribution:

class CauchyDistribution(object):

    def __init__(self, mean, gamma):

        self.mean = mean
        self.gamma = gamma

    def pdf(self, x):

        denominator = np.pi*self.ggam*(1+(x-self.mean)**2/self.gamma**2)
        probability = 1 / denominator

        return probability

    def rvs(self, size):

        sample = np.random.standard_cauchy(size)

        samples = self.mean+self.gamma*sample

        return samples

from pyLIMA.models import PSPLmodel
from pyLIMA.fits import DEfit

model = PSPLmodel(event)
thefit = DEfit(model)

t0prior =  CauchyDistribution(2459856,0.5)
u0prior =  CauchyDistribution(0.1,0.5)
tEprior =  CauchyDistribution(22,0.5)

thefit.priors = [t0prior,u0prior,tEprior]

Loss functions

By default, pyLIMA implements three loss functions:

  • \(\chi^2\) : the sum of the normed residuals

  • \(\log \cal L\) : the ln-likelihood, that includes priors

  • soft_l1 : the soft_l1 function is close to the Huber loss function and it is very robust against outliers

from pyLIMA.fits import DEfit
thefit = DEfit(model,loss_function='soft_l1')

Fitting algorithms have default loss functions described in pyLIMA Modules. The sign of the loss function will depends if the fitting algorithms maximize or minimize the objective function.

Advices on fitting binary lightcurves

For fitting binary models, DE has proven to be reliable to locate global minima. However, we recommand to explore \(s\le1\) and \(s\ge1\) separetely, to explore carefully the close/wide degeneracy (see). One the minimas are found, each of them should be explored using MCMC.

We note that some wide binary systems can be hard, if not impossible, to model with the default pyLIMA settings. OGLE-2015-BLG-0060 is a good example. In this case, it is recomanded to change the origin of the system, for example to the primary body:

from pyLIMA.models import USBLmodel

usbl = USBLmodel(current_event,origin=['primary',[0,0]])