我有一个一维数据集,我已经使用statsmodels和scipy在Python中计算了核密度估计。
我想生成一组随机数,看看它们是否能给我相同的分布。
到目前为止,我找到的解决方案是这样的:
在0到1之间抽取一个数x,并返回cdf^{-1}(x),其中cdf^{-1}是’f’的逆累积分布函数。
这个方法的问题是,使用statsmodels我能够找到逆累积分布,但它是以矩阵的形式存在的。因此,将一个数x乘以这个矩阵并不能给我从计算的KDE分布中得到的随机样本。
我如何从给定的KDE函数或分布中生成随机数呢?
编辑:这里有一个代码示例:
def calcKDE(data): #计算KDE kde = sm.nonparametric.KDEUnivariate(data) kde.fit(kernel='gau', bw='silverman') return kdedef generateData(data, kde): inverse_cdf = kde.icdf #这是一个不带参数的方法,kde.cdf也是如此 randomSet = np.random.random(1) * inverse_cdf #inverse_cdf被视为矩阵,这里还将添加一个循环以返回1000个随机值 return randomSet
回答:
逆变换抽样方法如下所示:
from scipy.optimize import brentqimport statsmodels.api as smimport numpy as np# 拟合kde = sm.nonparametric.KDEMultivariate() # ... 你已经做了这个# 抽样u = np.random.random()# 1-d 根查找def func(x): return kde.cdf([x]) - usample_x = brentq(func, -99999999, 99999999) # 阅读brentq文档关于这些常数的说明 # 常数需要使函数改变符号
我建议以基于类的形式实现这个方法,并自定义一个抽样函数以便更好地使用。
这种方法也非常通用,并且有许多更快的方法使用关于所用核的附加信息(不使用逆变换抽样)。你可以通过谷歌找到一些例子。
另一个评论:
- scikit-learn的核密度估计自带一个
sample-function
我对kde工具从最好到最差的排序(我的观点):
- statsmodels(像依赖变量这样的好功能;基于优化的交叉验证)
- scikit-learn(易于使用;sample-function;基于网格和随机搜索的交叉验证)
- scipy(不太喜欢它,但对于某些用途有基于fft的方法 -> 快)