【问题标题】:Custom metric in sklearnsklearn 中的自定义指标
【发布时间】:2019-03-26 14:51:21
【问题描述】:

我应该设计一个自定义指标,当应用于具有不同算法的 MNIST 时,其性能优于 L2。

from sklearn import neighbors

import utils
import math


# Extraction du dataset
x_train, y_train = utils.get_train_data()
x_test,  y_test  = utils.get_test_data()

def EuclideanDistance(x, y):
    return math.sqrt((y[0] - x[0]) ** 2 + (y[1] - x[1]) ** 2)

test_range = 10
test_results = []  # tableau d'enregistrements {nn: [uniform, distance]}

for k in range(test_range):  # will test all 'k' values from 2 to 'test_range + 1'
    n_neighbors = k+2
    print("\nTesting  k =", n_neighbors)
    error_rate = []
    for weights in ['uniform', 'distance']:
        knn_clf = neighbors.KNeighborsClassifier(n_neighbors,
                                                 metric=EuclideanDistance,
                                                 weights=weights)
        knn_clf.fit(x_train, y_train)
        predictions = knn_clf.predict(x_test)

        error_rate.append(utils.count_error_rate(predictions, y_test))

    test_results.append({n_neighbors: error_rate})

print("\nResults:", test_results)

这样做,我得到以下结果:

Testing  k = 2
Error rate =      91.58316633266533 %
Error rate =      91.58316633266533 %

Testing  k = 3
Error rate =      91.58316633266533 %
Error rate =      91.58316633266533 %

Testing  k = 4
Error rate =      91.58316633266533 %
Error rate =      91.58316633266533 %

...

这显然是错误的。为什么我的自定义指标应用于不同的上下文时会得到相同的输出?

【问题讨论】:

  • 您使用的“导入工具”是什么?看起来像是自制的东西。另一点是您没有显示您的数据。当您使用 k=2 k=3 和 k=4 时,是否有可能所有数据点都被分类为相同?
  • @FlorianH utils 用于加载只是 MNIST 的数据集。当我使用 sklearn 提供的内置欧几里得度量时,我得到了不同的结果,这帮助我得出结论 k=3 在这种情况下似乎是最好的。然后我想更好地了解如何尝试我自己的自定义指标,所以我从一个 euclidian 函数开始,但它为每个 k 提供了相同的结果。因此,我得出结论,我没有正确实施自定义指标。我的问题真的是:如何使用 sklearn 实现我自己的自定义指标?我找不到与此相关的文档。
  • 好吧,如果你使用 mnist,它是 28x28 = 784 像素的图片,你的 EuclideanDistance 函数只查看其中的前 2 个 x[0] 和 x[1]。所以你在计算中错过了 x[2] 到 x[783]?

标签: python-3.x machine-learning scikit-learn


【解决方案1】:

尝试使您的 EuclideanDistance 函数独立于输入数据的长度(您的函数仅查看 2 个组件,而不是 MNIST 中的 784 个维度):

def EuclideanDistance(x, y):
    if len(x) != len(y):
        raise ValueError("x and y need to have the same length")
    return math.sqrt(sum([(y[i] - x[i]) ** 2 for i in range(len(x))]))

*编辑您对效率的评论

如果您转到 pythons lib 文件夹(/site-packages/sklearn/metrics/pairwise.py),您可以看到自己是如何编写函数的。 但是函数内的注释指出:

出于效率原因,一对行之间的欧式距离
向量 x 和 y 计算为::

dist(x, y) = sqrt(dot(x, x) - 2 * dot(x, y) + dot(y, y))    

这个公式有两个优点 其他计算距离的方法。首先,它是计算的 处理稀疏数据时高效。第二,如果一个论点 变化,但另一个保持不变,然后 dot(x, x) 和/或 dot(y, y) 可以预先计算。

但是,这不是进行此计算的最精确方法, 并且此函数返回的距离矩阵可能不完全正确 根据例如scipy.spatial.distance 函数的要求对称。

【讨论】:

  • 我尝试了您的解决方案(并修复了您的缩进):到目前为止,它在大约 20 分钟内发现了 k=2 的错误率。 sklearn 如何具有相同的距离度量但结果更快?这太慢了。 :(
猜你喜欢
  • 2018-12-01
  • 1970-01-01
  • 2017-03-05
  • 2014-01-29
  • 2019-05-11
  • 2022-01-01
  • 2018-09-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多