使用异常处理、*args 和 **kwargs 删除函数的无穷大值
Posted
技术标签:
【中文标题】使用异常处理、*args 和 **kwargs 删除函数的无穷大值【英文标题】:Removing infinity values of a function using exception handling, *args, and **kwargs 【发布时间】:2015-08-17 22:09:13 【问题描述】:我目前正在阅读 Joel Grus 的 Data Science from Scratch 一书,我遇到了一个我不太了解的函数:
def safe(f):
def safe_f(*args, **kwargs):
try:
return f(*args, **kwargs)
except:
return float('inf')
return safe_f
在梯度下降算法中调用安全函数以删除无穷大值。
def minimize_batch(target_fn, gradient_fn, theta_0, tolerance=0.000001):
step_sizes = [100, 10, 1, 0.1, 0.001, 0.0001, 0.00001]
theta = theta_0
target_fn = safe(target_fn)
value = target_fn(theta)
while True:
gradient = gradient_fn(theta)
next_thetas = [step(theta, gradient, -step_size) for step_size in step_sizes]
next_theta = min(next_thetas, key=target_fn)
next_value = target_fn(next_theta)
if abs(value - next_value) < tolerance:
return theta
else:
theta, value = next_theta, next_value
我了解安全功能的要点,但我不明白 如何 它是这样做的。例如,如果 target_fn 没有输入,如何安全评估 target_fn?什么是安全的,它知道如何删除无穷大值?
抛开梯度下降不谈,这个安全函数是否可以在无数个地方都未定义的疯狂函数上工作?
【问题讨论】:
对我来说,它看起来并没有删除无穷大值。看起来它是在添加无穷大值,而不是引发异常。例如,return 1 / x
的不安全版本在 x 为零时引发 ZeroDivisionError
;安全装饰的版本不会引发异常,而是返回无穷大。
如果您知道safe
是一个装饰器 函数,并且f
可以在safe_f
中通过关闭.
【参考方案1】:
如果我们一步一步替换变量名,可能会帮助你理解:
target_fn = safe(target_fn)
表示safe
中的f
是target_fn
:
def safe(target_fn):
def safe_f(*args, **kwargs):
try:
return target_fn(*args, **kwargs)
except:
return float('inf')
return safe_f
和:
target_fn = safe_f
即我们将最初绑定到target_fn
的函数替换为我们刚刚在装饰器函数 safe
中创建的函数safe_f
,通过闭包保留对原始f
的访问权限。
所以参数是通过*args, **kwargs
传递的(见What does ** (double star) and * (star) do for parameters?):
next_value = target_fn(next_theta)
解决为:
def safe_f(next_theta):
try:
return target_fn(next_theta)
except:
return float('inf')
即要么返回调用原始 target_fn
并带有参数 next_theta
的结果,或者,如果这样做时发生任何错误,则返回 float('inf')
。
这个
safe
函数会在无数个地方都未定义的疯狂函数上工作吗?
由于它使用*args, **kwargs
,您可以使用它来包装any 函数,它会悄悄地抑制函数引发的any 错误并返回float('inf')
-不过,这并不总是可取的!装饰器函数还有许多其他用途,通常使用@decorator
语法应用(例如,用于class 和static 方法 和properties );参见例如What are some common uses for Python decorators?
【讨论】:
以上是关于使用异常处理、*args 和 **kwargs 删除函数的无穷大值的主要内容,如果未能解决你的问题,请参考以下文章
get_list_or_404(klass, *args, **kwargs)和get_object_or_404(klass, *args, **kwargs)区别