Я использую scipy.optimize ( дифференциальная эволюция ) для оптимизации.В целом работает отлично.Я начал использовать функцию работника (которая позволяет указывать оптимизации для выделения отдельных лиц из популяции в другие процессы, очень легко эффективно распараллеливая процесс оптимизации).
Я вижу, что если я укажу работников= -1, все мои ядра работают должным образом.
Симуляция управляется в структуре:
""" Sandbox stuff """
from scipy.optimize import *
class Simulation:
def __init__(self):
self.data = None
def optim_manager(self):
optimized_results = differential_evolution(self.optim_loop,
bounds=self.bounds, callback=self.optim_callback, workers=-1)
def optim_loop(self, parameters):
self.data = run_model(parameters)
optim_value = self.calc_optim_value(self.data)
# at this point self.data exist & is not None
return optim_value
def optim_callback(self,*args):
# *args contains the parameters value for that optimal run
optim_value = self.calc_optim_value(self.data) # error
write_optimisation_run_to_dictionnary(args, optim_value)
Однако, когда я пытаюсь вычислить optim_value вобратный вызов я получаю:
Traceback (most recent call last):
File "lancer_modele.py", line 512, in <module>
mp.launch()
File "lancer_modele.py", line 234, in launch
self.do_optim_ghosts()
File "lancer_modele.py", line 296, in do_optim_ghosts
opt.opti_manager_ghosts(**merged_kwargs)
File "/home/atari/PycharmProjects/RT/managers/optimisation.py", line 41, in opti_manager_ghosts
simul_params = simul.fctopti_ghosts(nbrite=1, free_params_ordereddict=free_init_params[-1], **kwargs) # it returns other stuff we don't need, a,b,c
File "/home/atari/PycharmProjects/RT/managers/Simulation.py", line 225, in fctopti_ghosts
popsize=5, callback=self.optim_callback, workers=2)
File "/home/atari/.local/lib/python3.6/site-packages/scipy/optimize/_differentialevolution.py", line 272, in differential_evolution
ret = solver.solve()
File "/home/atari/.local/lib/python3.6/site-packages/scipy/optimize/_differentialevolution.py", line 701, in solve
convergence=self.tol / convergence) is True):
File "/home/atari/PycharmProjects/RT/managers/Simulation.py", line 433, in optim_callback
optim_value = self.calc_ghost_optimized_value()
File "/home/atari/PycharmProjects/RT/managers/Simulation.py", line 509, in calc_ghost_optimized_value
optim_value = np.sum(cubedata[:,:,self.gstart_tick:self.gstop_tick])
TypeError: 'NoneType' object is not subscriptable
, поскольку self.data имеет значение None в контексте optim_callback.Это работает нормально, однако, если я использую только 1 ядро.Я предполагаю, что при использовании нескольких ядер класс сериализуется и передается, а атрибуты обновляются в каждом запущенном процессе.Затем он возвращается к основному процессу, где Simulation все еще остается прежним, потому что был вызван дополнительный ответчик (поэтому он все еще имеет self.data = None).Это означает, что я не могу легко вычислить значение optim, и кажется, что хотя обратный вызов scipy и дает мне значения параметров в порядке, он не передает значение, которое я сказал, что они стоили в моей модели.
Anyидея?Я думаю, что я мог бы отдельно заново создать полную модель в optim_callback, обновить ее с предоставленными параметрами, запустить ее снова, чтобы получить значение оптимизации.Тем не менее, модель работает довольно долго, и я бы не стал замедлять оптимизацию каждый раз, когда получаю (промежуточное) оптимальное значение.