为什么相同数据的scipy.stats.gaussian_kde()比seaborn.kde_plot()慢?

时间:2018-03-13 21:17:43

标签: python scipy distribution seaborn gaussian

在python 3.7中,我有这个numpy数组,其shape =(2,34900)。此数组是坐标列表,其中索引0表示X轴,索引1表示y轴。

当我使用seaborn.kde_plot()来显示这些数据的分布时,我可以在i5第7代上运行时大约5-15秒获得结果。

但是当我尝试运行以下代码时:

#Find the kernel for 
k = scipy.stats.kde.gaussian_kde(data, bw_method=.3)
#Define the grid
xi, yi = np.mgrid[0:1:2000*1j, 0:1:2000*1j]
#apply the function
zi = k(np.vstack([xi.flatten(), yi.flatten()]))

找到此数据的高斯内核并将其应用于我定义的网格,需要更多时间。我无法运行完整的阵列,但是当在大小为140的切片上运行时,大约需要40秒才能完成。

140大小的切片确实产生了一个有趣的结果,我可以使用plt.pcolormesh()进行可视化。

我的问题是我在这里缺少的。如果我理解正确发生的事情,我会使用scipy.stats.kde.gaussian_kde()来创建数据定义的函数估计。然后我将该函数应用于2D空间并获得它的Z分量作为结果。然后我正在绘制Z分量。但是这个过程怎么会有所不同呢 seaborn.kde_plot()使代码花费的时间更长。

Scipy的实施只是经历了这一点:

for i in range(self.n):
    diff = self.dataset[:, i, newaxis] - points
    tdiff = dot(self.inv_cov, diff)
    energy = sum(diff*tdiff,axis=0) / 2.0
    result = result + exp(-energy)

2 个答案:

答案 0 :(得分:5)

Seaborn通常有两种计算二元kde的方法。如果可用,则使用# Example: # spark.master spark://master:7077 # spark.eventLog.enabled true # spark.eventLog.dir hdfs://namenode:8021/directory # spark.serializer org.apache.spark.serializer.KryoSerializer # spark.driver.memory 5g # spark.executor.extraJavaOptions -XX:+PrintGCDetails -Dkey=value -Dnumbers="one two three" spark.driver.extraClassPath /path/to/drivers/postgresql-9.4.1210.jre7.jar spark.executor.extraClassPath /path/to/drivers/postgresql-9.4.1210.jre7.jar spark.jars /path/to/drivers/postgresql-9.4.1210.jre7.jar ,如果不可用,则会回退到statsmodels

scipy代码与问题中显示的类似。它使用scipy.stats.gaussian_kde。 statsmodels代码使用statsmodels.nonparametric.api.KDEMultivariate

然而,对于公平的比较,我们需要为这两种方法采用相同的网格大小。 seaborn的标准网格是100分。

scipy

如果我们计算这两个函数,

import numpy as np; np.random.seed(42)
import seaborn.distributions as sd

N = 34900
x = np.random.randn(N)
y = np.random.randn(N)
bw="scott"
gridsize=100
cut=3
clip = [(-np.inf, np.inf), (-np.inf, np.inf)]

f = lambda x,y : sd._statsmodels_bivariate_kde(x, y, bw, gridsize, cut, clip)
g = lambda x,y : sd._scipy_bivariate_kde(x, y, bw, gridsize, cut, clip)
因此,Scipy的速度是statsmodels(seaborn默认值)的两倍。问题中的代码花费这么长时间的原因是,使用大小为2000的网格而不是大小为100的网格。

看到这些结果,人们实际上会想要使用scipy而不是statsmodels。不幸的是,它不允许选择使用哪一个。因此需要手动设置相应的标志。

# statsmodels
%timeit f(x,y)  # 1 loop, best of 3: 16.4 s per loop
# scipy
%timeit g(x,y)  # 1 loop, best of 3: 8.67 s per loop

答案 1 :(得分:-2)

似乎seaborn只是采集了我的数据样本。由于尺寸较小,因此可以少量完成。另一方面,SciPy使用其处理中的每一个点。因此,使用数据集I的大小需要更长的时间。