机器学习中的维度诅咒通常是在您拥有的几个数据点之间爆炸空白空间的问题。低流形数据会使情况变得更糟。这是一个包含 10000 个样本的示例设置,我尝试使用 1 个邻居进行 kNN。
from numpy.random import normal
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import precision_score
import matplotlib.pyplot as plt
import numpy as np
from math import sqrt
from scipy.special import gamma
N=10000
N_broad=2
scale=20
dims=[]
precs=[]
def avg_distance(k):
return sqrt(2)*gamma((k+1)/2)/gamma(k/2)
for dim in range(N_broad+1,30):
clf = KNeighborsClassifier(1, n_jobs=-1)
X_train=np.hstack([normal(size=(N,N_broad)), normal(size=(N,dim-N_broad))/avg_distance(dim-N_broad)/scale])
y_train=(X_train[:,N_broad]>0).astype(int)
clf.fit(X_train, y_train)
X_test=np.hstack([normal(size=(N,N_broad)), normal(size=(N,dim-N_broad))/avg_distance(dim-N_broad)/scale])
y_test=(X_test[:,N_broad]>0).astype(int)
y_test_pred=clf.predict(X_test)
prec=precision_score(y_test, y_test_pred)
dims.append(dim)
precs.append(prec)
print(dim, prec)
plt.plot(dims, precs)
plt.ylim([0.5,1])
plt.xlabel("Dimension")
plt.ylabel("Precision")
plt.title("kNN(1) on {} samples".format(N))
plt.show()
你不喜欢完全均匀的分布,所以我把它做成了一个 2D 流形,尺寸更小(由 减少scale
)散布在前两个坐标的 2D 平面周围。碰巧的是,较小的维度之一是可预测的(当该维度为正时,标签为 1)。
精度随着尺寸的增加而迅速下降。
当然,precision=0.5 将是随机猜测。有了比飞机更复杂的决策面,情况会变得更糟。
就像 kNN 球太稀疏,无法帮助探测光滑的超平面。随着更高的维度,他们感到越来越孤独。
另一方面,像 SVM 这样的方法具有全局视图并且做得更好。