Могут ли некоторые объяснить это странное поведение гипергеометрического распределения у Сципиона? - PullRequest
11 голосов
/ 28 сентября 2010

Я использую Python 2.6.5 на Mac OS X 10.6.4 (это не нативная версия, я установил ее сам) с Scipy 0.8.0Если я сделаю следующее:

>>> from scipy.stats import hypergeom
>>> hypergeom.sf(5,10,2,5)

, я получу IndexError.Затем я делаю:

>>> hypergeom.sf(2,10,2,2)
-4.44....

Я подозреваю, что отрицательное значение связано с плохой точностью с плавающей запятой.Затем я делаю первый снова:

>>> hypergeom.sf(5,10,2,5)
0.0

Теперь это работает!Может кто-нибудь объяснить это?Вы тоже видите это поведение?

Ответы [ 2 ]

3 голосов
/ 22 октября 2010

Проблема, похоже, возникает из-за того, что первый вызов функции выживания находится в диапазоне, который, очевидно, должен быть равен нулю (см. Мой комментарий к предыдущему ответу). Например, для вызовов hypergeom.sf (x, M, n, N) он завершается неудачно, если первый вызов гипергеометрической функции для функции представляет собой ситуацию, когда x> n, где функция выживания всегда будет равна нулю.

Вы можете временно исправить это следующим образом:

def new_hypergeom_sf(k, *args, **kwds):
    from scipy.stats import hypergeom
    (M, n, N) = args[0:3]
    try:
        return hypergeom.sf(k, *args, **kwds)
    except Exception as inst:
        if k >= n and type(inst) == IndexError:
            return 0 ## or conversely 1 - hypergeom.cdf(k, *args, **kwds)
        else:
            raise inst

Теперь, если у вас нет проблем с редактированием /usr/share/pyshared/scipy/stats/distributions.py (или эквивалентного файла), исправление, скорее всего, в строке 3966, где прямо сейчас оно выглядит так:

    place(output,cond,self._sf(*goodargs))
    if output.ndim == 0:
        return output[()]
    return output

Но если вы измените его на:

    if output.ndim == 0:
        return output[()]
    place(output,cond,self._sf(*goodargs))
    if output.ndim == 0:
        return output[()]
    return output

Теперь работает без IndexError. В основном, если выходные данные являются нуль-мерными, потому что он не проходит проверки, он пытается вызвать place, терпит неудачу и не генерирует распределение. (Этого не происходит, если предыдущий дистрибутив уже был создан, что, вероятно, не было обнаружено в предыдущих тестах.) Обратите внимание, что место (определенное в numpy's function_base.py) изменит элементы массива (хотя я не уверен, изменяет ли он размерность), поэтому лучше оставить его, также оставив проверку 0 dim после места. Я не полностью проверил это, чтобы увидеть, нарушает ли это изменение что-то еще (и оно применяется ко всем распределениям дискретных случайных величин), поэтому, возможно, лучше всего сделать первое исправление.

Это ломает его; например, stats.hypergeom.sf (1,10,2,5) возвращается как ноль (вместо 2/9).

Это исправление работает намного лучше, в том же разделе:

class rv_discrete(rv_generic):
...
    def sf(self, k, *args, **kwds):
    ...
        if any(cond):
            place(output,cond,self._sf(*goodargs))
        if output.ndim == 0:
            return output[()]
        return output
0 голосов
/ 17 октября 2010

Я не знаю Python, но функция определяется следующим образом: hypergeom.sf (x, M, n, N, loc = 0)

M - количество интересных объектов, N -общее количество объектов, а n это то, как часто вы «выбираете один» (извините, немецкий статистик).

Если у вас была чаша с 20 шарами, 7 из которых желтые (интересный желтый), тогда N20 и M равно 7.

Возможно, функция ведет себя неопределенно для (бессмысленного) случая, когда M> N?

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