-
Notifications
You must be signed in to change notification settings - Fork 1
06 Distance Metrics_zh.md
cyclonedll edited this page Jun 2, 2026
·
1 revision
DistanceMetric 枚举定义了九种向量相似度计算方式:
| 度量类型 | 数学公式 | 值域 | 适用场景 | 预归一化 |
|---|---|---|---|---|
Cosine |
[-1, 1] | 文本嵌入、语义搜索 | ✅ 自动启用 | |
Euclidean |
(0, 1] | 空间坐标、物理距离 | ❌ | |
DotProduct |
已归一化向量、MIPS | ❌ | ||
Manhattan |
$\frac{1}{1 + \sum | a_i - b_i | }$ | (0, 1] |
Chebyshev |
$\frac{1}{1 + \max | a_i - b_i | }$ | (0, 1] |
Pearson |
[-1, 1] | 文本嵌入(去偏置)、TF-IDF、评分向量 | ❌ | |
Hamming |
[0, 1] | 二值哈希码、LSH、SimHash/MinHash 指纹 | ❌ | |
Jaccard |
[0, 1] | BoW/TF-IDF 稀疏特征、直方图比较 | ❌ | |
Canberra |
$1 - \frac{1}{n}\sum\frac{ | a_i-b_i | }{ | a_i |
flowchart LR
subgraph 写入时
V["原始向量 v"] --> NORM["L2 归一化<br/>v̂ = v / ‖v‖₂"]
NORM --> IDX["存入索引: v̂"]
end
subgraph 搜索时
Q["查询向量 q"] --> QNORM["L2 归一化<br/>q̂ = q / ‖q‖₂"]
QNORM --> DOT["Dot(q̂, v̂)"]
DOT --> RES["= CosineSimilarity(q, v)"]
end
style NORM fill:#d4edda
style QNORM fill:#d4edda
style DOT fill:#cce5ff
为什么 Dot 替代 Cosine 更快?
-
CosineSimilarity(a, b)= 一次点积 + 两次范数计算 = 3 次向量遍历 - 预归一化后,
Dot(â, b̂)= 一次点积 = 1 次向量遍历 - 归一化开销在写入/查询时各只执行一次,搜索时对 N 个候选只做点积
SIMD 加速实现:
// 使用内部 VectorMath 的 SIMD 优化实现
private static void NormalizeVector(ReadOnlySpan<float> source, Span<float> destination)
{
var norm = VectorMath.Norm(source); // SIMD 加速 L2 范数
if (norm > 0f)
VectorMath.Divide(source, norm, destination); // SIMD 加速向量除法
else
destination.Clear(); // 零向量安全处理,避免 NaN
}// Cosine — 最常用,文本/语义搜索
[QuiverVector(384, DistanceMetric.Cosine)]
public float[] TextEmbedding { get; set; } = [];
// Euclidean — 关心绝对距离的场景(地理坐标、物理空间)
[QuiverVector(3, DistanceMetric.Euclidean)]
public float[] Position { get; set; } = [];
// DotProduct — 向量已预归一化或需要最大内积搜索 (MIPS)
[QuiverVector(128, DistanceMetric.DotProduct)]
public float[] Feature { get; set; } = [];
// Manhattan — 稀疏特征、推荐系统
[QuiverVector(256, DistanceMetric.Manhattan)]
public float[] SparseFeature { get; set; } = [];
// Hamming — 二值哈希码、LSH 指纹
[QuiverVector(64, DistanceMetric.Hamming)]
public float[] BinaryHash { get; set; } = [];实现 ISimilarity<float> 接口定义自定义度量,然后通过 [QuiverVector] 的 CustomSimilarity 属性指定。设置 CustomSimilarity 后,metric 参数将被忽略。
// 1. 定义自定义相似度(readonly struct + ISimilarity<float>)
public readonly struct WeightedL1Similarity : ISimilarity<float>
{
public static float Compute(ReadOnlySpan<float> x, ReadOnlySpan<float> y)
{
float sum = 0f;
for (int i = 0; i < x.Length; i++)
sum += MathF.Abs(x[i] - y[i]) * (i < 128 ? 2f : 1f); // 前 128 维权重 2倍
return 1f / (1f + sum);
}
}
// 2. 在实体上使用
public class MyEntity
{
[QuiverKey]
public string Id { get; set; } = string.Empty;
[QuiverVector(256, CustomSimilarity = typeof(WeightedL1Similarity))]
public float[] Embedding { get; set; } = [];
}要求:
- 必须是实现
ISimilarity<float>的readonly struct - 必须有公共无参构造函数(结构体默认满足)
- JIT 会在调用站点内联
TSim.Compute()—— 与内置度量零开销等价
框架内部根据度量类型解析对应的 ISimilarity<float> 实现。所有实现均使用 SIMD 加速计算:
| 度量 | PreNormalize | ISimilarity 类型 | SIMD 后端 |
|---|---|---|---|
Cosine |
true |
DotProductSimilarity |
VectorMath.Dot |
Cosine (fallback) |
false |
CosineSimilarity |
VectorMath.CosineSimilarity |
DotProduct |
false |
DotProductSimilarity |
VectorMath.Dot |
Euclidean |
false |
EuclideanSimilarity |
VectorMath.Distance |
Manhattan |
false |
ManhattanSimilarity |
Vector<float> 绝对差累加 |
Chebyshev |
false |
ChebyshevSimilarity |
Vector<float> 绝对差最大值追踪 |
Pearson |
false |
PearsonCorrelationSimilarity |
VectorMath.Sum + Vector<float> 去均值点积 |
Hamming |
false |
HammingSimilarity |
Vector<float> 等值掩码 + ConditionalSelect |
Jaccard |
false |
JaccardSimilarity |
Vector<float> Min/Max 累加 |
Canberra |
false |
CanberraSimilarity |
Vector<float> 加权除法 |
| (自定义) | 用户定义 | 用户的 ISimilarity<float>
|
用户定义 |
| # | 章节 |
|---|---|
| 01 | 版本说明 |
| 02 | 产品概述 |
| 03 | 架构概述 |
| 04 | 快速开始 |
| 05 | 核心概念 |
| 06 | 距离度量 |
| 07 | 索引类型 |
| 08 | CRUD 操作 |
| 09 | 向量搜索 |
| 10 | 持久化存储 |
| 11 | 迁移系统 |
| 11a | 模式迁移 |
| 12 | 多向量字段支持 |
| 13 | 线程安全与并发 |
| 14 | 生命周期管理 |
| 15 | 配置选项 |
| 16 | 内部实现细节 |
| 17 | 完整示例 |
| 18 | API 参考速查表 |
| 19 | 使用建议 |