【发布时间】:2020-01-15 18:52:54
【问题描述】:
所以这是场景。我有一个未排序的数组(非常大),名为 gallery,其中包含成对的模板 (std::vector<uint8_t>) 及其关联的 ID (std::string)。
我有一个函数,其中为我提供了一个模板,并且必须返回我的画廊中最相似的k 模板的 ID(我使用余弦相似度来生成模板之间的相似度分数)。
我考虑过使用this post 中讨论的堆。
但是,问题是图库可以包含属于单个 ID 的多个不同模板。在我的函数中,我必须返回 k unique ID。
对于上下文,我正在做一个面部识别应用程序。我的画廊中可以有多个不同的模板属于一个人(该人使用多个不同的图像在画廊中注册,因此多个模板属于他们的 ID)。搜索功能应将k 最相似的人返回到提供的模板(因此不会多次返回相同的 ID)。
希望有一种在 C++ 中执行此操作的有效算法。
编辑:为我提出的堆解决方案代码截断(不能正确处理重复项)
std::priority_queue<std::pair<double, std::string>, std::vector<std::pair<double, std::string> >, std::greater<> > queue;
for(const auto& templPair : m_gallery) {
try{
double similairty = computeSimilarityScore(templPair.templ, idTemplateDeserial);
if (queue.size() < candidateListLength) {
queue.push(std::pair<double, std::string>(similairty, templPair.id));
} else if (queue.top().first < similairty) {
queue.pop();
queue.push(std::pair<double, std::string>(similairty, templPair.id));
}
} catch(...) {
std::cout << "Unable to compute similarity\n";
continue;
}
}
// CandidateListLength number of IDs with the highest scores will be in queue
这是一个示例,希望对您有所帮助。为了简单起见,我假设已经为模板计算了相似度分数。
模板1:相似度得分:0.4,ID:Cyrus
模板 2:相似度得分:0.5,ID:James
模板 3:相似度得分:0.9,ID:Bob
模板 4:相似度得分:0.8,ID:Cyrus
模板 5:相似度得分:0.7,ID:Vanessa
模板 6:相似度得分:0.3,ID:Ariana
获取前 3 个评分模板的 ID 将返回 [Bob, Cyrus, Vanessa]
【问题讨论】:
-
使用最大堆而不是丢弃顶部 ID,将它们放入
std::set并继续直到您的集合的size()为k? -
所以如果我把 ID 放在一个集合中,它会告诉我 ID 是否已经在最大堆中,这很好。但是,我还需要修改队列中给定 ID 的得分值(假设新的相似度得分大于队列中已有的相似度得分)。
-
我不太明白。您在问题中说您有一对 value 和一个 ID。您有一个描述两个 值 之间相似性的函数,可用于对元素进行排序。您说您要检索与最相似的 value 对应的唯一 ID 的
k。您在哪里提到您需要更改一些数据?无论如何,您可以使用std::map而不是std::set,将 IDs 作为 keys 并将指向您的对的指针作为 values,但是假设我正确理解了你。您能否提供一个示例输入和输出? -
在这种情况下输出仍然是相同的 [Bob, Cyrus, Vanessa](按此顺序)
-
那么我相信我的第一条评论提出了一个正确的解决方案。如果没有人在 ~24 小时内给你一个满意的答案,我会尽力想出我自己的。
标签: c++ arrays algorithm optimization max