embedding 模型换一款要重算多少容量:维度、条数与向量长度怎么估
换 embedding 模型时,容量账最容易静默出错的不是乘法,而是“一条向量”的定义。源记录数没有变化,不代表需要保存的向量对象数没有变化;输出维度相同,也不代表向量长度和存储精度相同。
只要计数口径错了,后面的乘法即使完全正确,也只是精确计算了一个错误对象。
先钉住下限估算边界
本文所有容量结果都只统计公式能够确认的向量负载,是下限估算,真实系统占用只会更高。
读数分为三档:
- ① 公式确定:输入的维度、条数、每分量字节都已确定,原始向量负载可以纯算术计算到字节。
- ② 按公开算法结构可推出:可以确认向量如何拆分、长度按什么单位统计,但还缺少实际配置。
- ③ 本站算不准:结果取决于具体实现或索引参数,只给计算公式,不给估算倍数。
换模型换的不只是维度:稠密、多向量、稀疏三种形态
多形态 embedding 模型可以同时承担稠密检索、多向量检索和稀疏检索。需要注意:模型能够输出多种形态,不等于部署时必须把多种形态全部保存。
容量测算首先要问的不是“模型叫什么”,而是:
实际选用了哪种输出形态?每个输入最终产生几个向量对象?每个向量对象按什么长度记账?
稠密形态:长度主要看维度
稠密向量按维度计量长度。设:
n:实际保存的向量对象数;d:每个向量的维度;b:每个分量占用的字节数。
如果每个输入实际只保存一个稠密向量,那么源记录数与向量对象数可能一致;如果切片、聚合或输出流程改变了对象数量,就不能继续沿用源记录数。
容量账里必须把“源记录数”和“向量对象数”分开命名,不能都叫“条数”。
多向量形态:一条输入可能对应多个向量对象
多向量形态的关键不是维度,而是拆分关系。设第 i 个输入产生 q_i 个向量对象,那么总向量数为:
n = Σq_i
如果每个输入固定产生 q 个向量,则可以写成:
n = m × q
其中,m 是输入对象数。输入对象数不变,也可能因为 q 改变而使容量负载改变。
因此,多向量模型即使使用相同维度,也不能直接继承旧测算。旧测算如果把“一份输入”当成“一条向量”,计数口径已经失效。
稀疏形态:对象数与元素数必须分开
稀疏形态下,一个向量对象仍然可以算一条,但它的长度不能直接按稠密维度填写。
设第 i 个稀疏向量包含 k_i 个非零元素。官方 sparsevec 定义以非零元素个数描述向量容量单位,而不是以稠密维度或源文档数代替。
所以这里至少存在三种不同的计数:
m:源对象数;n:实际保存的向量对象数;K = Σk_i:全部稀疏向量的非零元素总数。
三者不能共用一个没有定义的“条数”。
稀疏形态下“一条”按什么计:非零元素个数,不是维度
稀疏形态最容易出现两种误算。
一种是把稀疏向量仍按完整维度计算,相当于为大量零元素预留空间。另一种是把非零元素总数当成数据库对象数。两者都不准确。
正确的问法是:
- 问“保存了多少个向量对象”,回答
n; - 问“这些向量一共有多少个非零项”,回答
K; - 问“单个向量的容量相关长度”,回答该向量的
k_i; - 问“原始输入有多少份”,回答
m。
非零元素个数不是维度,也不是文档数。它只描述稀疏向量中实际存在的元素数量。
还要注意:知道 K 不等于已经知道字节数。只有存储格式明确给出一个非零项实际占用多少字节,才能进一步换算为容量。坐标、值及实现相关存储方式如果没有明确字节口径,就属于③ 本站算不准,不能用稠密分量的字节数直接代替。
重算算法:三个比值相乘,把公式写完整
Faiss 官方 wiki 的 Bytes/vector 列已经把向量长度与分量精度分开:普通 Flat 表示使用 4*d 字节,SQ8 使用 d 字节。NumPy 官方文档说明,numpy.float32 是 32 bit 浮点数,即每个分量 4 byte。
由此可以得到原始稠密向量负载公式:
B_dense = n × d × b
如果采用 numpy.float32,每分量字节 b = 4,公式就是:
B_dense = 4 × n × d
这个结果在“已选定的原始向量负载”范围内是① 公式确定,可以精确到字节;但作为完整系统容量,它仍然只是下限估算。
换模型后的三个比值
在输出形态、计数口径和估算范围保持一致时,新旧容量之比为:
R = (d_new / d_old) × (n_new / n_old) × (b_new / b_old)
再由旧基线得到:
B_new = B_old × R
三个比值分别回答:
- 维度比:每个向量由多少个分量构成;
- 条数比:实际保存的向量对象发生了多少变化;
- 精度比:每个分量或存储单元占用的字节发生了多少变化。
这三个比值必须使用同一种口径。新模型能输出多向量或稀疏向量,不代表这些输出一定被保存;如果部署只保留其中一种,就只计算实际落库的那一种。
维度变化而条数、精度及输出形态不变时,可以直接按比值重算,不必仅因维度改变就否定全部旧资料。反过来,维度相同但一条输入变成多个向量对象,旧容量仍然不能沿用。
稀疏向量如何套用同一算法
可以把公式中的长度统一写成 l:
B = n × l × b
对于稠密向量,l = d。
对于稀疏向量,l 应当是非零元素数量,而不是直接填写模型维度。
如果所有稀疏向量的非零元素数都为 k:
B_sparse = n × k × b_s
其中,b_s 必须是实际存储格式中一个非零项对应的字节宽度。这个值没有公开配置支持时,不能猜测。
如果每个稀疏向量的非零元素数不同,先计算:
K = Σk_i
再计算平均非零元素数:
k_avg = K / n
于是:
B_sparse = n × k_avg × b_s
对应的换模型比值为:
R_sparse = (k_avg,new / k_avg,old) × (n_new / n_old) × (b_s,new / b_s,old)
这里,稀疏非零项的平均长度可以由公开结构推出,属于② 按公开算法结构可推出;b_s 若未由实际格式确认,就属于③ 本站算不准。本站不会为它补一个实现倍数。
索引结构为什么不能塞进一个神秘系数
三比值公式只处理已经选定并可确认的向量负载。Faiss 官方 wiki 同时表明,一些索引的每向量字节公式还会出现 M、nbits 等索引参数。
这说明索引结构是公开算法的一部分,但只有实际索引类型和参数确定后,才能继续计算对应项。参数缺失时,本站只保留公式,不把未知开销折算成比例。
按本站口径,未纳入的索引结构与实现开销只增不减,真实占用只会高于当前下限读数。
维度这个数去哪里读:模型给的输入项,必须去模型卡或配置里查
对容量测算台而言,维度 d 是一个输入项,不是可以从模型名称、输入文本长度或索引参数反推出来的结果。
具体数值必须到对应模型的模型卡或服务配置中读取,并同时确认:
- 实际使用的是稠密、多向量还是稀疏输出;
- 稠密向量或多向量中的每个向量对象对应多少维度;
- 如果保存稀疏输出,使用的是怎样的非零元素计数口径;
- 计划采用的每分量或每非零项字节宽度是什么;
- 是否只保存其中一种输出形态。
论文摘要可以证明模型支持哪些输出形态,但不能自动替代部署配置中的具体维度值。输入长度上限也不是向量维度,存储类型允许的维度范围同样不是模型实际输出维度。
如果模型卡或配置没有给出本站所需的值,该项就应保持未知。不能从相近模型、旧版本配置或数据库类型上限中猜一个数字填入。
本站不接数据库、不上传或保存数据。模型配置、向量对象数和非零元素数需要在上游整理后,作为容量公式的输入。
什么时候旧测算还成立,什么时候必须推翻重算
旧测算仍然成立的条件
只有以下口径都保持一致时,旧容量读数才可以直接成立:
- 实际保存的输出形态相同;
- “一条向量”的计数单位相同;
- 实际向量对象数相同;
- 每个向量的容量相关长度相同;
- 每分量或每非零项字节数相同;
- 索引类型、参数及容量统计范围相同。
模型换了,但最终输出形态、维度、对象数、精度和存储方式都没有变化,旧读数才可继续使用。
旧基线可以按比例重算的情况
如果输出形态和计数口径没有改变,只是维度、向量对象数或存储字节发生变化,可以保留旧容量作为基线,代入三个比值重算。
这属于重算,不是直接沿用旧结果。尤其不能只更新维度而忽略条数,也不能只更新条数而继续沿用旧精度。
必须整个推翻重算的情况
出现以下任一变化时,旧读数应直接作废:
- 从稠密输出切换到稀疏输出;
- 从稀疏输出切换到稠密输出;
- 从单向量输出切换到多向量输出;
- 同一个输入对应的向量对象数发生变化;
- 新增了原本没有保存的多向量或稀疏结果;
- 旧测算把源记录数误当成向量对象数;
- 旧测算把稀疏维度误当成非零元素数;
- 稀疏非零元素数或实际字节宽度无法确认;
- 存储精度、索引类型或索引参数发生变化。
其中,只换维度不一定要推翻全部计数;换了“一条向量”的定义则一定不能只做比例换算。
最典型的反例是:新旧维度相同,但新模型为同一输入产生多个向量。此时维度比没有变化,容量仍可能改变,因为条数比已经失效。
换模型后自查的三步
- 先锁定输出形态:确认实际保存的是稠密、多向量、稀疏,还是多种结果并存。
- 再重建计数口径:分别数清源对象数、向量对象数,以及稀疏向量的非零元素总数。
- 最后代入同一公式:确认维度、每分量字节和索引统计范围,再计算新旧比值;缺少实现参数的部分保留为未知,不补估算倍数。
需要进一步区分原始向量负载与完整系统占用时,可查看使用边界;想了解本站为何只提供下限估算,可阅读规则;计算口径与资料处理原则则见关于。
本文为容量测算方法说明,不构成选型建议。