我正在使用numpy.optimize.fsolve. 由于不正确的初始值,其中一些计算导致 RuntimeWarning 告诉
RuntimeWarning:根据最近十次迭代的改进来衡量,迭代没有取得良好进展。
警告。警告(味精,运行时警告)
或者
RuntimeWarning:根据最近五次 Jacobian 评估的改进来衡量,迭代没有取得良好进展。
警告。警告(味精,运行时警告)
由于我将所有初始值和所属结果写入文本文件(只是将标准输出管道传输到文件),因此我想知道上面提到的 RuntimeWarnings 在我的 500 步计算中发生了什么。
正如numpy 文档中提到的,警告由Python 的标准警告模块处理,但是有没有办法在第一次 RuntimeWarning 发生后停止或暂停计算?
如果您想在发出警告时终止计算,您可以使用warnings模块的功能来强制将某些类型的警告作为异常引发。你可以这样写:
warnings.simplefilter('error')
Run Code Online (Sandbox Code Playgroud)
这会将所有警告变成错误并立即停止程序。缺点是不能通过简单地捕获异常来恢复计算:它已经完成了。
如果你想暂停程序,你可以使用一点“hack”来覆盖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)
Run Code Online (Sandbox Code Playgroud)
然后我们覆盖默认警告处理程序:
warnings.showwarning = handle_warning
Run Code Online (Sandbox Code Playgroud)
现在我们尝试优化一个平面函数:
from scipy.optimize import fsolve
fsolve(lambda x: 1, 1)
Run Code Online (Sandbox Code Playgroud)
我们几乎立即收到一条消息:
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:
Run Code Online (Sandbox Code Playgroud)
如果我们回答y,将允许优化继续并返回其结果。如果我们回答n,则会引发异常并终止计算。
或者,如果您不想showwarning在模块级别覆盖该功能,则可以使用上下文管理器。我们可以将它放在一个函数中,该函数将所有内容都包装得漂亮整洁:
def pause_if_warning(function, *args, **kwargs):
with warnings.catch_warnings():
warnings.showwarning = handle_warning
return function(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
所以我们现在可以写:
pause_if_warning(fsolve, lambda x: 1, 1)
Run Code Online (Sandbox Code Playgroud)
获得与上述相同的行为。