我应该设计一个自定义指标,以不同的算法应用于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 %
...
这显然是错误的。为什么我的自定义指标应用于相同的上下文会得到相同的输出?
答案 0 :(得分:0)
尝试使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))]))
对您对效率的评论进行* EDIT
如果转到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
函数所要求的对称性。