我正在尝试使用 k-最近邻分类器进行基于组的离开一个交叉验证 (LOOCV) 的泛化。标准 LOOCV 查找每个数据点的 k-最近邻,不包括点本身。在我的场景中,每个数据点除了其特征之外还与组变量 (如收集日期) 相关联。我想找到每个数据点的 k-最近邻,不包括同一组中的所有点 (例如,以获取
这是简单的实现(下面),但我正在寻找一个更清洁的解决方案,理想情况下几个标准库调用,这也是有效的,即利用 sklearn 的优化 NearestNeighbors 搜索像“球树”算法。
设置示例数据和导入库:
import pandas as pd
import numpy as np
from sklearn.neighbors import NearestNeighbors
np.random.seed(0)
group = pd.Series(['a', 'b', 'a', 'c', 'b', 'c'])
X = pd.DataFrame(np.random.rand(len(group), 2))
标准 LOOCV 所需的 k 最近邻可以通过单个库调用轻松计算:
# k nearest neighbor of query point, excluding query point
k = 2
nbrs = NearestNeighbors(n_neighbors=k)
nbrs.fit(X)
nbrs.kneighbors(return_distance=False)
但是找到基于组的排除的 k 最近邻居似乎需要迭代组,当有许多组时,这将是缓慢的:
# Inefficient for large number of groups: uses each group of data number_of_groups^2 times.
def kneighbors(X, group, k):
"""k nearest neighbors of each query point, excluding all points in query point's group."""
def kneighbors_group(g):
"""k nearest neighbors of all points in group g, excluding points in group g."""
Xg = X.loc[group==g, :]
Xnotg = X.loc[group!=g, :]
obj = NearestNeighbors(n_neighbors=min(k, Xnotg.shape[0])) # prevent number of neighbors from exceeding size of remaining data
obj.fit(Xnotg)
nbrs_notg_local = obj.kneighbors(X=Xg, return_distance=False) # locally indexed neighbors
nbrs_notg = [list(Xnotg.index[a]) for a in nbrs_notg_local] # globally indexed neighbors
return pd.Series(nbrs_notg, index=Xg.index)
# concatenate neighbors of each group and restore initial data order
return pd.concat([kneighbors_group(g) for g in group.unique()], axis=0).loc[X.index]
kneighbors(X, group, k)
我正在考虑的另一个选择是使用自定义距离度量,其中同一组中的点将被定义为具有距离无穷大。但我认为这在较大的数据集上太慢,因为它不能利用 sklearn 的高效搜索算法。
本站系公益性非盈利分享网址,本文来自用户投稿,不代表码文网立场,如若转载,请注明出处
评论列表(10条)