Как передать пользовательскую функцию equality_check в perfplot

Я работаю с библиотекой perfplot, чтобы сравнить производительность трех функций f1, f2 и f3. Предполагается, что функции возвращают одни и те же значения, поэтому я хочу выполнить проверку на равенство. Однако все другие примеры перфплотов, которые я могу найти в Интернете, используют pd.DataFrame.equals или np.allclose в качестве проверки равенства, но они не работают для моего конкретного случая.

Например, 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
)

Как мне передать функцию, отличную от вышеупомянутых функций?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если мы проверим исходный код , проверка на равенство работает следующим образом: она берет выходные данные первой функции, переданной kernels, в качестве эталона, и сравнивает их с выходными данными последующих функций, переданных kernels, в цикле.

По какой-то причине проверка на равенство различается в зависимости от того, возвращает ли первая функция в kernels кортеж или нет.

Если первая функция в kernels не возвращает кортеж, она просто вызывает функцию, переданную аргументу equality_check, для выполнения проверки. Функция проверки на равенство принимает два аргумента и может делать что угодно. Например, он может только проверить, равны ли длины, и назвать это днем ​​​​(т.е. передать следующую лямбду в equality_check: lambda x,y: len(x) == len(y)).

Например, в вопросе работает функция, которая перебирает пары элементов и проверяет неравенство.

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"
                    )

Другие вопросы по теме