在使用 Matlab 计算平均准确率召回率时无法找出数据库中的基本事实

Unable to figure out the ground truth databased in calculating the mean Average Precision Recall using Matlab

假设我有一个大小如下的数据集:

train = 500,000 * 960  %number of training samples (vector) each of 960 length

B_base = 1000000*960 %number of base samples  (vector) each of 960 length


Query = 1000*960  %number of query samples  (vector) each of 960 length

truth_nn = 1000*100

truth_nn 以 预先计算的 k 最近邻及其平方欧氏距离。因此,truth_nn 的列代表 k = 100 个最近的邻居。我发现很难在代码片段中应用最近邻搜索。有人可以展示如何应用基本事实邻居 truth_nn 来找到平均准确率吗?

如果有人可以通过创建任何数据矩阵、查询矩阵和以预先计算的 k 最近邻及其平方欧几里德距离的形式的地面实况邻居来展示任何小例子,那将是巨大的帮助。我尝试创建示例数据库。

假设,基础数据是

B_base = [1 1; 2 2; 3 2; 4 4; 5 6];

查询数据为

 Query = [1 1; 2 1; 6 2];

[neighbors distances] = knnsearch(a,b,'k',2);

会找到 2 个最近的邻居。

问题1:如何创建包含真值近邻和预先计算的k个最近邻距离的真值数据? 这称为平均准确率召回率。我尝试如下实施最近邻搜索和平均精度召回,但无法理解(不确定)如何应用基本事实 table

问题 2:

我正在尝试通过首先将实值特征转换为二进制来应用k最近邻搜索。

我无法对 k = 10,20,50 的不同值应用 k 最近邻搜索的概念,也无法检查使用 GIST 数据库正确调用了多少数据。在 GIST truth_nn() 文件中,当我为查询向量 i 指定 truth_nn(i,1:k) 时,函数 AveragePrecision 会抛出错误。因此,如果有人可以使用任何与 GIST 中具有相似结构的样本 ground truth 来展示如何正确指定 k 并计算平均精度召回率,那么我就可以将解决方案应用于 GIST 数据库。截至目前,这是我的方法,如果使用任何对我来说更容易与 GIST 数据库相关联的示例提供正确的方法,将会提供巨大的帮助。问题是如何从ground truth中找到邻居并将其与距离排序后获得的邻居进行比较?

我也对如何应用 pdist2() 而不是当前的距离计算很感兴趣,因为它需要很长时间。

 numQueryVectors = size(Query,1);
       %Calculate distances
     for i=1:numQueryVectors,
      queryMatrix(i,:)
      dist = sum((repmat(queryMatrix(i,:),numDataVectors,1)-B_base ).^2,2);
     [sortval sortpos] = sort(dist,'ascend');
      neighborIds(i,:) = sortpos(1:k);
     neighborDistances(i,:) = sqrt(sortval(1:k));
    end


        %Sorting calculated nearest neighbor distances for k = 50



 %HOW DO I SPECIFY k = 50 in the ground truth, truth_nn
for i=1:numQueryVectors
  AP(i) = AveragePrecision(neighborIds(i,:),truth_nn(i,:));
end
mAP = mean(AP);


  function ap = AveragePrecision(rank_id, truth_id)
    truth_num = length(truth_id);


truth_pos = zeros(truth_num,1);

for j=1:50  %% for k = 50 nearest neighbors
    truth_pos(j) = find(rank_id == truth_id(j));
end
truth_pos = sort(truth_pos, 'ascend');

% compute average precision as the area below the recall-precision curve
ap = 0;
delta_recall = 1/truth_num;
for j=1:truth_num
    p = j/truth_pos(j);
    ap = ap + p*delta_recall;
end

    end
end

更新: 根据解决方案,我尝试使用给定的公式 formula hereand a reference code 来计算平均精度。但是,不确定我的方法是否正确,因为理论上说我需要根据索引对返回的查询进行排名。我不完全理解这一点。判断检索算法的好坏需要平均精度。

precision = positives/total_data;
recal = positives /(positives+negatives);
precision = positives/total_data;
recall = positives /(positives+negatives);
truth_pos = sort(positives, 'ascend');
truth_num = length(truth_pos);

ap = 0;
delta_recall = 1/truth_num;
for j=1:truth_num
    p = j/truth_pos(j);
    ap = ap + p*delta_recall;
end
ap

ap = infinity 的值,positive = 0 和 negatives = 150 的值。这意味着 knnsearch() 根本不起作用。

我认为你在做额外的工作。这个过程在matlab中很简单,也可以对整个数组进行操作。这应该比 for 循环更快,并且更容易阅读。

如果没有错误,你的truth_nnneighbors应该有相同的数据。每行有一个条目。 Matlab 已经按升序对 kmeans 结果进行了排序,因此第 1 列是最近的邻居,第二近的是第 2 列,第三近的是 3,....不需要再次对数据进行排序。

只需比较 truth_nnneighbors 即可获得您的统计数据。这是一个简单的例子,向您展示程序应该如何进行。如果不进行一些修改,它将无法处理您的数据

%in your example this is provided, I created my own
truth_nn = [1,2;
            1,3;
            4,3];

B_base = [1 1; 2 2; 3 2; 4 4; 5 6];
Query = [1 1; 2 1; 6 2];

%performs k means
num_clusters = 2;
[neighbors distances] = knnsearch(B_base,Query,'k',num_clusters);

%--- output---
% neighbors = [1,2; 
%              1,2; notice this doesn't match truth_nn 1,3
%              4,3]
% distances = [     0    1.4142;
%              1.0000    1.0000;
%              2.8284    3.0000];

%computes statistics, nnz counts number of nonzero elements, in the first
%case every piece of data that matches 
%NOTE1: the indexing on truth_nn (:,1:num_clusters ) it says all rows
%       but only use the first num_clusters columns. This should
%       prevent the dimension mistmatch error you were getting
positives = nnz(neighbors == truth_nn(:,1:num_clusters ));     %result = 5
negatives = nnz(neighbors ~= truth_nn(:,1:num_clusters ));     %result = 1
%NOTE1: I've switched this from truth_nn to neighbors, this helps
%       when you cahnge num_neghbors 
total_data = numel(neighbors);               %result = 6

percent_incorrect = 100*(negatives / total_data);   % 16.6666
percent_correct   = 100*(positives / total_data);   % 93.3333