隐藏结构
处理大量文档、图像或其他非结构化数据集合时,了解整体情况通常会很有用。单独检查数据点并非总是掌握数据结构的最佳方式。

没有上下文的数据点,基本没用
正如表格中的数字在绘制成图表后获得意义一样,将非结构化数据项之间的距离(相似/不相似)可视化可以揭示隐藏的结构和模式。

可视化图表,非常直观
在许多实现中,距离矩阵计算是聚类或可视化过程的一部分,需要暴力计算或构建临时索引。然而,使用 Qdrant,数据已经索引,距离矩阵可以相对廉价地计算出来。
在本文中,我们将使用距离矩阵 API 探索几种数据探索方法。
降维
最初,我们可能希望一眼就能看到整个数据集,或者至少是其中的很大一部分。然而,高维数据无法直接可视化。我们必须应用降维技术将数据转换为低维表示,同时保留重要的数据属性。
在本文中,我们将使用 UMAP 作为我们的降维算法。
这里是 UMAP 的一个非常简化但直观的解释
- 在 2D 空间中随机生成点:为每个高维点分配一个随机的 2D 点。
- 计算高维点的距离矩阵:计算所有点对之间的距离。
- 计算 2D 点的距离矩阵:执行类似于步骤 2 的操作。
- 匹配两个距离矩阵:调整 2D 点以最小化差异。

UMAP 结果的典型示例,来源
UMAP 保留了高维点之间的相对距离;实际坐标并不重要。如果我们已经有了距离矩阵,可以完全跳过步骤 2。
让我们使用 Qdrant 计算距离矩阵并应用 UMAP。我们将使用一个非常适合在 Qdrant 中进行实验的默认数据集——Midjourney Styles 数据集。
使用此命令下载数据集并将其导入到 Qdrant 中
PUT /collections/midlib/snapshots/recover
{
"location": "http://snapshots.qdrant.io/midlib.snapshot"
}
我们还需要准备我们的 Python 环境
pip install umap-learn seaborn matplotlib qdrant-client
导入必要的库
# Used to talk to Qdrant
from qdrant_client import QdrantClient
# Package with original UMAP implementation
from umap import UMAP
# Python implementation for sparse matrices
from scipy.sparse import csr_matrix
# For vizualization
import seaborn as sns
建立与 Qdrant 的连接
client = QdrantClient("http://localhost:6333")
完成此操作后,我们可以计算距离矩阵
# Request distances matrix from Qdrant
# `_offsets` suffix defines a format of the output matrix.
result = client.search_matrix_offsets(
collection_name="midlib",
sample=1000, # Select a subset of the data, as the whole dataset might be too large
limit=20, # For performance reasons, limit the number of closest neighbors to consider
)
# Convert distances matrix to python-native format
matrix = csr_matrix(
(result.scores, (result.offsets_row, result.offsets_col))
)
# Make the matrix symmetric, as UMAP expects it.
# Distance matrix is always symmetric, but qdrant only computes half of it.
matrix = matrix + matrix.T
现在我们可以将 UMAP 应用于距离矩阵
umap = UMAP(
metric="precomputed", # We provide ready-made distance matrix
n_components=2, # output dimension
n_neighbors=20, # Same as the limit in the search_matrix_offsets
)
vectors_2d = umap.fit_transform(matrix)
这就是获取数据 2D 表示所需的一切。

UMAP 应用于 Midlib 数据集
UMAP 并非唯一与我们的距离矩阵 API 兼容的算法。例如,scikit-learn
还提供了
- Isomap - 通过等距映射进行非线性降维。
- SpectralEmbedding - 根据指定函数形成亲和矩阵,并对相应的图拉普拉斯进行谱分解。
- TSNE - 众所周知的降维算法。
聚类
理解数据结构的另一种方法是聚类——将相似的项目分组。
请注意,没有普遍最佳的聚类准则或算法。

聚类示例,来源
许多聚类算法接受预计算的距离矩阵作为输入,因此我们可以使用之前计算出的相同距离矩阵。
让我们考虑一个使用 KMeans 算法对 Midlib 数据集进行聚类的简单示例。
从 scikit-learn.cluster 文档 中我们了解到,KMeans 算法的 fit()
方法优先接受以下输入
X : {类数组, 稀疏矩阵} 形状 (n_samples, n_features)
:
用于聚类的训练实例。必须注意,数据将被转换为 C 顺序,如果给定数据不是 C 连续的,这将导致内存复制。如果传入的是稀疏矩阵且不是 CSR 格式,也将进行复制。
因此我们可以复用上一个示例中的 matrix
from sklearn.cluster import KMeans
# Initialize KMeans with 10 clusters
kmeans = KMeans(n_clusters=10)
# Generate index of the cluster each sample belongs to
cluster_labels = kmeans.fit_predict(matrix)
通过这段简单的代码,我们将数据聚类成 10 个簇,而其中 CPU 密集型的主要部分由 Qdrant 完成。

聚类应用于 Midlib 数据集
如何绘制此图表
sns.scatterplot(
# Coordinates obtained from UMAP
x=vectors_2d[:, 0], y=vectors_2d[:, 1],
# Color datapoints by cluster
hue=cluster_labels,
palette=sns.color_palette("pastel", 10),
legend="full",
)
图
聚类和降维都旨在提供更清晰的数据概览。然而,它们有一个共同的特点——在结果可视化之前需要一个训练步骤。
这也意味着引入新的数据点需要重新运行训练步骤,这可能会计算成本很高。
图提供了一种替代的数据探索方法,可以直接、交互式地可视化数据点之间的关系。在图表示中,每个数据点是一个节点,数据点之间的相似性表示为连接节点的边。
这样的图可以使用 力导向布局 算法实时渲染,该算法通过动态重新定位节点来最小化系统能量——数据点越相似,它们之间的边就越强。
向图中添加新的数据点就像插入新节点和新边一样简单,无需重新运行任何训练步骤。
在实践中,一次性渲染整个数据集的图表可能计算成本很高,并且对用户来说难以承受。因此,让我们探讨一些解决此问题的策略。
从单个节点展开
这是最简单的方法,我们从单个节点开始,通过将最相似的节点添加到图中来展开图表。

数据的图表示
从集合中采样
如果您想探索单个点的邻居,从单个节点展开非常有效,但如果您想探索整个数据集呢?如果您的数据集足够小,您可以一次性渲染所有数据点的关系。但这在实践中是很少见的情况。
相反,我们可以对数据进行采样,并为这个子集渲染图表。这样,我们可以在不向用户提供过多信息的情况下获得数据的良好概览。
让我们在 Qdrant 的图探索工具 中尝试这样做
{
"limit": 5, # node neighbors to consider
"sample": 100 # nodes
}

数据的图表示(Qdrant 的图探索工具)
此图捕获了数据的一些高级结构,但您可能已经注意到,它相当嘈杂。这是因为相似性差异相对较小,并且可能被力导向布局算法的拉伸和压缩所淹没。
为了使图表更具可读性,让我们关注最重要的相似性并构建所谓的最小/最大生成树。
{
"limit": 5,
"sample": 100,
"tree": true
}

图的生成树(Qdrant 的图探索工具)
该算法将仅保留最重要的边并移除其余的边,同时保持图的连通性。通过这样做,我们可以揭示数据的簇以及它们之间最重要的关系。
从某种意义上说,这类似于层次聚类,但具有交互式探索数据的能力。另一个类比可能是动态构建的思维导图。
结论
向量相似性不仅仅是查找最近的邻居——它为数据探索提供了强大的工具。许多算法可以构建人类可读的数据表示,而 Qdrant 使使用这些算法变得容易。
Qdrant Web UI 中提供了多种数据探索工具(可视化和图探索工具),对于更高级的用例,您可以直接利用我们的距离矩阵 API。
用您自己的数据试试,看看您能揭示出哪些隐藏结构!