如何将BallTree metric参数内的lambda函数转换为独立函数并正确传参
错误原因
你遇到的报错核心是给BallTree的func参数传入了函数执行后的返回值(浮点型),但该参数要求传入可被内部调用的函数对象本身:
- 原有lambda写法传入的是未执行的函数本身,BallTree内部计算距离时会自动传入
p0、p1两个样本点参数 - 你的改写写法直接执行了
elipse(),把计算得到的浮点结果赋值给了func,BallTree尝试调用该浮点值时就触发了类型错误 - 额外注意:
p0、p1是BallTree遍历样本时自动传入的参数,不需要你手动传递样本值
解决方案
有两种常用的改写方式,都可以实现把lambda提取为独立函数的需求:
方案1:使用functools.partial固定额外参数
该方法灵活性最高,适合aspect参数需要动态调整的场景:
import math import numpy as np from sklearn.neighbors import BallTree from functools import partial # 自定义距离函数不用改 def elipse(p0, p1, aspect): return math.sqrt((p1[0] - p0[0]) ** 2 + (p1[1] - p0[1]) ** 2 * aspect) X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]]) aspect = 2 # 用partial提前绑定aspect参数,得到仅需接收p0、p1的可调用对象 tree = BallTree(X, metric="pyfunc", func=partial(elipse, aspect=aspect))
方案2:用轻量lambda包装自定义函数
如果不想引入额外的包,也可以用lambda做一层简单的参数转发:
# 自定义距离函数定义不变 def elipse(p0, p1, aspect): return math.sqrt((p1[0] - p0[0]) ** 2 + (p1[1] - p0[1]) ** 2 * aspect) # 构造BallTree时用lambda转发p0、p1参数,同时传入aspect tree = BallTree(X, metric="pyfunc", func=lambda p0, p1: elipse(p0, p1, aspect))
内容的提问来源于stack exchange,提问作者roudan
相关产品推荐
相关产品推荐

