Нетипичная ошибка при нахождении минимумов с помощью Scipy Optimize

#python #scipy #scipy-optimize

#python #scipy #scipy-оптимизировать

Вопрос:

Я пытаюсь найти глобальные минимумы функции, используя методы scipy.optimizer, и продолжаю сталкиваться с нетипичными проблемами. Я пробовал несколько алгоритмов, включая differential_evolution, shgo и brute, но продолжаю сталкиваться с ошибками.

Вот настройка:

 def sizing_trade_study(ranges, payload):
    with open("config.yml", "r") as yml:
        cfg = yaml.load(yml)
    first_int = True
    km = []
    for range in ranges:

        km.append( range * 1000)
    print(km)
    params = (km, payload)

    if first_int:
        x0 = [float(cfg['design_variables']['initial_guess']['prop_radius']),
              float(cfg['design_variables']['initial_guess']['speed']),
              float(cfg['design_variables']['initial_guess']['battery_mass']),
              float(cfg['design_variables']['initial_guess']['motor_mass']),
              float(cfg['design_variables']['initial_guess']['mtow'])]

    lb = [float(cfg['design_variables']['lower_bound']['prop_radius']),
          float(cfg['design_variables']['lower_bound']['speed']),
          float(cfg['design_variables']['lower_bound']['battery_mass']),
          float(cfg['design_variables']['lower_bound']['motor_mass']),
          float(cfg['design_variables']['lower_bound']['mtow'])] # Min cruise at 1.3 * VStall

    ub = [float(cfg['design_variables']['upper_bound']['prop_radius']),
          float(cfg['design_variables']['upper_bound']['speed']),
          float(cfg['design_variables']['upper_bound']['battery_mass']),
          float(cfg['design_variables']['upper_bound']['motor_mass']),
          float(cfg['design_variables']['upper_bound']['mtow'])]

    # bounds = (slice(lb[0], ub[0]), slice(lb[1], ub[1]), slice(lb[2], ub[2]), slice(lb[3], ub[3]), slice(lb[4], ub[4]))
    # bounds = [(lb[0], ub[0]), (lb[1], ub[1]), (lb[2], ub[2]), (lb[3], ub[3]), (lb[4], ub[4])]

    bounds = optimize.Bounds(lb,ub)
    result = optimize.differential_evolution(objective_function, bounds, args=(params,))

    print(result)

def objective_function(x, *params):
    global trials
    trials = trials 1
    print(trials)
    performance.compute_performance(x, params[0][0], params[0][1])
  

Вот функция, которую я пытаюсь оптимизировать:

 import yaml
import simple_mission
import reserve_mission
import config_weight

def compute_performance(x, range, payload):
    rprop = x[0]
    speed = x[1]
    battery = x[2]
    motors = x[3]
    mtow = x[4]

    w = mtow * 9.8
    with open("config.yml", "r") as yml:
        cfg = yaml.load(yml)
    bat_energy_density = int(cfg['performance']['bat_energy_density'])
    motor_power_density = int(cfg['performance']['motor_power_density'])
    discharge_depth = float(cfg['performance']['discharge_depth'])

    e_nominal, flight_time, hover_output, cruise_output = simple_mission.run_simple_mission(rprop, speed, w, range)

    reserve_e = reserve_mission.reserve_mission(rprop,speed, w, range)

    mass = config_weight.config_weight(battery,motors, rprop, w, mtow, hover_output, cruise_output, payload)

    batt = reserve_e - battery * bat_energy_density * discharge_depth / 1000
    motor = hover_output.pow_hover / 1000 - motors * motor_power_density
    weight = mass - w

    return batt  motor  weight
  

Сбой происходит не сразу, а после пары запусков функции оптимизатора. Например, с differential_evolution это всегда происходит после 75-й попытки.

Вот трассировка стека:

 69
70
71
72
73
74
75
76
Traceback (most recent call last):
  File "sizing_trade_study.py", line 62, in <module>
    sizing_trade_study(args.ranges, args.payload)
  File "sizing_trade_study.py", line 42, in sizing_trade_study
    result = optimize.differential_evolution(objective_function, bounds, args=(params,))
  File "/usr/local/anaconda3/envs/simple_mission/lib/python3.7/site-packages/scipy/optimize/_differentialevolution.py", line 308, in differential_evolution
    ret = solver.solve()
  File "/usr/local/anaconda3/envs/simple_mission/lib/python3.7/site-packages/scipy/optimize/_differentialevolution.py", line 759, in solve
    next(self)
  File "/usr/local/anaconda3/envs/simple_mission/lib/python3.7/site-packages/scipy/optimize/_differentialevolution.py", line 1082, in __next__
    self.constraint_violation[candidate]):
  File "/usr/local/anaconda3/envs/simple_mission/lib/python3.7/site-packages/scipy/optimize/_differentialevolution.py", line 1008, in _accept_trial
    return energy_trial <= energy_orig
TypeError: '>=' not supported between instances of 'float' and 'NoneType'
  

Любая помощь приветствуется!

Комментарии:

1. Я полагаю, что исправил это. Мне не хватало возврата в objective_function

Ответ №1:

Проблема связана с одним из полученных значений из вашего bounds or objective_function , которое, в свою очередь, передается как NoneType to energy_orig внутри differential_evolution()

Источник:https://github.com/scipy/scipy/blob/master/scipy/optimize/_differentialevolution.py

 if feasible_orig and feasible_trial:
    return energy_trial <= energy_orig
  

Вы должны убедиться, что каждое ключевое значение не является пустым из ваших config.yml или других параметров функции. Трудно сказать, в чем может быть проблема. Однако вы могли бы обернуть это вокруг try / catch, чтобы пока это не останавливалось на 75-й попытке.

 try:
    result = optimize.differential_evolution(
      objective_function,
      bounds,
      args=(params,),
    )
except TypeError:
  import pdb; pdb.set_trace()
  

Я установил pdb, который позволит отлаживать значения каждого параметра, не стесняйтесь менять его с помощью pass, если вам нужно быстро продолжить