numpy.sum переход на kahan, но с замаскированными массивами для повышения точности - PullRequest
0 голосов
/ 03 июля 2019

У меня есть стек из нескольких массивов данных, который замаскирован для исключения «плохих» или проблемных значений - это в 3-м измерении. Текущий код использует np.sum, но уровень точности (как большого, так и малого числа) отрицательно сказывается на результатах. Я попытался реализовать kahan_sum, на который есть ссылка, но забыл о замаскированных массивах, и результаты не похожи (из-за маскировки). Я надеюсь, что дополнительное сохранение точности за счет использования суммирования и накопления Кахана позволит операциям в нисходящем направлении поддерживать меньше ошибок.

Источник / исследования: https://github.com/numpy/numpy/issues/8786 суммирование по Кахану Сумма точности с плавающей точкой Python (Я повысил точность настолько, насколько это возможно, но это не помогает)


import numpy as np
import numpy.ma as ma


def kahan_sum(a, axis=None):
    s = numpy.zeros(a.shape[:axis] + a.shape[axis+1:])
    c = numpy.zeros(s.shape)
    for i in range(a.shape[axis]):
        # http://stackoverflow.com/a/42817610/353337
        y = a[(slice(None),) * axis + (i,)] - c
        t = s + y
        c = (t - s) - y
        s = t.copy()
    return s


data=np.random.rand(5,5,5)
dd=np.ma.masked_array(data=d, mask=np.random.rand(5,5,5)<0.2)

Я хочу суммировать по 3-й (ось = 2), поскольку это, по сути, моя «стопка» фотографий.

Маски не выходят так, как я ожидал. Возможно, я просто переутомился ...

np.sum(dd, axis=2)
kahan_sum(dd, axis=2)

np.sum предоставляет полностью заполненный массив данных и исключает «замаскированные» значения. kahan_sum по сути или все маскированные значения, и я не смог придумать образец для этого.

Печать маски довольно очевидна, вот в чем проблема; Я просто не понимаю, как это исправить или почему он работает так, как есть.

Спасибо.

1 Ответ

0 голосов
/ 03 июля 2019

Если вам действительно нужно больше точности, рассмотрите возможность использования math.fsum, которое точно соответствует разрешению fp.Если A - это ваш массив 3D-маски, что-то вроде:

i,j,k = A.shape
np.frompyfunc(lambda i,j:math.fsum(A[i,j].compressed().tolist()),2,1)(*np.ogrid[:i,:j])

Но перед этим я бы трижды проверил, что np.sum действительно недостаточно хорош.Насколько я знаю, он использует парное суммирование по смежным осям, что на практике имеет тенденцию быть довольно хорошим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...