Как создать lo git -нормальный дистрибутив в Python? - PullRequest
2 голосов
/ 13 марта 2020

После этого поста я попытался создать ненормальный дистрибутив lo git, создав класс LogitNormal:

import numpy as np
import matplotlib.pyplot as plt
from scipy.special import logit
from scipy.stats import norm, rv_continuous


class LogitNormal(rv_continuous):
    def _pdf(self, x, **kwargs):
        return norm.pdf(logit(x), **kwargs)/(x*(1-x))


class OtherLogitNormal:
    def pdf(self, x, **kwargs):
        return norm.pdf(logit(x), **kwargs)/(x*(1-x))


fig, ax = plt.subplots()
values = np.linspace(10e-10, 1-10e-10, 1000)
sigma, mu = 1.78, 0
ax.plot(
    values, LogitNormal().pdf(values, loc=mu, scale=sigma), label='subclassed'
)
ax.plot(
    values, OtherLogitNormal().pdf(values, loc=mu, scale=sigma),
    label='not subclassed'
)
ax.legend()
fig.show()

Однако класс LogitNormal делает не дает желаемых результатов. Когда я не делаю подкласс rv_continuous, это работает. Это почему? Мне нужен подкласс для работы, потому что мне также нужны другие методы, которые идут с ним, как rvs.

Кстати, единственная причина, по которой я создаю свой собственный lo git -нормальный дистрибутив в Python, заключается в том, что единственные реализации этого дистрибутива, которые я смог найти, были из PyMC3 пакета и из пакета TensorFlow , оба из которых довольно тяжелые / избыточные, если они нужны только для этой одной функции. Я уже пробовал PyMC3, но, видимо, с * 1017 это не очень хорошо. Я думаю, он всегда падал для меня. Но это совсем другая история.

1 Ответ

1 голос
/ 13 марта 2020

Если вы посмотрите на исходный код метода pdf , вы заметите, что _pdf вызывается без аргументов ключевых слов scale и loc.

   if np.any(cond):
        goodargs = argsreduce(cond, *((x,)+args+(scale,)))
        scale, goodargs = goodargs[-1], goodargs[:-1]
        place(output, cond, self._pdf(*goodargs) / scale)

В результате kwargs в вашем переопределенном методе _pdf всегда является пустым словарем.

Если вы посмотрите немного ближе к коду, вы также заметите, что масштабирование и расположение обрабатываются pdf, а не _pdf.

В вашем случае _pdf вызывает метод norm.pdf, поэтому параметры loc и scale должны как-то быть доступны в LogitNormal._pdf.

Вы можете, например, передать scale и loc при создании экземпляра LogitNormal и сохранить значения как атрибуты класса:

import numpy as np
import matplotlib.pyplot as plt
from scipy.special import logit
from scipy.stats import norm, rv_continuous


class LogitNormal(rv_continuous):
    def __init__(self, scale=1, loc=0):
        super().__init__(self)
        self.scale = scale
        self.loc = loc

    def _pdf(self, x):
        return norm.pdf(logit(x), loc=self.loc, scale=self.scale)/(x*(1-x))


fig, ax = plt.subplots()
values = np.linspace(10e-10, 1-10e-10, 1000)
sigma, mu = 1.78, 0
ax.plot(
    values, LogitNormal(scale=sigma, loc=mu).pdf(values), label='subclassed'
)
ax.legend()
fig.show()
...