[英]Need help understanding function passing in Python
我试图通过解决我提出的一些问题来教自己Python,我需要一些帮助来理解如何传递函数。
假设我试图根据今天和昨天的温度预测明天的温度,我写了以下函数:
def predict_temp(temp_today, temp_yest, k1, k2):
return k1*temp_today + k2*temp_yest
我还写了一个错误函数来比较预测温度列表和实际温度,并返回平均绝对误差:
def mean_abs_error(predictions, expected):
return sum([abs(x - y) for (x,y) in zip(predictions,expected)]) / float(len(predictions))
现在,如果我有一个过去某个时间间隔的每日温度列表,我可以看到我的预测函数如何使用特定的k1和k2参数完成,如下所示:
>>> past_temps = [41, 35, 37, 42, 48, 30, 39, 42, 33]
>>> pred_temps = [predict_temp(past_temps[i-1],past_temps[i-2],0.5,0.5) for i in xrange(2,len(past_temps))]
>>> print pred_temps
[38.0, 36.0, 39.5, 45.0, 39.0, 34.5, 40.5]
>>> print mean_abs_error(pred_temps, past_temps[2:])
6.5
但是如何设计一个函数来最小化我的predict_temp函数的参数k1和k2给定一个错误函数和我的past_temps数据?
具体来说,我想写一个函数最小化(args *),它采用预测函数,误差函数,一些训练数据,并使用一些搜索/优化方法(例如梯度下降)来估计和返回k1的值和k2在给定数据的情况下最小化我的错误?
我不是问如何实现优化方法。 假设我能做到这一点。 相反,我只想知道如何将我的预测和错误函数 (以及我的数据)传递给我的最小化函数,以及如何告诉我的最小化函数它应该优化参数k1和k2 ,以便我的最小化函数可以自动搜索k1和k2的一堆不同设置,每次将我的预测函数与这些参数应用于数据和计算错误(就像我手动为k1 = 0.5和k2 = 0.5以上)然后返回最佳结果。
我希望能够通过这些功能,以便我可以轻松交换不同的预测和错误功能(不仅仅是参数设置不同)。 每个预测函数可能具有不同数量的自由参数。
我的最小化函数应该看起来像这样,但我不知道如何继续:
def minimize(prediction_function, which_args_to_optimize, error_function, data):
# 1: guess initial parameters
# 2: apply prediction function with current parameters to data to compute predictions
# 3: use error function to compute error between predictions and data
# 4: if stopping criterion is met, return parameters
# 5: update parameters
# 6: GOTO 2
编辑:这很容易吗? 这不好玩。 我要回到Java了。
更严重的是,我认为我也开始讨论如何使用不同数量的参数来调整不同的预测函数。 如果我只将所有自由参数作为一个元组,我可以保持函数的形式相同,以便于传递和使用。
这是一个如何将函数传递给另一个函数的示例。 apply_func_to
将取一个函数f
和一个数字num
作为参数并return f(num)
。
def my_func(x):
return x*x
def apply_func_to(f, num):
return f(num)
>>>apply_func_to(my_func, 2)
4
如果你想要聪明,你可以使用lambda(匿名函数)。 这些允许您“动态”传递函数,而无需单独定义它们
>>>apply_func_to(lambda x:x*x, 3)
9
希望这可以帮助。
使用Python传递函数很简单,只需使用函数名作为包含函数本身的变量即可。
def predict(...):
...
minimize(predict, ..., mean_abs_error, ...)
至于问题的其余部分:我建议看看SciPy将其作为模型实现的方式。 基本上,它们具有函数leastsq
,其最小化残差的平方和(我假设你知道什么是最小二乘最小化;-)。 传递给leastsq
是计算残差,参数的初始猜测以及传递给残差计算函数(闭包)的任意参数的函数,其中包括数据:
# params will be an array of your k's, i.e. [k1, k2]
def residuals(params, measurements, times):
return predict(params, times) - measurements
leastsq(residuals, initial_parameters, args = (measurements, times))
请注意,SciPy实际上并不关心你如何提出残差。 measurements
数组只是不加改变地传递给residuals
函数。
如果你想了解更多信息,我可以查看我最近做的一个例子 - 当然,你可以在网上找到例子,但根据我的经验,他们并不那么清楚。 我编写的特定代码与您的场景有很好的关系。
正如David和Il-Bhima所说,函数可以像任何其他类型的对象一样传递到其他函数中。 当您传入函数时,您只需像通常那样调用它。 人们有时会通过说函数是Python中的第一类来引用这种能力。 在更高级别的细节上,您应该将Python中的函数视为一种可调用对象 。 Python中另一种重要的可调用对象是类对象; 在这种情况下,调用类对象会创建该对象的实例。 这里将详细讨论这个概念。
一般地,你可能会想利用Python中的位置和/或关键字参数的功能,如所描述这里 。 这将允许您编写一个通用的最小化器,可以最小化采用不同参数集的预测函数。 我写了一个例子---它比我想要的更复杂(使用生成器!)但它适用于具有任意参数的预测函数。 我已经掩饰了一些细节,但这应该让你开始:
def predict(data, k1=None, k2=None):
"""Make the prediction."""
pass
def expected(data):
"""Expected results from data."""
pass
def mean_abs_err(pred, exp):
"""Compute mean absolute error."""
pass
def gen_args(pred_args, args_to_opt):
"""Update prediction function parameters.
pred_args : a dict to update
args_to_opt : a dict of arguments/iterables to apply to pred_args
This is a generator that updates a number of variables
over a given numerical range. Equivalent to itertools.product.
"""
base_args = pred_args.copy() #don't modify input
argnames = args_to_opt.keys()
argvals = args_to_opt.values()
result = [[]]
# Generate the results
for argv in argvals:
result = [x+[y] for x in result for y in argv]
for prod in result:
base_args.update(zip(argnames, prod))
yield base_args
def minimize(pred_fn, pred_args, args_to_opt, err_fn, data):
"""Minimize pred_fn(data) over a set of parameters.
pred_fn : function used to make predictions
pred_args : dict of keyword arguments to pass to pred_fn
args_to_opt : a dict of arguments/iterables to apply to pred_args
err_fn : function used to compute error
data : data to use in the optimization
Returns a tuple (error, parameters) of the best set of input parameters.
"""
results = []
for new_args in gen_args(pred_args, args_to_opt):
pred = pred_fn(data, **new_args) # Unpack dictionary
err = err_fn(pred, expected(data))
results.append((err, new_args))
return sorted(results)[0]
const_args = {k1: 1}
opt_args = {k2: range(10)}
data = [] # Whatever data you like.
minimize(predict, const_args, opt_args, mean_abs_err, data)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.