Curve fitting of complex data

这一生的挚爱 提交于 2020-07-07 06:00:13

问题


I want to fit complex data set with a two functions which shared the same parameters. For this I used

def funcReal(x,a,b,c,d):
    return np.real((a + 1j*b)*(np.exp(1j*k*x - kappa1*x) - np.exp(kappa2*x)) + (c + 1j*d)*(np.exp(-1j*k*x - kappa1*x) - np.exp(-kappa2*x)))

def funcImag(x,a,b,c,d):
    return np.imag((a + 1j*b)*(np.exp(1j*k*x - kappa1*x) - np.exp(kappa2*x)) + (c + 1j*d)*(np.exp(-1j*k*x - kappa1*x) - np.exp(-kappa2*x)))`

poptReal, pcovReal = curve_fit(funcReal, x, yReal)
poptImag, pcovImag = curve_fit(funcImag, x, yImag)

Here funcReal is the real part of my model, funcImag the imaginary part, yReal the real part of the data and yImag the imaginary part of the data.

However, both fits does not give me the same parameters for the real and imaginary part.

My question is there a package or a method such that I can realized multi fits for multiple data sets and multiple functions with shared parameters?


回答1:


To fit both the complex function given above, we can treat the real and imaginary components as a coordinate point, or as a vector. Since curve_fit doesn't care about the order at which data points are inserted in the vectors x (independent data) and y (dependent data), we can simply split the complex data and stack the real and imaginary components using hstack. See the example below.

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

kappa1 = np.pi
kappa2 = -0.01

def long_function(x, a, b, c, d):
    return (a + 1j*b)*(np.exp(1j*k*x - kappa1*x) - np.exp(kappa2*x)) + (c + 1j*d)*(np.exp(-1j*k*x - kappa1*x) - np.exp(-kappa2*x))

def funcBoth(x, a, b, c, d):
    N = len(x)
    x_real = x[:N//2]
    x_imag = x[N//2:]
    y_real = np.real(long_function(x_real, a, b, c, d))
    y_imag = np.imag(long_function(x_imag, a, b, c, d))
    return np.hstack([y_real, y_imag])

# Create an independent variable with 100 measurements
N = 100
x = np.linspace(0, 10, N)
# True values of the dependent variable
y = long_function(x, a=1.1, b=0.3, c=-0.2, d=0.23)
# Add uniform complex noise (real + imaginary)
noise = (np.random.rand(N) + 1j * np.random.rand(N) - 0.5 - 0.5j) * 0.1
yNoisy = y + noise

# Split the measurements into a  real and imaginary part
yReal = np.real(yNoisy)
yImag = np.imag(yNoisy)
yBoth = np.hstack([yReal, yImag])

# Find the best-fit solution
poptBoth, pcovBoth = curve_fit(funcBoth, np.hstack([x, x]), yBoth)

# Compute the best-fit solution
yFit = long_function(x, *poptBoth)
print(poptBoth)

# Plot the results
plt.figure(figsize=(9, 4))

plt.subplot(121)
plt.plot(x, np.real(yNoisy), "k.", label="Noisy y")
plt.plot(x, np.real(y), "r--", label="True y")
plt.plot(x, np.real(yFit), label="Best fit")
plt.ylabel("Real part of y")
plt.xlabel("x")
plt.legend()

plt.subplot(122)
plt.plot(x, np.imag(yNoisy), "k.")
plt.plot(x, np.imag(y), "r--")
plt.plot(x, np.imag(yFit))
plt.ylabel("Imaginary part of y")
plt.xlabel("x")

plt.tight_layout()
plt.show()

Result:

The best-fit parameters that were found in this example were a = 1.14, b = 0.375, c = -0.236, and d = 0.163, which are close enough to the true parameter values given the amplitude of the noise that I inserted here.



来源:https://stackoverflow.com/questions/50203879/curve-fitting-of-complex-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!