Вычисление движущейся медианы с помощью scipy generic_filter и numpy median_filter дает разные результаты - PullRequest
1 голос
/ 25 июня 2019

Я рассчитываю реализовать быстро движущуюся медиану, так как мне приходится делать много медиан для моей программы.Я хотел бы использовать встроенные функции Python, поскольку они были бы более оптимизированы, чем то, что я мог бы сделать.

Моя медиана должна сделать: - извлечь 5 значений, - удалить центральное, - найти медиану оставшихся 4значения.

В основном несколько вызовов:

numpy.median(np.array([0, 1, 2, 3, 4])[np.array([True, True, False, True, True])])
# (1. + 3.) / 2. = 2.0

Я нашел две функции: scipy generic_filter и numpy median_filter.Моя проблема в том, что generic_filter дает правильный вывод, а не median_filter, даже если кажется, что они имеют одинаковые параметры.Более того, generic_filter медленнее, чем median_filter.Поэтому я хотел бы знать, что я делаю неправильно в моем вызове median_filter, и использовать его для целей скорости.

import numpy as np
import scipy.ndimage as sc

v = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

print(sc.generic_filter(v, sc.median, footprint=np.array([1, 1, 0, 1, 1]), mode = "mirror", output=np.float64))
%timeit sc.generic_filter(v, sc.median, footprint=np.array([1, 1, 0, 1, 1]), mode = "mirror", output=np.float64)

print(sc.median_filter(v, footprint=np.array([1, 1, 0, 1, 1]), output=np.float64, mode="mirror"))
%timeit sc.median_filter(v, footprint=np.array([1, 1, 0, 1, 1]), output=np.float64, mode="mirror")

Как видите, generic_filter дает правильный вывод: [1.5 1.5 2. 34. 5. 6. 7. 8. 8.5 8.5] 327 мкс ± 15,2 мкс на цикл (среднее ± стандартное отклонение из 7 циклов, по 1000 циклов каждый)

, и median_filter быстрее, но я нене понимаю его вывод: [2.2. 3. 4. 5. 6. 7. 8. 9. 9. 9.] 12,4 мкс ± 217 нс на цикл (среднее ± стандартное отклонение из 7 циклов, 100000 циклов каждый)

DoВы знаете, что не так с моим звонком?

1 Ответ

0 голосов
/ 25 июня 2019

Единственная разница, кажется, связана с тем, как обрабатываются "связи":

  • sc.median возвращает среднее значение связей
  • sc.median_filter, кажется, систематически возвращает большее значение

учитывая способ median_filter реализован Неловко обрабатывать специальные / специфические для случая "медианы по четному числу элементов должны эффективно возвращать среднее число связей"

Я взломал версию, которая обрабатывает этот случай:

from scipy.ndimage.filters import _rank_filter

def median_filter(input, footprint, output=None, mode="reflect", cval=0.0, origin=0):
    filter_size = np.where(footprint, 1, 0).sum()
    rank = filter_size // 2
    result = _rank_filter(
        input, rank, None, footprint, output, mode, cval, origin, 'dummy')
    if filter_size % 2 == 0:
        if result is output:
            tmp = result.copy()
        else:
            tmp = result
        rank -= 1
        assert rank > 0
        result = _rank_filter(
            input, rank, None, footprint, output, mode, cval, origin, 'dummy')
        # fix up ties without creating any more garbage
        result += tmp
        result /= 2
    return result

но это немного неуклюже, и использует внутреннюю функциональность от scipy (я использую 1.3.0), поэтому, вероятно, сломается в будущем

на моей машине эти показатели как:

  • sc.generic_filter занимает 578 мкс ± 8,51 мкс на цикл
  • sc.median_filter занимает 27,4 мкс ± 1,37 мкс на петлю
  • my median_filter занимает 65,6 мкс ± 1,29 мкс на цикл
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...