我收集了512 D std::vector来存储面部嵌入。我创建索引并对数据子集执行培训。
int d = 512;
size_t nb = this->templates.size() // 95000
size_t nt = 50000; // training data size
std::vector<float> training_set(nt * d);
faiss::IndexFlatIP coarse_quantizer(d);
int ncentroids = int(4 * sqrt(nb)));
faiss::IndexIVFPQ index(&coarse_quantizer,d,ncentroids,4,8);
std::vector<float> training_set(nt*d);这个->模板有一个索引值,512维向量在1。我的问题是关于训练和索引。我现在有这样的情况:
int v=0;
for (auto const& element : this->templates)
{
std::vector<double> enrollment_template = element.second;
for (int i=0;i<d;i++){
training_set[(v*d)+i] = (float)enrollment_template.at(i);
v++;
}
index.train(nt,training_set.data());FAISS Index.Train函数
virtual void train(idx_t n, const float *x)
Perform training on a representative set of vectors
Parameters:
n – nb of training vectors
x – training vecors, size n * d这是将512 D矢量数据添加到Faiss中进行培训的正确方法吗?在我看来,如果我有2个大小为512 D的面嵌入,那么training_set应该是这样的:
训练_set0-511-面#1的512 D矢量训练_set0 512-1024-面#2's 512 D向量
由于Faiss知道我们正在处理512 D向量,所以它将智能地将它们从数组中解析出来。
发布于 2022-09-18 07:56:07
下面是一种更有效的编写方法:
int v = 0;
for (auto const& element : this->templates)
{
auto& enrollment_template = element.second; // not copy
if (v + d > training_set.size()) {
break; // prevent overflow, "nt" is smaller than templates.size()
}
for (int i = 0; i < d; i++) {
training_set[v] = enrollment_template[i]; // not at()
v++;
}
}我们避免使用auto& enrollment_template复制,避免使用enrollment_template[i]进行额外分支(您知道不会超出界限),并通过使v成为元素计数而不是行来简化training_set[v]的地址计算。
如果可以将templates更改为存储浮点数而不是双倍,则可以进一步提高效率--然后按位复制512浮点数,而不是将双浮点数转换为浮点数。
另外,一定要声明d为constexpr,以便给编译器优化循环的最佳机会。
https://stackoverflow.com/questions/73760093
复制相似问题