0
import pandas as pd
import math
import numpy as np
from scipy.optimize
import curve_fit
L_data = np.array([0.856, 0.451])
t_data = np.array([0.398, 0.507])
y_data = np.array([0.63, 0.5])
def model(x, c1, c2):
  x = ([L, t])
return ((480 / c2) * (math.sqrt(((1 + (c1 ** 2)) / 3)) * np.cos((L * math.pi) / 6)) + c1 * (t + (1 / 3) * np.sin((L * math.pi) / 6))) ** (-1 / 0.19741)
xd = [L_data, t_data]
p0 = 0.003, 231
popt, pcov = curve_fit(model, xd, y_data, p0)

I am trying to curve fit a multivariable model with 2 parameters without any luck. The documentation I found focuses mostly on a single variable. I tried to follow the other posts about linking and unpacking but I keep getting this error message "TypeError: can't multiply sequence by non-int of type 'float'" The error is linked to the last line of code. Other than this error is there anything I need to change in my code to get a better solution.

y is the output of the model.

I am new to python so any help is appreciated. Thanks

I tried changing the input tonp.array but that did not solve the issue

Zack
  • 1
  • 1

2 Answers2

0

Somewhere in your code, you are trying to multiply an array by a float just like in this example;

>>> a = [2,3]
>>> a * 2
[2, 3, 2, 3]
>>> a * 2.3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't multiply sequence by non-int of type 'float'

For multivariate curve fitting, check this answer.

doneforaiur
  • 1,308
  • 7
  • 14
  • 21
  • I see what you mean, so do I need to edit the sequence (list) in this case – Zack Jun 02 '23 at 21:03
  • Sadly I can't reproduce the error since your code contains variables `yd`, `L` and `t` which are not defined in the snippet. Can you update your code so that it could be run in a single cell (I'm guessing you are using Jupyter)? – doneforaiur Jun 02 '23 at 21:07
  • Yes jupyter just fixed yd to y_data. L & t are in the formula and related to L_data & t_data – Zack Jun 02 '23 at 21:13
0

This is not a curve-fitting problem; you only have two data points. It's really a root-finding problem over two dimensions.

The following fixes most of your issues, including the unpacking issue; but to get a better fit is outside of the scope of this question.

import numpy as np
from scipy.optimize import root


def model(x: np.ndarray, c1: float, c2: float) -> np.ndarray:
    L, t = x
    y = (
        480/c2
        * np.sqrt((1 + c1**2)/3)
        * np.cos(L*np.pi/6)
        + c1*(
            t + np.sin(L*np.pi/6)/3
        )
    )**(-1 / 0.19741)
    return y


def err(c: np.ndarray) -> np.ndarray:
    y = model(xd, *c)
    err = y - y_data
    return err


L_data = np.array((0.856, 0.451))
t_data = np.array((0.398, 0.507))
y_data = np.array((0.63, 0.5))
xd = [L_data, t_data]
p0 = 0.003, 231
result = root(
    fun=err, x0=p0, method='lm',
    options={'maxiter': 10_000}
)
print(result.message)
if result.success:
    print('Guess:', model(xd, *p0))
    print('Fit:', model(xd, *result.x))
Reinderien
  • 11,755
  • 5
  • 49
  • 77