文件 ProductQuantizer.h

namespace faiss

使用多种变体的 k-means 聚类的实现。

版权所有 (c) Facebook, Inc. 及其附属公司。

此源代码根据 MIT 许可证获得许可,该许可证位于此源树的根目录中的 LICENSE 文件中。

IDSelector 旨在定义要处理的向量子集(用于删除或作为搜索的子集)

PQ4 SIMD 打包和累加函数

基本内核使用 bbs = nb * 2 * 16 个向量累加 nq 个查询向量,并生成该向量的输出矩阵。 对于 nq * nb <= 4 来说,它很有意义,否则寄存器溢出太大。

这些函数的实现分布在 3 个 cpp 文件中,以减少并行编译时间。 模板被显式实例化。

此文件包含用于计算距离的内核的回调。

在整个库中,向量以 float * 指针的形式提供。 当一起批量处理(添加/搜索)多个向量时,大多数算法都可以得到优化。 在这种情况下,它们作为矩阵传递。 当大小为 d 的 n 个向量以 float * x 的形式提供时,向量 i 的分量 j 为

x[ i * d + j ]

其中 0 <= i < n 且 0 <= j < d。 换句话说,矩阵始终是紧凑的。 指定矩阵的大小时,我们将其称为 n*d 矩阵,这意味着行主存储。

I/O 函数可以读取/写入文件名、文件句柄或抽象介质的对象。

读取函数返回的对象应该用 delete 释放。 这些对象中的所有引用都归该对象所有。

反向列表的定义 + 实现该接口的一些常用类。

由于 IVF(反向文件)索引对于大规模用例非常有用,因此我们将与它们相关的一些函数分组到这个小型库中。 大多数函数都适用于 IndexIVF 和嵌入在 IndexPreTransform 中的 IndexIVF。

此文件中实现了 L2 和内积之外的额外度量

实现了一些神经网络层,主要用于支持 QINCo

定义了一些将转换应用于一组向量的对象。通常这些是预处理步骤。

变量

FAISS_API int product_quantizer_compute_codes_bs
struct ProductQuantizer : public faiss::Quantizer
#include <ProductQuantizer.h>

产品 Quantizer。 PQ 使用 k-means 进行训练,以最大限度地减少到质心的 L2 距离。 PQ 支持 L2 和内积搜索,但是量化误差偏向 L2 距离。

公共类型

enum train_type_t

初始化

enumerator Train_default
enumerator Train_hot_start

质心已经初始化

enumerator Train_shared

在 PQ 段之间共享字典

enumerator Train_hypercube

用 nbits-D 超立方体初始化质心

enumerator Train_hypercube_pca

用 nbits-D 超立方体初始化质心

公共函数

inline float *get_centroids(size_t m, size_t i)

返回与子向量 m 关联的质心

inline const float *get_centroids(size_t m, size_t i) const
virtual void train(size_t n, const float *x) override

训练量化器

参数:

x – 训练向量,大小为 n * d

ProductQuantizer(size_t d, size_t M, size_t nbits)
ProductQuantizer()
void set_derived_values()

当 d、M 和 nbits 设置后,计算导出值

void set_params(const float *centroids, int m)

定义子量化器 m 的质心。

void compute_code(const float *x, uint8_t *code) const

使用乘积量化器量化一个向量。

virtual void compute_codes(const float *x, uint8_t *codes, size_t n) const override

与多个向量的 compute_code 相同

void compute_codes_with_assign_index(const float *x, uint8_t *codes, size_t n)

使用 assign_index 加速代码分配(非常量是因为索引被更改)

void decode(const uint8_t *code, float *x) const

从给定的码字解码一个向量(如果第三个参数存在,则解码 n 个向量)

virtual void decode(const uint8_t *code, float *x, size_t n) const override

解码一组向量

参数:
  • codes – 输入码字,大小为 n * code_size

  • x – 输出向量,大小为 n * d

void compute_code_from_distance_table(const float *tab, uint8_t *code) const

如果我们恰好预先计算了距离表,那么计算码字会更有效率。

void compute_distance_table(const float *x, float *dis_table) const

计算单个向量的距离表。

x = [x_0 x_1 .. x_(M-1)] 的距离表是一个 M * ksub 矩阵,其中包含

dis_table (m, j) = || x_m - c_(m, j)||^2,对于 m = 0..M-1 和 j = 0 .. ksub - 1

其中 c_(m, j) 是子量化器 m 的质心 j。

参数:
  • x – 输入向量大小 d

  • dis_table – 输出表,大小为 M * ksub

void compute_inner_prod_table(const float *x, float *dis_table) const
void compute_distance_tables(size_t nx, const float *x, float *dis_tables) const

计算几个向量的距离表

参数:
  • nx – 输入向量的数量

  • x – 输入向量大小 nx * d

  • dis_table – 输出表,大小为 nx * M * ksub

void compute_inner_prod_tables(size_t nx, const float *x, float *dis_tables) const
void search(const float *x, size_t nx, const uint8_t *codes, const size_t ncodes, float_maxheap_array_t *res, bool init_finalize_heap = true) const

执行搜索 (L2 距离)

参数:
  • x – 查询向量,大小为 nx * d

  • nx – 查询的数量

  • codes – 数据库码字,大小为 ncodes * code_size

  • ncodes – 向量的数量

  • res – 用于存储结果的堆数组 (nh == nx)

  • init_finalize_heap – 初始化堆(输入)并排序(输出)?

void search_ip(const float *x, size_t nx, const uint8_t *codes, const size_t ncodes, float_minheap_array_t *res, bool init_finalize_heap = true) const

与 search 相同,但使用内积相似度

void compute_sdc_table()
void search_sdc(const uint8_t *qcodes, size_t nq, const uint8_t *bcodes, const size_t ncodes, float_maxheap_array_t *res, bool init_finalize_heap = true) const
void sync_transposed_centroids()

将转置的质心与常规质心同步。如果直接编辑了质心,则需要调用此方法。

void clear_transposed_centroids()

清除转置的质心表,使其不再使用。

公共成员

size_t M

子量化器的数量

size_t nbits

每个量化索引的位数

size_t dsub

每个子向量的维度

size_t ksub

每个子量化器的质心数量

bool verbose

训练期间是否显示详细信息?

train_type_t train_type
ClusteringParameters cp

聚类期间使用的参数

Index *assign_index

如果非 NULL,则使用此索引进行分配 (大小应为 d / M)

std::vector<float> centroids

质心表,大小为 M * ksub * dsub。布局:(M, ksub, dsub)

std::vector<float> transposed_centroids

转置的质心表,大小为 M * ksub * dsub。布局:(dsub, M, ksub)

std::vector<float> centroids_sq_lengths

质心的平方长度,大小为 M * ksub 布局:(M, ksub)

std::vector<float> sdc_table

对称距离表。

struct PQEncoderGeneric

公共函数

inline PQEncoderGeneric(uint8_t *code, int nbits, uint8_t offset = 0)
inline void encode(uint64_t x)
inline ~PQEncoderGeneric()

公共成员

uint8_t *code

code for this vector

uint8_t offset
const int nbits

number of bits per subquantizer index

uint8_t reg
struct PQEncoder8

公共函数

inline PQEncoder8(uint8_t *code, int nbits)
inline void encode(uint64_t x)

公共成员

uint8_t *code
struct PQEncoder16

公共函数

inline PQEncoder16(uint8_t *code, int nbits)
inline void encode(uint64_t x)

公共成员

uint16_t *code
struct PQDecoderGeneric

公共函数

inline PQDecoderGeneric(const uint8_t *code, int nbits)
inline uint64_t decode()

公共成员

const uint8_t *code
uint8_t offset
const int nbits
const uint64_t mask
uint8_t reg
struct PQDecoder8

公共函数

inline PQDecoder8(const uint8_t *code, int nbits)
inline uint64_t decode()

公共成员

const uint8_t *code

Public Static Attributes

static const int nbits = 8
struct PQDecoder16

公共函数

inline PQDecoder16(const uint8_t *code, int nbits)
inline uint64_t decode()

公共成员

const uint16_t *code

Public Static Attributes

static const int nbits = 16