Python scipy rv_continuous 实施的问题
Issues with Python scipy rv_continuous implementation
我正在尝试使用自定义分布创建 rv_continuous 的子class,我可以通过许多函数为其计算 pdf。
这是我到目前为止所做的
import numpy as np
from scipy.stats import rv_continuous
辅助功能
def func1(xx, a_, b_, rho, m, sigma):
return a_ + b_*(rho*(xx-m) + np.sqrt((xx-m)*(xx-m) + sigma*sigma))
def func2(xx, a_, b_, rho, m, sigma):
sig2 = sigma*sigma
return b_*(rho*np.sqrt((xx-m)*(xx-m)+sig2)+xx-m)/(np.sqrt((xx-m)*(xx-m)+sig2))
def func3(xx, a_, b_, rho, m, sigma):
sig2 = sigma*sigma
return b_*sig2/(np.sqrt((xx-m)*(xx-m)+sig2)*((xx-m)*(xx-m)+sig2))
def func4(xx, a_, b_, rho, m, sigma):
w = func1(xx, a_, b_, rho, m, sigma)
w1 = func2(xx, a_, b_, rho, m, sigma)
w2 = func3(xx, a_, b_, rho, m, sigma)
return (1.-0.5*xx*w1/w)*(1.0-0.5*xx*w1/w) - 0.25*w1*w1*(0.25 + 1./w) + 0.5*w2
def func5(xx, a_, b_, rho, m, sigma):
vsqrt = np.sqrt(func1(xx, a_, b_, rho, m, sigma))
return -xx/vsqrt - 0.5*vsqrt
密度函数最终
def density(xx, a_, b_, rho, m, sigma):
dm = func5(xx, a_, b_, rho, m, sigma)
return func4(xx, a_, b_, rho, m, sigma)*np.exp(-0.5*dm*dm)/np.sqrt(2.*np.pi*func1(xx, a_, b_, rho, m, sigma))
一组参数
Params = 1.0073, 0.3401026, -0.8, 0.000830, 0.5109564
检查函数中的 pdf
xmin, xmax, nbPoints = -10., 10., 2000
x_real = np.linspace(xmin, xmax, nbPoints)
den_from_func = density(x_real, *Params)
现在构造我的分布class
class density_gen(rv_continuous):
def _pdf(self, x, a_hat, b_hat, rho, m, sigma):
return density(x, a_hat, b_hat, rho, m, sigma)
实例化
my_density = density_gen(name='density_gen')
my_density.a, my_density.b, my_density.numargs
正如我指定的 _pdf 我应该有一个工作分发实例
这有效
pdf = my_density._pdf(x_real, *Params)
cdf 也可以工作,尽管它非常慢
cdf = my_density._cdf(x_real, *Params)
my_density._cdf(0.1, *Params)
但是对于所有其他方法我得到了 nans,例如
my_density.mean(*Params)
my_density.ppf(0.01, *Params)
我哪里做错了?
您似乎需要将 _argcheck
方法添加到 density_gen
,因为您的分发使用了自定义参数:
class density_gen(rv_continuous):
def _argcheck(self, *Params):
return True
def _pdf(self, x, a_hat, b_hat, rho, m, sigma):
return density(x, a_hat, b_hat, rho, m, sigma)
my_density = density_gen(name='density_gen')
pdf = my_density._pdf(x_real, *Params)
print(my_density.rvs(size=5, *Params))
print(my_density.mean(*Params))
print(my_density.ppf(0.01, *Params))
但是rvs
、mean
等之后会很慢,估计是因为该方法每次需要生成随机数或者计算统计量的时候都需要对PDF进行积分.如果速度非常重要,那么您需要向 density_gen
添加一个使用自己的采样器的 _rvs
方法。这方面的一个例子是我自己的 DensityInversionSampler
,当只给定 PDF 和采样域时,它通过数值反转生成随机数。
我正在尝试使用自定义分布创建 rv_continuous 的子class,我可以通过许多函数为其计算 pdf。
这是我到目前为止所做的
import numpy as np
from scipy.stats import rv_continuous
辅助功能
def func1(xx, a_, b_, rho, m, sigma):
return a_ + b_*(rho*(xx-m) + np.sqrt((xx-m)*(xx-m) + sigma*sigma))
def func2(xx, a_, b_, rho, m, sigma):
sig2 = sigma*sigma
return b_*(rho*np.sqrt((xx-m)*(xx-m)+sig2)+xx-m)/(np.sqrt((xx-m)*(xx-m)+sig2))
def func3(xx, a_, b_, rho, m, sigma):
sig2 = sigma*sigma
return b_*sig2/(np.sqrt((xx-m)*(xx-m)+sig2)*((xx-m)*(xx-m)+sig2))
def func4(xx, a_, b_, rho, m, sigma):
w = func1(xx, a_, b_, rho, m, sigma)
w1 = func2(xx, a_, b_, rho, m, sigma)
w2 = func3(xx, a_, b_, rho, m, sigma)
return (1.-0.5*xx*w1/w)*(1.0-0.5*xx*w1/w) - 0.25*w1*w1*(0.25 + 1./w) + 0.5*w2
def func5(xx, a_, b_, rho, m, sigma):
vsqrt = np.sqrt(func1(xx, a_, b_, rho, m, sigma))
return -xx/vsqrt - 0.5*vsqrt
密度函数最终
def density(xx, a_, b_, rho, m, sigma):
dm = func5(xx, a_, b_, rho, m, sigma)
return func4(xx, a_, b_, rho, m, sigma)*np.exp(-0.5*dm*dm)/np.sqrt(2.*np.pi*func1(xx, a_, b_, rho, m, sigma))
一组参数
Params = 1.0073, 0.3401026, -0.8, 0.000830, 0.5109564
检查函数中的 pdf
xmin, xmax, nbPoints = -10., 10., 2000
x_real = np.linspace(xmin, xmax, nbPoints)
den_from_func = density(x_real, *Params)
现在构造我的分布class
class density_gen(rv_continuous):
def _pdf(self, x, a_hat, b_hat, rho, m, sigma):
return density(x, a_hat, b_hat, rho, m, sigma)
实例化
my_density = density_gen(name='density_gen')
my_density.a, my_density.b, my_density.numargs
正如我指定的 _pdf 我应该有一个工作分发实例
这有效
pdf = my_density._pdf(x_real, *Params)
cdf 也可以工作,尽管它非常慢
cdf = my_density._cdf(x_real, *Params)
my_density._cdf(0.1, *Params)
但是对于所有其他方法我得到了 nans,例如
my_density.mean(*Params)
my_density.ppf(0.01, *Params)
我哪里做错了?
您似乎需要将 _argcheck
方法添加到 density_gen
,因为您的分发使用了自定义参数:
class density_gen(rv_continuous):
def _argcheck(self, *Params):
return True
def _pdf(self, x, a_hat, b_hat, rho, m, sigma):
return density(x, a_hat, b_hat, rho, m, sigma)
my_density = density_gen(name='density_gen')
pdf = my_density._pdf(x_real, *Params)
print(my_density.rvs(size=5, *Params))
print(my_density.mean(*Params))
print(my_density.ppf(0.01, *Params))
但是rvs
、mean
等之后会很慢,估计是因为该方法每次需要生成随机数或者计算统计量的时候都需要对PDF进行积分.如果速度非常重要,那么您需要向 density_gen
添加一个使用自己的采样器的 _rvs
方法。这方面的一个例子是我自己的 DensityInversionSampler
,当只给定 PDF 和采样域时,它通过数值反转生成随机数。