-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathget_knn.m
89 lines (82 loc) · 2.14 KB
/
get_knn.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
function [nnX,D,mu,sigma,idxtmp] = get_knn(X,dtype,K,NV)
arguments
X double
dtype char {mustBeMember(dtype,{'omega','norm','alen'})} = 'omega'
K(1,1) double {mustBePositive,mustBeInteger} = 1
NV.dispQ(1,1) logical = false
NV.ID = []
NV.Y = []
NV.skipself(1,1) logical = true
end
% GET_KNN k-nearest neighbor points, distances, mean, and std
%--------------------------------------------------------------------------
% Author(s): Sterling Baird
%
% Date: 2020-07-27
%
% Inputs:
% pts - rows of points (euclidean)
%
% dtype - distance type
%
% Outputs:
% creates a histogram figure
%
% Usage:
% pts = sqrt2norm(normr(rand(1000,8))); %octonion case (omega), input must have norm == sqrt(2)
% nnhist(pts)
%
% pts = nnhist(rand(1000,5)); % euclidean distance
% nnhist(pts)
%
% Dependencies:
% get_omega.m
%
% Notes:
% *
%--------------------------------------------------------------------------
%get nearest neighbor IDs and euclidean distances
ID = NV.ID;
Y = NV.Y;
skipselfQ = NV.skipself;
assert(isempty(ID) || isempty(Y),'ID and Y should not be supplied simultaneously')
if ~isempty(ID)
Y = X(ID,:);
elseif isempty(Y)
Y = X; %check NNs within set of points (otherwise check NN against specific pts in NV.Y)
end
if skipselfQ
[idxtmp,Dtmp] = knnsearch(X,Y,'K',K+1);
else
[idxtmp,Dtmp] = knnsearch(X,Y,'K',K);
end
%remove "self" column
if skipselfQ
idxtmp = idxtmp(:,2:end);
Dtmp = Dtmp(:,2:end);
end
%initialize
[mu,sigma] = deal(zeros(K,1));
D = cell(K,1);
for k = 1:K
idx = idxtmp(:,k);
%nearest neighbor pts
nnX = X(idx,:);
%get distances for plotting
switch dtype
case 'omega'
Drad = get_omega(nnX,Y);
D{k} = rad2deg(Drad);
case 'norm'
D{k} = Dtmp(:,k);
case 'alen' %general arc length formula
assert(norm(X(1,:))-1 < 1e-6,'norm(pts,2) must be 1 (within tol)')
Drad = real(acos(dot(nnX,Y,2)));
D{k} = rad2deg(Drad);
end
mu(k) = mean(D{k});
sigma(k) = std(D{k});
if NV.dispQ
disp(['nn: ' int2str(k) ', mu = ' num2str(mu(k)) ', sigma = ' num2str(sigma(k))])
end
end