使用Scipy Optimize查找最小值时出现NoneType错误

问题描述

我正在尝试使用scipy.optimizer方法查找函数的全局最小值,并不断遇到nonetype问题。我尝试了多种算法,包括differential_evolution,shgo和brute,但一直遇到错误

这是设置:

    # @user = User.new(user_params)
    @patient = @user.build_patient
    @patient.save

这是我要优化的功能

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],(lb[1],(lb[2],(lb[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])

失败不是立即发生,而是在运行了几次优化器功能之后。例如,对于differential_evolution,它总是在第75次试用后发生。

这是堆栈跟踪:

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,range)

    mass = config_weight.config_weight(battery,motors,rprop,mtow,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

非常感谢您的帮助!

解决方法

问题出在从您的boundsobjective_function中检索到的值之一,而这些值又作为NoneType传递到{{1 }}

来源:https://github.com/scipy/scipy/blob/master/scipy/optimize/_differentialevolution.py

energy_orig

您应确保differential_evolution()或其他函数参数中的每个键值都不为空。很难说出可能是问题所在。但是,您可以将其包裹在try / catch周围,以使它不会在第75次尝试时停止。

if feasible_orig and feasible_trial:
    return energy_trial <= energy_orig

我已经设置了pdb,它将允许调试每个参数的值,如果需要快速继续,可以随时通过传递将其替换掉