python中多元核密度估计的条件抽样
Posted
技术标签:
【中文标题】python中多元核密度估计的条件抽样【英文标题】:conditional sampling from multivariate kernel density estimate in python 【发布时间】:2020-05-30 02:10:30 【问题描述】:可以创建一个多元核密度估计 (KDE) scikitlearn (https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KernelDensity.html#sklearn.neighbors.KernelDensity) 和 scipy (https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.gaussian_kde.html)
两者都允许从估计分布中进行随机抽样。有没有办法在两个库(或任何其他库)中的任何一个中进行条件采样? 在 2 变量 (x,y) 的情况下,这意味着来自 P(x|y)(或 P(y|x))的样本,因此来自概率函数的横截面(并且该横截面必须重新缩放到其曲线下的单位面积)。
x = np.random.random(100)
y =np.random.random(100)
kde = stats.gaussian_kde([x,y])
# sampling from the whole pdf:
kde.resample()
我正在寻找类似的东西
# sampling y, conditional on x
kde.sample_conditional(x=1.5) #does not exist
【问题讨论】:
你解决了吗? 也对此感兴趣。 有什么进展吗? 检查我的答案 【参考方案1】:此函数根据所有其他列有条件地对一列进行采样。
def conditional_sample(kde, training_data, columns, values, samples = 100):
if len(values) - len(columns) != 0:
raise ValueError("length of columns and values should be equal")
if training_data.shape[1] - len(columns) != 1:
raise ValueError(f'Expected training_data.shape[1] - 1 columns/values but len(columns) have be given')
cols_values_dict = dict(zip(columns, values))
#create array to sample from
steps = 10000
X_test = np.zeros((steps,training_data.shape[1]))
for i in range(training_data.shape[1]):
col_data = training_data.iloc[:, i]
X_test[:, i] = np.linspace(col_data.min(),col_data.max(),steps)
for col in columns:
idx_col_training_data = list(training_data.columns).index(col)
idx_in_values_list = list(cols_values_dict.keys()).index(col)
X_test[:, idx_col_training_data] = values[idx_in_values_list]
#compute probability of each sample
prob_dist = np.exp(kde.score_samples(X_test))/np.exp(kde.score_samples(X_test)).sum()
#sample using np.random.choice
return X_test[np.random.choice(range(len(prob_dist)), p=prob_dist, size = (samples))]
【讨论】:
解决部分问题的好方法,但不适用于所有问题。如果我理解正确,它适用于用离散网格探测 KDE,这会引入错误。此外,KDE 实际上可以沿轴推断超出最小和最大训练点,而这种方法无法做到。 确实为了更有效的条件采样,我们需要构建我认为的 pdf。遗憾的是,sklearn.kde 中没有 pdf 的实现,statsmodels.kde 中也没有采样的采样实现【参考方案2】:此函数适用于只有一维条件的用例。它的构建方式不需要完全满足条件,但有一定的容忍度。
from scipy import stats
import numpy as np
x = np.random.random(1000)
y = np.random.random(1000)
kde = stats.gaussian_kde([x,y])
def conditional_sample(kde, condition, precision = 0.5, sample_size = 1000):
block_size = int(sample_size / (2 * precision / 100))
sample = kde.resample(block_size)
lower_limit = np.percentile(sample[-1], stats.percentileofscore(sample[-1], condition) - precision)
upper_limit = np.percentile(sample[-1], stats.percentileofscore(sample[-1], condition) + precision)
conditional_sample = sample[:, (upper_limit > sample[-1]) * (sample[-1] > lower_limit)]
return conditional_sample[0:-1]
conditional_sample(kde=kde, condition=0.6)
不是通用解决方案,但对我的用例很有效。
【讨论】:
您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。以上是关于python中多元核密度估计的条件抽样的主要内容,如果未能解决你的问题,请参考以下文章