用户友好的 scipy 优化包装器包?

计算科学 优化 scipy 可视化
2021-12-07 02:58:25

我正在创建太多丢弃代码,以便以用户友好的方式与 scipy 优化包交互。(有关可中断优化的示例,请参见下面的代码,该示例在键盘中断后保留最后的优化值)

def monitoring_callback(x):
    global callback_dict
    callback_dict['cached_results'] = x
    callback_dict['counter']  = callback_dict['counter']  +1

try:
    fit_results= optimize.minimize(get_mean_squared_error,
                                   my_fit_params,method="CG", 
                                   callback=monitoring_callback)
    my_fit_params = fit_results

except KeyboardInterrupt:
    my_fit_params = callback_dict['cached_results']


是否有现有的包可以做这种事情?(另外,如果它实现了像这里这样的图形, http: //louistiao.me/notes/visualizing-and-animating-optimization-algorithms-with-matplotlib/

这将非常有用。)

1个回答

通常最好将这种对库函数的有状态调用封装在一个新函数中。然后monitoring_callback可以成为局部嵌套函数,并且callback_dict将是具有函数范围的常规变量,仅对嵌套函数可见。

def compute_fit_params(my_fit_params):
    callback_dict = {'counter': 0}

    def monitoring_callback(x, state):
        callback_dict['cached_results'] = x
        callback_dict['counter'] += 1
        return False

    try:
        return optimize.minimize(get_mean_squared_error,
                                 my_fit_params, method="CG",
                                 callback=monitoring_callback)
    except KeyboardInterrupt:
        return callback_dict['cached_results'] if "cached_results" in callback_dict else None

my_fit_params = compute_fit_params()

这避免了看起来可疑的全局变量(在对同一函数的多次调用之间持续存在!)。

另请注意,捕获KeyboardInterrupt是一种反模式:特别是,如果您尝试真正中断计算,则必须按 ctrl-c 两次。程序的结果也不太确定,因为它们取决于坐在键盘前的用户何时中断了程序。通常最好限制优化算法可以使用的迭代次数,或者实现简单的超时,像这样,让minimize终止更优雅:

callback_dict["start_time"] = time.process_time()
def monitoring_callback(x, state):
    callback_dict['cached_results'] = x
    callback_dict['counter'] += 1
    return time.process_time() > 10 + callback_dict["start_time"]