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 解析实现

Download history 204/week @ 2024-04-22 283/week @ 2024-04-29 116/week @ 2024-05-06 106/week @ 2024-05-13 59/week @ 2024-05-20 75/week @ 2024-05-27 148/week @ 2024-06-03 95/week @ 2024-06-10 110/week @ 2024-06-17 131/week @ 2024-06-24 150/week @ 2024-07-01 112/week @ 2024-07-08 94/week @ 2024-07-15 131/week @ 2024-07-22 114/week @ 2024-07-29 110/week @ 2024-08-05

每月 454 次下载
用于 8 个 crate (6 个直接使用)

MIT/Apache

290KB
6.5K SLoC

简介

crates.io docs.rs Travis CI

finalfusion 是一个用于在 Rust 中读取、写入和使用嵌入的 crate。 finalfusion 主要与 其自己的格式 合作,该格式支持大量特性。此外,还支持 fastText、floret、GloVe 和 word2vec 文件格式。

finalfusion 自 0.11.0 版本以来 API 稳定。然而,我们目前还不能标记版本 1,因为通过 API 暴露的几个依赖项尚未达到版本 1(尤其是 ndarrayrand)。未来 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 还提供了

  • 相似度查询
  • 类比查询
  • 通过 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:使用OpenBLAS
  • intel-mkl-src:使用Intel Math Kernel Library

如果您想使用优化乘积量化量化嵌入矩阵,除了添加BLAS/LAPACK实现之外,还必须启用reductive/opq-train功能。

可以以finalfusion-utilsCargo.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