为什么'kd_tree'比'brute'需要更多的时间?

时间:2019-09-23 09:59:47

标签: python machine-learning scikit-learn

我正在用sklearn标定knn。这是系统信息。

系统信息

  • 英特尔®至强®L5640(6核12兄弟姐妹);
  • Ubuntu 18.04,Python 3.7.3,numpy 1.16.4,sklearn 0.21.2;
  • 没有其他作业/任务占用CPU核心。

数据集

该基准测试在sklearn MNIST上运行,它具有1797个样本,10个类,8 * 8维度和17个特征。

此样本图像中的每个正方形代表一个像素,总共8 * 8维度。每个像素的范围是0到16。

enter image description here

代码

这是代码。

snippet_1:

n_neighbors=5; n_jobs=1; algorithm = 'brute'
model = KNeighborsClassifier(n_neighbors=n_neighbors, n_jobs=n_jobs, algorithm = algorithm)
model.fit(trainData, trainLabels)
predictions = model.predict(testData)

大约需要0.1s

snippet_2:

n_neighbors=5; n_jobs=1; algorithm = 'kd_tree'
model = KNeighborsClassifier(n_neighbors=n_neighbors, n_jobs=n_jobs, algorithm = algorithm)
model.fit(trainData, trainLabels)
predictions = model.predict(testData)

大约需要0.2s

我多次重复执行基准测试,无论我先运行哪个,snippet_1总是比snippet_2快2倍。

问题

为什么'kd_tree'比'brute'需要更多的时间?

我知道“维数的诅咒”,因为doc清楚地说,我要问的是为什么

2 个答案:

答案 0 :(得分:0)

答案似乎与与模型相关的尺寸有关。维数的诅咒也是众所周知的。当KD-tree的尺寸超过15/20(kinda指数)时,缩放比例非常差,而蛮力似乎遵循了更线性的模式。在GPU上运行时,对于更大的尺寸,蛮力确实可以更快。在这里,另一位研究人员发现了类似的问题:Comparison search time between K-D tree and Brute-force

答案 1 :(得分:0)

通常,如果N < 2**k(其中k是维数(在这种情况下为8 * 8 = 64)中且N2**64 = 1.8E19 >> 1797,则KD-Tree的速度将比蛮力慢。样本数。在这种情况下,N < 2**k使得KDTree的运行速度慢得多。

基本上,作为第一步,KDTree沿每个维度对数据进行二进制拆分。如果它具有足够的数据来执行此操作,则可以根据它们共有的拆分数目来猜测最接近的邻居。如果为{ "header": { "serviceId":"xxx", "productCode":"xxx", "transactionId":"xxx" }, "data": { "items": [ { "paymentModel":"Retail Banking", "paymentChannels": [ { "name":"A", "status":"Active" }, { "name":"B", "status":"Active" }, { "name":"C", "status":"Active" }, { "name":"D", "status":"Active" } ], "name":"Internet Banking", "logoUrl":"xxx" }, { "paymentModel":"Retail Banking", "paymentChannels": [ { "bankFeeRate":"0", "ccIsRequired":true, "name":"R", "currency": [{ "isoCode":"xxx", "name":"xxx" }], "bankFeeType":"xxx", "paymentChannelId":"9", "status":"Active", "acceptedCard": [ "visa", "mastercard" ] }, { "bankFeeRate":"0", "ccIsRequired":true, "name":"M", "currency": [{ "isoCode":"xxx", "name":"xxx" }], "bankFeeType":"fixed", "paymentChannelId":"13", "status":"Active", "acceptedCard": [ "amex" ] } ], "name":"Credit Card", "logoUrl":"xxx" } ], "metadata": { "count":2 } }, "status": { "code":"200", "message":"OK" } } ,则数据用完之前将要用尽。这样就没有关于其他尺寸的距离信息。毫无疑问,它仍然必须蛮力对待其余维度,从而使KDTree不必要的开销。

可以更here找到有关问题和可能解决方案的更深入讨论。对于此应用程序,建议您首先使用PCA降低尺寸的第三个答案可能是最好的选择。