发生RuntimeWarning后暂停或停止numpy计算

时间:2015-06-22 15:25:22

标签: python numpy

我正在使用numpy.optimize.fsolve进行一些计算。由于不恰当的初始值,其中一些计算会导致运行时警告

  

运行时警告:经过测量,迭代没有取得良好进展   通过最近十次迭代的改进   warnings.warn(msg,RuntimeWarning)

  

运行时警告:经过测量,迭代没有取得良好进展   通过最近五次雅可比评估的改进   warnings.warn(msg,RuntimeWarning)

由于我将所有初始值和所有结果写入文本文件(只是将stdout传递给文件),我想得到一个线索,计算上面提到的RuntimeWarnings的500步骤。

numpy docs中所述,警告由Python's standard warnings module处理,但有没有办法在第一次运行时发生错误后停止或暂停计算?

1 个答案:

答案 0 :(得分:2)

如果要在发出警告时终止计算,可以使用warnings模块强制将某些类型的警告作为例外引发。你可以写下:

warnings.simplefilter('error')

这会将所有警告变为错误并立即停止该程序。缺点是只能通过捕获异常来恢复计算:它已经完成了。

如果您希望暂停该程序,您可以使用一点“黑客”来覆盖warnings模块用来显示警告的功能。尽管我们目前的目的与文档的目的不同,但是文档明确允许覆盖此函数。这是一个简单的警告处理程序,询问用户是否继续。如果用户拒绝,则错误将提升为异常:

def handle_warning(message, category, filename, lineno, file=None, line=None):
    print('A warning occurred:')
    print(message)
    print('Do you wish to continue?')

    while True:
        response = input('y/n: ').lower()
        if response not in {'y', 'n'}:
            print('Not understood.')
        else:
            break

    if response == 'n':
        raise category(message)

然后我们覆盖默认警告处理程序:

warnings.showwarning = handle_warning

现在我们尝试优化平面函数:

from scipy.optimize import fsolve
fsolve(lambda x: 1, 1)

我们几乎立即得到一条消息:

A warning occurred:
The iteration is not making good progress, as measured by the 
  improvement from the last ten iterations.
Do you wish to continue?
y/n:

如果我们回答y,将允许优化继续并返回其结果。如果我们回答n,则会引发异常并终止计算。

上下文管理器解决方案

或者,如果您不想覆盖模块级别的showwarning函数,则可以使用上下文管理器。我们可以将它放在一个包装好的和整洁的函数中:

def pause_if_warning(function, *args, **kwargs):
    with warnings.catch_warnings():
        warnings.showwarning = handle_warning
        return function(*args, **kwargs)

所以我们现在可以写:

pause_if_warning(fsolve, lambda x: 1, 1)

获得与上述相同的行为。