主要内容

knnsearch

使用输入数据查找 k 最近邻点

说明

Idx = knnsearch(X,Y)X 中为 Y 中的每个查询点查找最近邻点,并在 Idx(一个列向量)中返回最近邻点的索引。Idx 的行数与 Y 的行数相同。

示例

Idx = knnsearch(X,Y,Name,Value) 返回 Idx,并使用一个或多个名称-值对组参量指定其他选项。例如,您可以指定要搜索的最近邻点的数量以及在搜索中使用的距离度量。

示例

[Idx,D] = knnsearch(___) 还使用上述语法中的任何输入参量额外返回矩阵 DD 包含 Y 中每个观测值与 X 中对应的最接近观测值之间的距离。

示例

示例

全部折叠

根据年龄和体重,在 hospital 数据集中找到与 Y 中的患者最相似的患者。

加载 hospital 数据集。

load hospital;
X = [hospital.Age hospital.Weight];
Y = [20 162; 30 169; 40 168; 50 170; 60 171];   % New patients

XY 之间执行 knnsearch 以找到最近邻点的索引。

Idx = knnsearch(X,Y);

X 中找到与 Y 中患者的年龄和体重最接近的患者。

X(Idx,:)
ans = 5×2

    25   171
    25   171
    39   164
    49   170
    50   172

X 中找到与 Y 中每个点最接近的 10 个最近邻点,首先使用闵可夫斯基距离度量,然后使用切比雪夫距离度量。

加载费舍尔鸢尾花数据集。

load fisheriris
X = meas(:,3:4);    % Measurements of original flowers
Y = [5 1.45;6 2;2.75 .75];  % New flower data

使用闵可夫斯基距离度量和切比雪夫距离度量,在 X 和查询点 Y 之间执行 knnsearch

[mIdx,mD] = knnsearch(X,Y,'K',10,'Distance','minkowski','P',5);
[cIdx,cD] = knnsearch(X,Y,'K',10,'Distance','chebychev');

可视化两个最近邻搜索的结果。绘制训练数据。用标记 X 绘制查询点。使用圆圈表示闵可夫斯基最近邻点。使用五角星表示切比雪夫最近邻点。

gscatter(X(:,1),X(:,2),species)
line(Y(:,1),Y(:,2),'Marker','x','Color','k',...
   'Markersize',10,'Linewidth',2,'Linestyle','none')
line(X(mIdx,1),X(mIdx,2),'Color',[.5 .5 .5],'Marker','o',...
   'Linestyle','none','Markersize',10)
line(X(cIdx,1),X(cIdx,2),'Color',[.5 .5 .5],'Marker','p',...
   'Linestyle','none','Markersize',10)
legend('setosa','versicolor','virginica','query point',...
'minkowski','chebychev','Location','best')

Figure contains an axes object. The axes object contains 6 objects of type line. One or more of the lines displays its values using only markers These objects represent setosa, versicolor, virginica, query point, minkowski, chebychev.

创建两个由点组成的大型矩阵,然后测量 knnsearch 采用默认的 "euclidean" 距离度量时所用的时间。

rng default % For reproducibility
N = 10000;
X = randn(N,1000);
Y = randn(N,1000);
Idx = knnsearch(X,Y); % Warm up function for more reliable timing information
tic
Idx = knnsearch(X,Y);
standard = toc
standard = 
25.3805

接下来,测量 knnsearch 采用 "fasteuclidean" 距离度量时所用的时间。指定缓存大小为 100。

Idx2 = knnsearch(X,Y,Distance="fasteuclidean",CacheSize=100); % Warm up function
tic
Idx2 = knnsearch(X,Y,Distance="fasteuclidean",CacheSize=100);
accelerated = toc
accelerated = 
2.4388

计算加速后的计算比标准计算快多少倍。

standard/accelerated
ans = 
10.4071

对于此示例,加速版本快三倍以上。

输入参数

全部折叠

输入数据,指定为数值矩阵。X 的行对应于各个观测值,列对应于各个变量。

数据类型: single | double

查询点,指定为数值矩阵。Y 的行对应于各个观测值,列对应于各个变量。Y 的列数必须与 X 的列数相同。

数据类型: single | double

名称-值参数

全部折叠

将可选参量对组指定为 Name1=Value1,...,NameN=ValueN,其中 Name 是参量名称,Value 是对应的值。名称-值参量必须出现在其他参量之后,但对各个参量对组的顺序没有要求。

如果使用的是 R2021a 之前的版本,请使用逗号分隔每个名称和值,并用引号将 Name 引起来。

示例: knnsearch(X,Y,'K',10,'IncludeTies',true,'Distance','cityblock') 搜索 10 个最近邻点,包括结值,并使用城市街区距离。

要在 X 中为 Y 中的每个点求出的最近邻点的数量,指定为由 'K' 和一个正整数组成的以逗号分隔的对组。

示例: 'K',10

数据类型: single | double

包括所有与查询点距离相同的最近邻点的标志,指定为由 'IncludeTies'false (0) 或 true (1) 组成的以逗号分隔的对组。

如果 'IncludeTies'false,则 knnsearch 在距查询点相同距离的观测值中选择索引最小的观测值。

如果 'IncludeTies'true,则:

  • knnsearch 包括距离等于输出参量中第 k 个最小距离的所有最近邻点。要指定 k,请使用 'K' 名称-值对组参量。

  • IdxDm×1 元胞数组,其中每个元胞包含一个向量,该向量中有至少 k 个索引和距离。D 中的每个向量包含按升序排列的距离。Idx 中的每行包含与 D 中的距离对应的最近邻点的索引。

示例: 'IncludeTies',true

最近邻搜索方法,指定为由 'NSMethod' 和以下值之一组成的以逗号分隔的对组。

  • 'kdtree' - 创建并使用 Kd 树来查找最近邻。当 X 中的列数小于或等于 10,X 不是稀疏值,并且距离度量是 'euclidean''cityblock''chebychev''minkowski' 时,'kdtree' 为默认值。否则,默认值为 'exhaustive'

    仅当距离度量是上述四个度量之一时,值 'kdtree' 才有效。

  • 'exhaustive' - 使用穷举搜索算法,方法是计算从 X 中的所有点到 Y 中每个点的距离值。

示例: 'NSMethod','exhaustive'

knnsearch 使用的距离度量,指定为下表中的值之一,或指定为函数句柄。

描述
'euclidean'欧几里德距离
'seuclidean'标准化的欧几里德距离。X 中的行与查询矩阵 Y 之间的每个坐标差会除以根据 X 计算的标准差的对应元素进行缩放。要指定不同的缩放,请使用 'Scale' 名称-值参量。
'fasteuclidean'当预测变量的数目至少为 10 时,使用替代算法计算的欧几里德距离,该算法可以节省时间。在某些情况下,这种更快的算法会降低准确度。此距离度量仅当 NSMethod'exhaustive' 时可用。以 'fast' 开头的算法不支持稀疏数据。有关详细信息,请参阅算法
'fastseuclidean'当预测变量的数目至少为 10 时,使用替代算法计算的标准化的欧几里德距离,该算法可以节省时间。在某些情况下,这种更快的算法会降低准确度。此距离度量仅当 NSMethod'exhaustive' 时可用。以 'fast' 开头的算法不支持稀疏数据。有关详细信息,请参阅算法
'cityblock'城市街区距离
'chebychev'切比雪夫距离(最大坐标差)
'minkowski'闵可夫斯基距离。默认指数是 2。要指定不同的指数,请使用 'P' 名称-值参量。
'mahalanobis'马氏距离,使用正定协方差矩阵计算。要更改协方差矩阵的值,请使用 'Cov' 名称-值参量。
'cosine'1 减去观测值(视为向量)之间夹角的余弦值
'correlation'1 减去观测值(视为值序列)之间的样本线性相关系数
'spearman'1 减去样本观测值(视为值序列)之间的斯皮尔曼秩相关
'hamming'汉明距离,即相异坐标所占的百分比
'jaccard'1 减去杰卡德系数,即非零相异坐标所占的百分比

您也可以通过使用 @(例如 @distfun)为自定义距离度量指定函数句柄。自定义距离函数必须:

  • 具有 function D2 = distfun(ZI,ZJ) 形式。

  • 接受以下参量:

    • n 向量 ZI,该向量包含来自 X 或查询点 Y 的单个行。

    • m2×n 矩阵 ZJ,该矩阵包含 XY 的多行。

  • 返回 m2×1 距离向量 D2,该距离向量的第 j 个元素是观测值 ZIZJ(j,:) 之间的距离。

有关详细信息,请参阅Distance Metrics

示例: 'Distance','chebychev'

数据类型: char | string | function_handle

格拉姆矩阵的大小,以 MB 为单位,指定为正标量或 "maximal"。仅当 Distance 名称-值参量以 fast 开头且 NSMethod 名称-值参量设置为 'exhaustive' 时,knnsearch 函数才能使用 CacheSize

如果您将 CacheSize 设置为 "maximal"knnsearch 会尝试为大小为 MX×MY 的整个中间矩阵分配足够的内存,其中 MX 是输入数据 X 的行数,MY 是输入数据 Y 的行数。高速缓存的大小不必大到足以容纳整个中间矩阵,但必须至少大到足以容纳一个 MX×1 向量。否则,knnsearch 使用标准算法来计算欧几里德距离。

如果 Distance 参量的值以 fast 开头,NSMethod 的值为 'exhaustive',而 CacheSize 的值太大或为 "maximal",则 knnsearch 可能会尝试分配超出可用内存的格拉姆矩阵。在这种情况下,MATLAB® 会引发错误。

示例: CacheSize="maximal"

数据类型: double | char | string

闵可夫斯基距离度量的指数,指定为由 'P' 和一个正标量组成的以逗号分隔的对组。

仅当 'Distance''minkowski' 时,此参量才有效。

示例: 'P',3

数据类型: single | double

马氏距离度量的协方差矩阵,指定为由 'Cov' 和一个正定矩阵组成的以逗号分隔的对组。

仅当 'Distance''mahalanobis' 时,此参量才有效。

示例: 'Cov',eye(4)

数据类型: single | double

标准化欧几里德距离度量的尺度参数值,指定为由 'Scale' 和一个非负数值向量组成的以逗号分隔的对组。'Scale' 的长度等于 X 中的列数。当 knnsearch 计算标准化欧几里德距离时,X 的每个坐标由 'Scale' 的对应元素缩放,每个查询点也是如此。仅当 'Distance''seuclidean' 时,此参量才有效。

示例: 'Scale',quantile(X,0.75) - quantile(X,0.25)

数据类型: single | double

Kd 树的叶节点中的最大数据点数,指定为由 'BucketSize' 和一个正整数组成的以逗号分隔的对组。仅当 NSMethod'kdtree' 时,此参量才有效。

示例: 'BucketSize',20

数据类型: single | double

根据距离对返回的索引进行排序的标志,指定为由 'SortIndices'true (1) 或 false (0) 组成的以逗号分隔的对组。

为了提高性能,当以下条件成立时,您可以将 SortIndices 设置为 false

  • Y 包含很多观测值,并且这些观测值在 X 中有许多最近邻点。

  • NSMethod'kdtree'

  • IncludeTiesfalse

在这种情况下,knnsearch 返回的最近邻点索引没有特定顺序。当 SortIndicestrue 时,函数按距离以升序排列最近邻点索引。

SortIndices 默认为 true。当 NSMethod'exhaustive'IncludeTiestrue 时,函数始终会对索引进行排序。

示例: 'SortIndices',false

数据类型: logical

输出参量

全部折叠

最近邻点的输入数据索引,以数值矩阵或数值向量的元胞数组形式返回。

  • 如果您不指定 IncludeTies(默认为 false),则 Idx 是一个 m×k 数值矩阵,其中 mY 的行数,k 是搜索到的最近邻点数量。Idx(j,i) 表示 X(Idx(j,i),:)X 中最接近查询点 Y(j,:)k 个观测值之一。

  • 如果您指定 'IncludeTies',true,则 Idx 是一个 m×1 元胞数组,其中元胞 j (Idx{j}) 包含一个向量,该向量中有至少 k 个索引,对应 X 中与查询点 Y(j,:) 最接近的观测值。

如果 SortIndicestrue,则 knnsearch 按距离以升序排列索引。

最近邻点到查询点的距离,以数值矩阵或数值向量的元胞数组形式返回。

  • 如果您不指定 IncludeTies(默认为 false),则 D 是一个 m×k 数值矩阵,其中 mY 的行数,k 是搜索到的最近邻点的数量。D(j,i)X(Idx(j,i),:)Y(j,:) 之间的距离(基于指定的距离度量)。

  • 如果您指定 'IncludeTies',true,则 D 是一个 m×1 元胞数组,其中元胞 j (D{j}) 包含一个向量,该向量中有至少 k 个距离,对应 X 中与查询点 Y(j,:) 最接近的观测值。

如果 SortIndicestrue,则 knnsearch 按升序排列距离。

提示

  • 对于固定正整数 kknnsearchX 中找到 k 个最接近 Y 中每个点的点。要找到 X 中在固定距离内接近 Y 中每个点的所有点,请使用 rangesearch

  • knnsearch 不保存搜索对象。要创建一个搜索对象,请使用 createns

算法

全部折叠

有关特定搜索算法的信息,请参阅 k-Nearest Neighbor Search and Radius Search

替代功能

如果您将 knnsearch 函数的 'NSMethod' 名称-值对组参量设置为合适的值('exhaustive' 用于穷举搜索算法,或 'kdtree' 用于 Kd 树算法),则搜索结果等效于使用 knnsearch 对象函数进行距离搜索得到的结果。与 knnsearch 函数不同,knnsearch 对象函数需要 ExhaustiveSearcherKDTreeSearcher 模型对象。

Simulink 模块

要将 k 最近邻搜索集成到 Simulink® 中,您可以使用 Statistics and Machine Learning Toolbox™ 库中的 KNN Search 模块或具有 knnsearch 函数的 MATLAB Function 模块。有关示例,请参阅Predict Class Labels Using MATLAB Function Block

在决定要使用的方法时,请考虑以下因素:

  • 如果使用 Statistics and Machine Learning Toolbox 库模块,可以使用定点工具 (Fixed-Point Designer)将浮点模型转换为定点。

  • 必须为具有 knnsearch 函数的 MATLAB Function 模块启用对可变大小数组的支持。

参考

[1] Friedman, J. H., J. Bentley, and R. A. Finkel. “An Algorithm for Finding Best Matches in Logarithmic Expected Time.” ACM Transactions on Mathematical Software 3, no. 3 (1977): 209–226.

扩展功能

全部展开

版本历史记录

在 R2010a 中推出

全部展开