1

I would like to perform multivariate fit using iminuit. Everything works fine when I use two dimensions but I get an 'ValueError: too many values to unpack (expected 2)' if I use more than two dimensions.

Below is the working code for 2D fit:

from iminuit import Minuit
from iminuit.cost import LeastSquares
import numpy as np

def model1(xy, a, b, c):
    x, y = xy
    return a + (x ** b) + (y ** c)

np.random.seed(1)
data_x = np.linspace(0, 1, 10)
data_y = np.linspace(0, 1, 10)

data_terr = 0.1
data_t1 = model1([data_x,data_y], 2, 3, 10) + data_terr * np.random.randn(len(data_x))

least_squares = LeastSquares([data_x,data_y], data_t1, data_terr, model1)

m1 = Minuit(least_squares, a=1.0, b=1.0, c=1.0)
m1.migrad()

2D minuit fit results

The problem occurs for 3D fit as demonstrated below:

from iminuit import Minuit
from iminuit.cost import LeastSquares
import numpy as np

def model2(xyz, a, b, c, d):
    x, y, z = xyz
    return a + (x ** b) + (y ** c) + (z ** d)

np.random.seed(1)
data_x = np.linspace(0, 1, 10)
data_y = np.linspace(0, 1, 10)
data_z = np.linspace(0, 1, 10)

data_terr = 0.1
data_t2 = model2([data_x,data_y, data_z], 2, 3, 10, 20) + data_terr * np.random.randn(len(data_x))

least_squares = LeastSquares([data_x, data_y, data_z], data_t2, data_terr, model2)

m2 = Minuit(least_squares, a=1.0, b=1.0, c=1.0, d=1.0)
m2.migrad() 

With the error output

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[30], line 16
     13 least_squares = LeastSquares([data_x, data_y, data_z], data_t2, data_terr, model2)
     15 m2 = Minuit(least_squares, a=1.0, b=1.0, c=1.0, d=1.0)
---> 16 m2.migrad() 

File ~/anaconda3/envs/minuit_fitting/lib/python3.9/site-packages/iminuit/minuit.py:702, in Minuit.migrad(self, ncall, iterate)
    700 if self._precision is not None:
    701     migrad.precision = self._precision
--> 702 fm = migrad(ncall, self._tolerance)
    703 if fm.is_valid or fm.has_reached_call_limit:
    704     break

File ~/anaconda3/envs/minuit_fitting/lib/python3.9/site-packages/iminuit/cost.py:594, in Cost.__call__(self, *args)
    579 def __call__(self, *args: float) -> float:
    580     """
    581     Evaluate the cost function.
    582 
   (...)
    592     float
    593     """
--> 594     r = self._call(args)
    595     if self.verbose >= 1:
    596         print(args, "->", r)

File ~/anaconda3/envs/minuit_fitting/lib/python3.9/site-packages/iminuit/cost.py:1721, in LeastSquares._call(self, args)
   1719 def _call(self, args: Sequence[float]) -> float:
   1720     x = self._masked.T[0] if self._ndim == 1 else self._masked.T[: self._ndim]
-> 1721     y, yerror = self._masked.T[self._ndim :]
   1722     ym = self._model(x, *args)
   1723     ym = _normalize_model_output(ym)

ValueError: too many values to unpack (expected 2)

Could you please point me out what I am doing wrong ? Any help would be appreciated.

1 Answer 1

1

This isn't a mistake on your end. It looks like there is a bug in iminuit where it takes the number of dimensions in the x array that is passed in instead of the size of the first dimension. I've submitted a bug report on the github: https://github.com/scikit-hep/iminuit/issues/974

In the meantime, the best workaround seems to be to set least_squares._ndim directly:

least_squares = LeastSquares([data_x, data_y, data_z], data_t2, data_terr, model2)
least_squares._ndim = 3

m2 = Minuit(least_squares, a=1.0, b=1.0, c=1.0, d=1.0)
m2.migrad() 
4
  • It looks like this answer would be more suitable as a comment to the original question.
    – qingy2019
    Commented Mar 5 at 0:11
  • Why? The content of the answer is the answer to the question, i.e. "You are doing nothing wrong, it is a bug in the underlying library". I found this question because I was having the same problem, and this is the information I would have wanted to find here. If it is about the presentation of the answer, I have now edited the answer to be clearer about how it is an answer to the question and to add a workaround I just found.
    – FinnStokes
    Commented Mar 6 at 2:02
  • Oh my bad...., I agree.
    – qingy2019
    Commented Mar 6 at 7:12
  • Hello @FinnStokes. Thank you very much for answering this long standing question of mine, and also providing very clear workaround for the problem. Indeed, you suggested solution least_squares._ndim = 3 works like a charm, at least for iminuit 2.21.3. Let's hope that your bug report will be included in the forthcoming version. Cheers...
    – PitisCat
    Commented Mar 21 at 19:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.