Подтвердить что ты не робот

Может ли кто-нибудь объяснить это странное поведение гипергеометрического распределения в скупе?

Я запускаю 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

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

4b9b3361

Ответ 1

Проблема, по-видимому, возникает, если первый вызов функции выживания находится в диапазоне, который должен быть равен нулю (см. мой комментарий к предыдущему ответу). Например, для вызовов 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. В принципе, если результат равен нулю, потому что он не выполняет проверки, он пытается вызвать место, терпеть неудачу и не генерировать распределение. (Этого не происходит, если предыдущий дистрибутив уже создан, что вполне вероятно, почему это не было обнаружено при более ранних тестах.) Обратите внимание, что место (определенное в numpy function_base.py) изменит элементы массива (хотя я не уверен, изменит ли он размерность), поэтому лучше всего оставить его после того, как он погаснет. Я не полностью тестировал это, чтобы увидеть, не изменилось ли это изменение на что-либо другое (и оно относится ко всем дискретным распределениям случайных переменных), поэтому лучше всего сделать первое исправление.

Это сломает его; например, 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

Ответ 2

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

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

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

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