Scipy回调只调用一次

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scipy回调只调用一次相关的知识,希望对你有一定的参考价值。

我正在使用tf scipy interface,使用scipy minimize而不是我在tensorflow中定义的自定义函数。我需要调试它,我想使用回调函数来打印一些信息。但是,尽管迭代/函数评估/梯度评估的数量多于一个,但回调函数仅被调用一次。为什么?我使用scipy(没有tensorflow)得到同样的问题。

这是一个带有Rosenbrock函数的MWE(它应该说最小化器执行23次迭代,53次函数评估,23次梯度评估,但CALLBACK!只打印两次,一次用于step_callback,一次用于loss_callback)。

import tensorflow as tf
import numpy as np

class Solver:
    def __init__(self, session, y, x):
        self.session = session
        self.y = y
        self.x = x
        self.optimizer = tf.contrib.opt.ScipyOptimizerInterface(self.y,
                                              options={'maxiter': 100, 'disp': True},
                                              method='SLSQP',
                                              var_list=[self.x],
                                              var_to_bounds={self.x: (1e-8, np.infty)})

    def optimize(self):
      self.optimizer.minimize(self.session, step_callback=self.callback(), loss_callback=self.callback())

    def callback(self):
        print('CALLBACK!')


def main():
    seed = 0
    np.random.seed(seed)
    tf.set_random_seed(seed)
    session = tf.Session()

    x_size = 10
    x = tf.Variable(np.random.rand(x_size), dtype=tf.float32)
    y = 0.
    for i in range(x_size-1):
        y += 100. * (x[i+1] - x[i]*x[i])**2 + (x[i] - 1)**2

    solver = Solver(session, y, x)

    session.run(tf.global_variables_initializer())

    solver.optimize()


if __name__ == '__main__':
    main()
答案

(添加到我上面的评论)

根据docs

step_callback:在每个优化步骤中调用的函数; arguments是所有优化变量的当前值,这些变量被展平为单个向量。

loss_callback:每次计算丢失和梯度时调用的函数,作为位置参数提供计算的提取。

你必须传递一个功能。

一个简单的例子,显示你的案例中没有传递函数的问题;但是对功能的评估如下。

请记住,我只会显示一些纯粹的scipy-example而不是-argument self,我正在传递一个向量(这是回调中的常见情况)。它看起来不同,但它转移到您的情况!

码:

import numpy as np
from scipy.optimize import minimize, rosen

def callback(xs):
    print('callback')

x0 = np.zeros(5)

print('Wrong passing')
res = minimize(rosen, np.zeros(5), callback=callback(x0))  # need some arg x0 to make it run
                                                           # in your case this is "self"
print('Correct passing')
res = minimize(rosen, np.zeros(5), callback=callback)

日期:

Wrong passing
callback
alpha1:  1.0
Correct passing
callback
callback
callback
callback
...
...
alpha1:  1.0

在您的情况下,您还可以再进行一次调试实验,以显示问题。介绍两种不同的回调,一种用于step_callback,另一种用于loss_callback。您将看到每个被调用一次(在实际开始优化之前的单次评估!)。

以上是关于Scipy回调只调用一次的主要内容,如果未能解决你的问题,请参考以下文章

javascript中setTimeout每隔1秒调用一次ajax,但回调函数只调用一次。求解。。

获取“来自本机模块的非法回调调用。此回调类型仅允许从本机代码进行一次调用”

从片段替换片段时,onRequestPermissionsResult 回调不起作用

调用第三方接口 拦截重复回调

使用 forEach 时避免回调多次调用

对“xxx”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们。 错误解决一例。(代码片段