我正在使用lmfit来拟合一系列光谱。我的模型是几个谱线和一个常数项的总和。我想使用multiprocessing.Pool同时适应多个光谱。当在for循环中使用时,拟合非常有效,但在使用multiprocessing.Pool时似乎失败了。
我的模型相当复杂,所以我为此道歉,但希望这很清楚。我知道在函数中有一个函数很奇怪,但我发现这是让lmfit.Model()正确运行的唯一方法。
import numpy as np
from lmfit import Model
from lmfit.models import ConstantModel
def fit_spectrum(spectrum):
xdata, ydata = spectrum
def line_profile(x, amp1, amp2, a, center, wave1, wave2, sig1, sig2, N):
gauss1 = amp1*np.exp(-(x-wave1)**2/(2*sig1**2.))
gauss2 = amp2*np.exp(-(x-wave2)**2/(2*sig2**2.))
core = gauss1 + gauss2
w = center/N_eff * (1/(np.sqrt(2)*np.pi))
t = w**2.
b = ((x-center)**2+w**2)
scatter = a*t/b
return core + scatt
mod = None
spectral_lines = [ 391.44, 404.71, 435.92, 546.15, 557.89, 589.15, 589.75, 630.2 ]
for i, line in enumerate(spectral_lines):
pref = 'f%s_' % str(i).zfill(4)
line_model = Model(line_profile, prefix=pref)
line_model.set_param_hint(pref+'amp1', value=10, min=0)
line_model.set_param_hint(pref+'amp2', value=10, min=0)
line_model.set_param_hint(pref+'center', value=line, min=line-.1, max=line + .1, vary=True)
line_model.set_param_hint(pref+'delta1', value=0.06, min=0, max=0.1, vary=True)
line_model.set_param_hint(pref+'delta2', value=0.09, min=0, max=0.1, vary=True)
line_model.set_param_hint(pref+'wave1', expr=pref+'center + '+pref+'delta1')
line_model.set_param_hint(pref+'wave2', expr=pref+'center - '+pref+'delta2')
line_model.set_param_hint(pref+'a', value=10, min=0)
line_model.set_param_hint(pref+'sig1', value=0.1, min=0, max=1)
line_model.set_param_hint(pref+'sig2', value=0.1, min=0, max=1)
line_model.set_param_hint(pref+'N', value=83200, min=0)
if mod is None:
mod = line_model
else:
mod = mod + line_model
offset = ConstantModel()
offset.set_param_hint('c', value=1)
model = mod + offset
params = model.make_params()
results = model.fit(ydata, params, x=xdata)
return results
现在,我列出了许多我希望通过多处理适合的光谱。如果我在for循环中运行fit_spectrum()函数,则拟合成功。下面是一个有效的代码示例,其中spectrum是波长和数据的numpy数组的列表,spectrum = [np.array(波长),np.array(数据)],list_of_spectra是这些的列表:
FitResults = []
for spectrum in list_of_spectra:
result = fit_spectrum(spectrum)
FitResults.append(result)
当我尝试在多处理中实现它时,代码只是停留在Model.fit()。没有错误消息也没有代码崩溃。它只是移动到下一个光谱而不会缩小拟合结果。没有返回任何内容,当程序到达list_of_spectra的末尾时,代码挂起。
import multiprocessing
pool = multiprocessing.Pool(processes=4)
FitResults = pool.map(fit_spectrum, list_of_spectra)
pool.terminate()
我想也许这与需要多处理来解决问题有关,但我不知道如何解决这个问题。我还发现这个问题实现了lmfit.minimize()函数而不是Model.fit(),并对上面的代码进行了一些更改。