繁体   English   中英

如何将自定义 equality_check function 传递到 perfplot

[英]How to pass a custom equality_check function into perfplot

我正在使用 perfplot 库来比较三个函数f1f2f3的性能。 这些函数应该返回相同的值,所以我想进行相等性检查。 但是,我可以在 inte.net 上找到的所有其他 perfplot 示例都使用pd.DataFrame.equalsnp.allclose作为相等性检查器,但这些不适用于我的特定情况。

例如,如果函数返回不同长度的 numpy arrays 列表,则np.allclose将不起作用。

import perfplot
import numpy as np

def f1(rng):
    return [np.array(range(i)) for i in rng]

def f2(rng):
    return [np.array(list(rng)[:i]) for i in range(len(rng))]

def f3(rng):
    return [np.array([*range(i)]) for i in rng]


perfplot.show(
    kernels=[f1, f2, f3],
    n_range=[10**k for k in range(4)],
    setup=lambda n: range(n),
    equality_check=np.allclose   # <-- doesn't work; neither does pd.DataFrame.equals
)

如何传递与上述功能不同的 function?

如果我们检查源代码,相等性检查的工作方式是将传递给kernels的第一个 function 中的 output 作为参考,并将其与循环中传递给kernels的后续函数的 output 进行比较。

出于某种原因,相等性检查会有所不同,具体取决于kernels中的第一个 function 是否返回元组。

如果kernels中的第一个 function 没有返回元组,它只是调用传递给equality_check参数的 function 来执行检查。 相等性检查 function 需要两个 arguments 并且可以做任何事情。 例如,它只能检查长度是否相等并收工(即将以下 lambda 传递给equality_checklambda x,y: len(x) == len(y) )。

对于问题中的示例,循环元素对并检查不等式的 function 有效。

def equality_check(x, y):
    for i, j in zip(x, y):
        if not np.allclose(i, j):
            return False
    return True

perfplot.show(
    kernels=[f1, f2, f3],
    n_range=[10**k for k in range(4)],
    setup=lambda n: range(n),
    equality_check=equality_check
)

事实上, all()也有效。

perfplot.show(
    kernels=[f1, f2, f3],
    n_range=[10**k for k in range(4)],
    setup=lambda n: range(1, n+1),
    equality_check=lambda x,y: all([x,y])
)

源代码中复制的以下代码是实现相等性检查的片段:

for k, kernel in enumerate(self.kernels):

    val = kernel(*data)

    if self.equality_check:
        if k == 0:
            reference = val
        else:
            try:
                if isinstance(reference, tuple):
                    assert isinstance(val, tuple)
                    assert len(reference) == len(val)
                    is_equal = True
                    for r, v in zip(reference, val):
                        if not self.equality_check(r, v):
                            is_equal = False
                            break
                else:
                    is_equal = self.equality_check(reference, val)
            except TypeError:
                raise PerfplotError(
                    "Error in equality_check. "
                    + "Try setting equality_check=None."
                )
            else:
                if not is_equal:
                    raise PerfplotError(
                        "Equality check failure.\n"
                        + f"{self.labels[0]}:\n"
                        + f"{reference}:\n\n"
                        + f"{self.labels[k]}:\n"
                        + f"{val}:\n"
                    )

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM