Эффективная оценка всей базы BSpline в Python

#python #numpy #scipy

Вопрос:

У меня есть последовательность узлов кубического сплайна в массиве NumPy knots , и я хотел бы эффективно оценить весь кубический базис BSpline, который представлен массивом узлов в определенной точке x . То, что я сейчас делаю, — это построение основы с использованием scipy.interpolate.BSpline класса SciPy:

 from scipy.interpolate import BSpline

def bspline_basis(knots):
    return [
        BSpline.basis_element(knots[i:(i 5)], extrapolate=False)
        for i in range(len(knots) - 4)
    ]
 

а затем использовать возвращенную основу для оценки:

 def eval_basis(basis, x):
    return [elem(val).item() for elem in basis]
 

Однако, поскольку eval_basis функция вызывается миллионы раз, приведенный выше код выполняется медленно! BSpline Объект оптимизирован для работы с массивами, и я снабжаю его отдельными скалярами x и извлекаю скаляры из результирующих массивов.

Из-за того , что я работаю в существующей кодовой базе, в которой я не могу изменить протокол вызова eval_basis , он должен вызываться на отдельных скалярах x .

Код явно может быть ускорен, если я смогу каким-то образом эффективно оценить всю базу BSpline в какой-то момент x и получить массив NumPy значений базовых функций. Есть ли такой способ использовать SciPy или другую библиотеку Python?

Ответ №1:

scipy.interpolate._bspl.evaluate_all_bspl не имеет документов, но делает это

Комментарии:

1. Поскольку он недокументирован, может быть, добавьте в свой ответ некоторый контекст и код, чтобы показать, как его использовать?

2. Я не знаю, в каких версиях он существует, но в официальном репозитории scipy, похоже, его не существует: github.com/scipy/scipy/blob/master/scipy/interpolate/…

3. Действительно, это так _bspl.evaluate_all_bspl . В какой-то момент он может стать общедоступным интерфейсом, но сегодня вы можете использовать непубличную внутреннюю версию (предостережение).