使用异常处理、*args 和 **kwargs 删除函数的无穷大值

Removing infinity values of a function using exception handling, *args, and **kwargs

我目前正在阅读 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 没有输入,safe 如何计算 target_fn?做什么是安全的,它知道如何删除无穷大值?

撇开梯度下降不谈,这个安全函数是否适用于在无数地方未定义的疯狂函数?

如果我们一步一步替换变量名,可能会帮助您理解:

target_fn = safe(target_fn)

表示safe中的ftarget_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')

即return 使用参数 next_theta 调用原始 target_fn 的结果,或者,如果这样做时出现任何错误,float('inf').

would this safe function work on a crazy functions that was undefined at uncountably many places?

因为它使用 *args, **kwargs 你可以用它来包装 any 函数,它会安静地抑制 any 引发的错误由函数和 return float('inf') 代替——但这并不总是令人满意的!装饰函数还有许多其他用途,通常使用 @decorator 语法(例如 class 静态方法属性 classes);参见例如What are some common uses for Python decorators?