我有一个x,y
点分布,我从中获得了KDE
到scipy.stats.gaussian_kde。这是我的代码以及输出的外观(x,y
数据可以从here获得):
import numpy as np
from scipy import stats
# Obtain data from file.
data = np.loadtxt('data.dat', unpack=True)
m1, m2 = data[0], data[1]
xmin, xmax = min(m1), max(m1)
ymin, ymax = min(m2), max(m2)
# Perform a kernel density estimate (KDE) on the data
x, y = np.mgrid[xmin:xmax:100j, ymin:ymax:100j]
positions = np.vstack([x.ravel(), y.ravel()])
values = np.vstack([m1, m2])
kernel = stats.gaussian_kde(values)
f = np.reshape(kernel(positions).T, x.shape)
# Define the number that will determine the integration limits
x1, y1 = 2.5, 1.5
# Perform integration?
# Plot the results:
import matplotlib.pyplot as plt
# Set limits
plt.xlim(xmin,xmax)
plt.ylim(ymin,ymax)
# KDE density plot
plt.imshow(np.rot90(f), cmap=plt.cm.gist_earth_r, extent=[xmin, xmax, ymin, ymax])
# Draw contour lines
cset = plt.contour(x,y,f)
plt.clabel(cset, inline=1, fontsize=10)
plt.colorbar()
# Plot point
plt.scatter(x1, y1, c='r', s=35)
plt.show()
坐标为(x1, y1)
的红点(与2D图中的每个点一样)具有f
(内核或KDE
)在0和0.42之间给出的关联值。我们说f(x1, y1) = 0.08
。
我需要将f
与x
和y
中的集成限制进行整合,其中f
评估的区域为 less 而不是{{} 1}},即:f(x1, y1)
。
对于我所看到的f(x, y)<0.08
可以通过数值积分执行函数和一维数组的集成,但我还没有看到任何可以让我执行数值积分的东西一个二维数组(python
内核)此外,我不确定如何识别该特定条件给出的区域(即:f
小于给定值)
这可以完成吗?
答案 0 :(得分:6)
这是使用monte carlo集成的方法。它有点慢,解决方案中存在随机性。误差与样本大小的平方根成反比,而运行时间与样本大小成正比(样本大小是指monte carlo样本(在我的示例中为10000),而不是数据集的大小)。以下是使用kernel
对象的一些简单代码。
#Compute the point below which to integrate
iso = kernel((x1,y1))
#Sample from your KDE distribution
sample = kernel.resample(size=10000)
#Filter the sample
insample = kernel(sample) < iso
#The integral you want is equivalent to the probability of drawing a point
#that gets through the filter
integral = insample.sum() / float(insample.shape[0])
print integral
我得到大约0.2作为数据集的答案。
答案 1 :(得分:1)
直接的方法是integrate
import matplotlib.pyplot as plt
import sklearn
from scipy import integrate
import numpy as np
mean = [0, 0]
cov = [[5, 0], [0, 10]]
x, y = np.random.multivariate_normal(mean, cov, 5000).T
plt.plot(x, y, 'o')
plt.show()
sample = np.array(zip(x, y))
kde = sklearn.neighbors.KernelDensity().fit(sample)
def f_kde(x,y):
return np.exp((kde.score_samples([[x,y]])))
point = x1, y1
integrate.nquad(f_kde, [[-np.inf, x1],[-np.inf, y1]])
问题是,如果你大规模地这样做,这是非常慢的。例如,如果要在x(0,100)处绘制x,y
行,则需要很长时间才能计算。
注意:我使用kde
中的sklearn
,但我相信您也可以将其更改为其他形式。
使用原始问题中定义的kernel
:
import numpy as np
from scipy import stats
from scipy import integrate
def integ_func(kde, x1, y1):
def f_kde(x, y):
return kde((x, y))
integ = integrate.nquad(f_kde, [[-np.inf, x1], [-np.inf, y1]])
return integ
# Obtain data from file.
data = np.loadtxt('data.dat', unpack=True)
# Perform a kernel density estimate (KDE) on the data
kernel = stats.gaussian_kde(data)
# Define the number that will determine the integration limits
x1, y1 = 2.5, 1.5
print integ_func(kernel, x1, y1)
答案 2 :(得分:0)
当前可用
kernel.integrate_box([-np.inf,-np.inf], [2.5,1.5])