23 个版本 (13 个重大更新)
0.18.0 | 2023 年 10 月 10 日 |
---|---|
0.17.2 | 2021 年 12 月 12 日 |
0.16.0 | 2021 年 7 月 20 日 |
0.15.0 | 2021 年 2 月 22 日 |
0.5.1 | 2019 年 3 月 24 日 |
#254 in 解析实现
每月 454 次下载
用于 8 个 crate (6 个直接使用)
290KB
6.5K SLoC
简介
finalfusion
是一个用于在 Rust 中读取、写入和使用嵌入的 crate。 finalfusion
主要与 其自己的格式 合作,该格式支持大量特性。此外,还支持 fastText、floret、GloVe 和 word2vec 文件格式。
finalfusion
自 0.11.0 版本以来 API 稳定。然而,我们目前还不能标记版本 1,因为通过 API 暴露的几个依赖项尚未达到版本 1(尤其是 ndarray
和 rand
)。未来 finalfusion
的 0.x 版本将用于适应这些依赖项的更新。
注意:finalfusion 0.11 和 0.12 之间存在小的 API 变更。将 Error
类型从 finalfusion::io
移动到 finalfusion::error
。将单独的 ErrorKind
枚举与 Error
合并。现在 Error
被标记为非穷举的,这样可以在不更改 API 的情况下在将来添加新的错误变体。
使用方法
要使 finalfusion
可用于您的 crate,只需将以下内容放入您的 Cargo.toml
finalfusion = 0.16
加载嵌入和查询它就像这样简单
use std::fs::File;
use std::io::BufReader;
use finalfusion::prelude::*;
fn main() {
let mut reader = BufReader::new(File::open("embeddings.fifu").unwrap());
let embeds = Embeddings::<VocabWrap, StorageWrap>::read_embeddings(&mut reader).unwrap();
embeds.embedding("Query").unwrap();
}
功能
finalfusion
支持多种格式
- 词汇表
- 子词
- 无子词
- 存储
- 数组
- 内存映射
- 量化
- 格式
- finalfusion
- fastText
- floret
- GloVe
- word2vec
此外,finalfusion
还提供了
- 相似度查询
- 类比查询
- 通过 reductive 对嵌入进行量化
- 转换为以下格式
- finalfusion
- word2vec
- GloVe
欲了解更多信息,请参阅 API 文档。
获取嵌入
从版本 0.4
开始,使用 finalfrontier 训练的嵌入在 finalfusion
格式下,与该包兼容。我们网站上提供了一系列的 预训练嵌入,并将 fastText Wikipedia 和 Common Crawl 嵌入转换为 finalfusion
。更多详细信息可在 https://finalfusion.github.io 找到。
我应该使用哪种存储方式?
量化嵌入
量化嵌入将嵌入存储为离散表示。想象一下,对于给定的嵌入空间,你会找到 256 个原型嵌入。每个嵌入可以存储为一个指向这些原型嵌入之一的 1 字节指针。当然,只有 256 种可能的表示,这种量化嵌入空间会非常粗糙。
产品量化器 (pq) 通过将每个嵌入均匀分割成 q 个子向量,并为每个子向量集找到原型向量来解决这个问题。如果我们为每个子空间使用 256 个原型表示,则可以表示 256^q 个不同的词嵌入。例如,如果 q = 150,我们可以表示 250^150 个不同的嵌入。然后每个嵌入将存储为 150 字节大小的指针。
优化产品量化器 (opq) 还将线性映射应用于嵌入空间,以在嵌入维度之间分配方差。
通过量化嵌入矩阵,可以在磁盘和内存中减小其大小。
内存映射嵌入
通常,我们将嵌入读入内存。然而,作为一种替代方案,嵌入可以 内存映射。通过 内存映射,将磁盘上的嵌入矩阵作为虚拟内存中的页面提供。操作系统将(透明地)根据需要将这些页面加载到物理内存中。
内存映射可以加快词嵌入的初始加载时间,因为只需要读取词汇表。然后操作系统将根据需要加载(部分)嵌入矩阵。当不再查找嵌入且其他进程需要内存时,操作系统还可以释放内存。
经验比较
以下关于嵌入类型的经验比较使用了一个包含 2,807,440 个嵌入(710,288 个词,2,097,152 个子词)的 300 维嵌入矩阵。嵌入查找时间是在 Intel Core i5-8259U CPU,2.30GHz 上完成的。
已知查找 和 未知查找 时间是查找词汇表内外的词。查找包含已知和未知词的混合。
存储 | 查找 | 已知查找 | 未知查找 | 内存 | 磁盘 |
---|---|---|---|---|---|
数组 | 449 纳秒 | 232 纳秒 | 18 微秒 | 3213 MiB | 3213 MiB |
数组 mmap | 833 纳秒 | 494 纳秒 | 23 微秒 | 可变 | 3213 MiB |
opq | 40 微秒 | 21 微秒 | 962 微秒 | 402 MiB | 402 MiB |
opq mmap | 41 微秒 | 21 微秒 | 960 微秒 | 可变 | 402 MiB |
注意:使用了两个单位:纳秒 (ns) 和微秒 (μs)。
使用 BLAS 或 LAPACK 库
如果您在二进制crate中使用finalfusion
,可以通过为ndarray
编译添加BLAS支持来加快finalfusion-rust
中某些功能。为此,启用ndarray/blas
功能,并添加以下crate之一作为依赖项以选择BLAS/LAPACK实现
netlib-src
:使用参考BLAS/LAPACK(较慢,不推荐使用)openblas-src
:使用OpenBLASintel-mkl-src
:使用Intel Math Kernel Library
如果您想使用优化乘积量化量化嵌入矩阵,除了添加BLAS/LAPACK实现之外,还必须启用reductive/opq-train
功能。
可以以finalfusion-utils
的Cargo.toml文件为例,了解如何在二进制crate中使用BLAS。
示例:量化矩阵中的嵌入查找
使用优化乘积量化器量化的嵌入矩阵中的嵌入查找可以使用良好的BLAS实现加快。以下表格比较了在编译带有和没有MKL/OpenBLAS支持的finalfusion在Intel Core i5-8259U CPU、2.30GHz上的查找时间
存储 | 查找 | 已知查找 | 未知查找 |
---|---|---|---|
opq | 40 微秒 | 21 微秒 | 962 微秒 |
opq mmap | 41 微秒 | 21 微秒 | 960 微秒 |
opq (MKL) | 14 μs | 7 μs | 309 μs |
opq mmap (MKL) | 14 μs | 7 μs | 309 μs |
opq (OpenBLAS) | 15 μs | 7 μs | 336 μs |
opq mmap (OpenBLAS) | 15 μs | 7 μs | 342 μs |
接下来该怎么做
依赖关系
~6MB
~113K SLoC