一等一网站,成都做网络推广的公司有哪些,门户网站价格,wordpress 文字背景训练过程
通过gdb调试得到这个ivfsq的训练过程#xff0c;我尝试对这个内容具体训练过程进行解析#xff0c;对每个调用栈里面的逻辑和代码进行解读。
步骤函数名称调用位置说明1faiss::IndexIVF::train/faiss/IndexIVF.cpp:1143开始训练#xff0c;判断是否需要训练第一级…训练过程
通过gdb调试得到这个ivfsq的训练过程我尝试对这个内容具体训练过程进行解析对每个调用栈里面的逻辑和代码进行解读。
步骤函数名称调用位置说明1faiss::IndexIVF::train/faiss/IndexIVF.cpp:1143开始训练判断是否需要训练第一级量化器调用 train_q1。2faiss::Level1Quantizer::train_q1/faiss/IndexIVF.cpp:56训练第一级量化器创建聚类器 Clustering并调用其 train 方法进行训练。3faiss::Clustering::train/faiss/Clustering.cpp:81使用输入数据 x 和聚类索引进行聚类训练生成聚类中心。4faiss::IndexIVF::train_residual/faiss/IndexScalarQuantizer.cpp:139训练残差部分调用 ScalarQuantizer::train_residual 计算残差向量并训练标量量化器。5faiss::ScalarQuantizer::train_residual/faiss/impl/ScalarQuantizer.cpp:1124对输入数据进行预处理如采样计算残差向量后调用 train 方法完成训练。6faiss::ScalarQuantizer::train/faiss/impl/ScalarQuantizer.cpp:1081根据量化器类型调用 train_NonUniform 或其他方法完成具体量化器的训练。7train_NonUniform/faiss/impl/ScalarQuantizer.cpp:572为每个维度的量化器计算范围如 vmin 和 vmax根据指定的范围统计方法如 RS_meanstd完成训练。8std::vector::resize/usr/include/c/14/bits/stl_vector.h:1015为量化器的训练结果分配内存调整 std::vector 的大小以容纳训练结果。9train_NonUniform/faiss/impl/ScalarQuantizer.cpp:1097计算每个维度的最小值 vmin 和最大值 vmax并将训练结果存储在 trained 向量中。
具体的流程如下
解析IndexIVF.cpp:1143文件中的train函数
作为IndexIVFScalarQuantizer数据结构的第一个变脸index1所调用的函数train需要去了解其如何去训练所存在的数据查看具体的流程是什么样子的
faiss::IndexFlatL2 quantizer1(d); // the other indexfaiss::IndexIVFScalarQuantizer index1(quantizer1, d, nlist, faiss::ScalarQuantizer::QT_8bit);index1.sq.rangestat faiss::ScalarQuantizer::RS_meanstd;index1.train(nb, xb); //调用的第一个函数从gdb的调用栈里面发现其首先调用的就是IndexIVF.cpp文件里面的第1143行的train函数代码如下
void IndexIVF::train(idx_t n, const float* x) {if (verbose) {printf(Training level-1 quantizer\n);}train_q1(n, x, verbose, metric_type);if (verbose) {printf(Training IVF residual\n);}// optional subsamplingidx_t max_nt train_encoder_num_vectors();if (max_nt 0) {max_nt (size_t)1 35;}TransformedVectors tv(x, fvecs_maybe_subsample(d, (size_t*)n, max_nt, x, verbose));if (by_residual) {std::vectoridx_t assign(n);quantizer-assign(n, tv.x, assign.data());std::vectorfloat residuals(n * d);quantizer-compute_residual_n(n, tv.x, residuals.data(), assign.data());train_encoder(n, residuals.data(), assign.data());} else {train_encoder(n, tv.x, nullptr);}is_trained true;
}现在对这里面的内容进行解读
打印训练状态
if (verbose) {printf(Training level-1 quantizer\n);
}
train_q1(n, x, verbose, metric_type);作用检查是否开启 verbose调试输出如果是打印量化器训练的信息。verbose的来自于Index数据结构然后IndexIVF继承了IndexIndexIVFInterface两个类IndexIVF : Index, IndexIVFInterface核心函数train_q1训练一级量化器。 n训练数据的数量。x训练数据float 指针表示数据的起始地址。verbose控制是否输出详细信息。metric_type度量类型可能决定了用什么距离计算方法比如欧几里得或余弦距离。
训练 IVF 残差
if (verbose) {printf(Training IVF residual\n);
}作用如果启用了调试模式打印残差训练的日志信息。
可选的下采样
idx_t max_nt train_encoder_num_vectors();
if (max_nt 0) {max_nt (size_t)1 35;
}
TransformedVectors tv(x, fvecs_maybe_subsample(d, (size_t*)n, max_nt, x, verbose));train_encoder_num_vectors获取训练数据的最大数量 max_nt。如果返回值小于等于 0则默认设置为一个非常大的值2^35也就是34,359,738,368。fvecs_maybe_subsample对输入数据 x 进行采样可能会减少训练数据的数量根据 max_nt。 参数 d特征的维度。参数 (size_t*)n更新后的训练样本数量指针。参数 verbose控制是否输出调试信息。 TransformedVectors 是一个简单的 RAII 类型资源管理器专注于浮点数组的管理。它通过成员变量 own_x 确定是否需要释放 x 的内存构造函数和析构函数一起保证资源管理的安全性。适合用于数据变换或动态内存场景帮助减少显式的 delete[] 调用降低内存管理的复杂性。如果这里面fvecs_maybe_subsample返回的结果和TransformedVectors数据结构上的x相同那么就会释放原来多余的内存如果构建采取的数据样本大于max_nt那么就会选择里面的随机采样的数据。 fvecs_maybe_subsample对输入数据集进行可选的下采样并返回下采样后的数据。如果输入数据集的大小超过了指定的最大数量 (nmax)它会随机选择一部分数据nmax 个样本进行下采样如果数据集大小在范围内则直接返回原始数据。 size_t d, // 数据的维度每个样本的特征数size_t* n, // 输入数据的样本数量指针函数可能会修改该值size_t nmax, // 数据集允许的最大样本数量const float* x, // 输入数据样本集每个样本有 d 个 float 特征bool verbose, // 是否打印详细信息int64_t seed // 随机数种子用于确保采样结果可重复
根据模式处理残差或原始数据
if (by_residual) {std::vectoridx_t assign(n);quantizer-assign(n, tv.x, assign.data());- by_residual一个布尔值表示是否使用残差训练。如果为 true执行残差计算流程
1. assign里面就是按照n的大小进行分配大概分配的大小就是k*nk为邻居的数量。quantizer-assign为每个训练样本分配一个量化器中心点即将每个点分配到一个簇。- n训练样本数量10w个。- tv.x训练数据。- assign.data()分配结果的存储位置一个大小为 n 的向量。assign 向量存储每个输入向量的分配结果例如所属簇的索引。std::vectorfloat residuals(n * d);quantizer-compute_residual_n(n, tv.x, residuals.data(), assign.data());2. quantizer-compute_residual_n计算残差。
- 残差是样本和分配中心点之间的差值。
- 存储在 residuals 数组中。train_encoder(n, residuals.data(), assign.data());3. train_encoder使用残差数据和分配结果训练编码器。原始数据训练
} else {train_encoder(n, tv.x, nullptr);
}如果 by_residual 为 false直接用原始数据进行编码器训练不使用分配结果。
标记训练完成
is_trained true;将 is_trained 标记为 true表示训练已经完成。
核心逻辑总结
函数接收高维训练数据 x并根据配置by_residual选择 使用残差方法训练量化器和编码器。或直接对原始数据进行训练。 支持下采样、量化器分配、残差计算等多种预处理。用途广泛适用于构建高效的倒排文件索引以加速高维数据的检索。
函数调用流程图
train ├── train_q1 ├── fvecs_maybe_subsample │ └── TransformedVectors ├── by_residual ? │ ├── quantizer-assign │ ├── quantizer-compute_residual_n │ └── train_encoder (using residuals) └── train_encoder (using original data)