百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

向量搜索之 k-means 算法(向量搜索框架)

ztj100 2025-06-15 20:40 20 浏览 0 评论

一直好奇向量数据库的索引是如何实现的,我们可以推断向量搜索的简单实现:把数据存入向量数据库时,会计算每个分段文档的向量(文档向量),然后把分段文档和文档向量同时存入向量数据库。从向量数据库中搜索文档时,会把待搜索问题转为向量(问题向量),然后计算问题向量与所有文档向量的距离,数据库会返回距离最短的一个或多个文档。

上面计算方式,返回的文档与问题最相关,但文档多时,耗费的计算资源同样多,有没有更好的方法?最容易想到的方法是把存入数据库中的文档向量先聚类为 K 个簇,从向量数据库中搜索文档时,先找到最相近的簇,再和簇内的每个文档向量比较找到与问题向量距离最短的一个或多个文档。这样需要的计算量就会少很多。

K-means算法简介

怎么把文档向量聚类为 K 个簇?可以使用K-means 算法。

  1. 初始化:随机选择K个数据点作为初始簇中心 。
  2. 分配样本:计算每个数据点到各簇中心的距离(通常用欧氏距离),将其分配到最近的簇 。
  3. 更新簇中心:重新计算每个簇的均值作为新中心 。
  4. 迭代:重复分配和更新步骤,直到中心不再变化或达到最大迭代次数

K-means 算法 python 实现

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs

# 生成模拟数据,300个数据点,4个簇,每个簇的标准差为0.6,随机种子为0
X, _ = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=0)

# K-means算法实现
def k_means(X, K, max_iters=100):
    np.random.seed(42)
    # 1. 随机初始化:从数据集中随机选择K个点作为初始簇中心
    # np.random.choice 是随机抽样函数
    # X.shape[0] 表示模拟数据个数;
    # replace=False 表示无放回抽样,即每个数据只能被选中一次,不允许重复
    centroids = X[np.random.choice(X.shape[0], K, replace=False)]
    original_centroids = centroids.copy()

    for iteration in range(max_iters):
        # 2. 分配数据点:计算每个数据点到各个簇中心的距离
        # X[:, np.newaxis] 表示为 X 添加一个新维度,使其形状变为 (n_samples, 1, n_features)。
        # 目的是通过广播机制与 centroids 的维度 (K, n_features) 对齐,便于后续逐元素计算
        # X[:, np.newaxis] - centroids 广播机制会将 X 扩展为 (n_samples, K, n_features),
        # centroids 扩展为 (n_samples, K, n_features)(实际仅逻辑扩展,不占用额外内存)
        distances = np.linalg.norm(X[:, np.newaxis] - centroids, axis=2)
        # 3. 将每个数据点分配到最近的簇
        labels = np.argmin(distances, axis=1)
 
        # 4. 更新簇中心:重新计算每个簇的中心点,即簇内所有点的均值
        # labels == k 生成布尔掩码(Boolean Mask),筛选出 labels 数组中标签等于 k 的所有样本索引
        # X[labels == k] 根据布尔掩码从数据矩阵 X 中提取属于第 k 个簇的所有样本
        # .mean(axis=0) 沿列方向(axis=0)计算均值,得到第 k 个簇的中心坐标
        new_centroids = np.array([X[labels == k].mean(axis=0) for k in range(K)])
      
        # 5. 迭代优化:检查簇中心是否变化
        if np.all(centroids == new_centroids):
            print(f"算法在第{iteration + 1}次迭代后收敛")
            break
        centroids = new_centroids

    return original_centroids, centroids, labels


# 使用K-means算法进行聚类
K = 4  # 指定簇的数量
original_centroids, centroids, labels = k_means(X, K)
# 结果可视化
plt.figure(figsize=(8, 6))
# 每个簇的数据使用不同颜色展示
plt.scatter(X[:, 0], X[:, 1], c=labels, s=50, cmap='viridis', edgecolor='k')
# 最终得到的簇心用红色展示
plt.scatter(centroids[:, 0], centroids[:, 1], c='red', s=200, alpha=0.5, marker='X')
# 最初得到的簇心用蓝色展示
plt.scatter(origcentroids[:, 0], origcentroids[:, 1], c='blue', s=200, alpha=0.5, marker='X')
plt.title("K-means Clustering")
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
# 保存到本地图片
plt.savefig("k_means_clustering.png")

上面实现中 distances = np.linalg.norm(X[:, np.newaxis] - centroids, axis=2) 等价于下面代码,计算每个数据点到各个簇中心的距离。

distances = np.zeros((X.shape[0], centroids.shape[0]))
for i in range(X.shape[0]):
    for j in range(centroids.shape[0]):
        distances[i, j] = np.sqrt(np.sum((X[i] - centroids[j])**2))

展示最终得到的簇中心与各个簇如下图所示

同时展示 K-means 算法最初随机选择的簇中心,使用蓝色叉展示如下,与最终的簇中心位置相隔较远,可见算法帮我们动态调整了簇中心。



向量数据库进行实际的向量搜索时,并不是简单通过 K-meams 算法创建索引,本文是从一个算法小白角度推导向量搜索如何实现,接下来会逐步介绍实际使用的向量搜索算法。

相关推荐

Linux集群自动化监控系统Zabbix集群搭建到实战

自动化监控系统...

systemd是什么如何使用_systemd/system

systemd是什么如何使用简介Systemd是一个在现代Linux发行版中广泛使用的系统和服务管理器。它负责启动系统并管理系统中运行的服务和进程。使用管理服务systemd可以用来启动、停止、...

Linux服务器日常巡检脚本分享_linux服务器监控脚本

Linux系统日常巡检脚本,巡检内容包含了,磁盘,...

7,MySQL管理员用户管理_mysql 管理员用户

一、首次设置密码1.初始化时设置(推荐)mysqld--initialize--user=mysql--datadir=/data/3306/data--basedir=/usr/local...

Python数据库编程教程:第 1 章 数据库基础与 Python 连接入门

1.1数据库的核心概念在开始Python数据库编程之前,我们需要先理解几个核心概念。数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,它就像一个电子化的文件柜,能让我们高效...

Linux自定义开机自启动服务脚本_linux添加开机自启动脚本

设置WGCloud开机自动启动服务init.d目录下新建脚本在/etc/rc.d/init.d新建启动脚本wgcloudstart.sh,内容如下...

linux系统启动流程和服务管理,带你进去系统的世界

Linux启动流程Rhel6启动过程:开机自检bios-->MBR引导-->GRUB菜单-->加载内核-->init进程初始化Rhel7启动过程:开机自检BIOS-->M...

CentOS7系统如何修改主机名_centos更改主机名称

请关注本头条号,每天坚持更新原创干货技术文章。如需学习视频,请在微信搜索公众号“智传网优”直接开始自助视频学习1.前言本文将讲解CentOS7系统如何修改主机名。...

前端工程师需要熟悉的Linux服务器(SSH 终端操作)指令

在Linux服务器管理中,SSH(SecureShell)是远程操作的核心工具。以下是SSH终端操作的常用命令和技巧,涵盖连接、文件操作、系统管理等场景:一、SSH连接服务器1.基本连接...

Linux开机自启服务完全指南:3步搞定系统服务管理器配置

为什么需要配置开机自启?想象一下:电商服务器重启后,MySQL和Nginx没自动启动,整个网站瘫痪!这就是为什么开机自启是Linux运维的必备技能。自启服务能确保核心程序在系统启动时自动运行,避免人工...

Kubernetes 高可用(HA)集群部署指南

Kubernetes高可用(HA)集群部署指南本指南涵盖从概念理解、架构选择,到kubeadm高可用部署、生产优化、监控备份和运维的全流程,适用于希望搭建稳定、生产级Kubernetes集群...

Linux项目开发,你必须了解Systemd服务!

1.Systemd简介...

Linux系统systemd服务管理工具使用技巧

简介:在Linux系统里,systemd就像是所有进程的“源头”,它可是系统中PID值为1的进程哟。systemd其实是一堆工具的组合,它的作用可不止是启动操作系统这么简单,像后台服务...

Red Hat Enterprise Linux 10 安装 Kubernetes (K8s) 集群及高级管理

一、前言...

Linux下NetworkManager和network的和平共处

简介我们在使用CentoOS系统时偶尔会遇到配置都正确但network启动不了的问题,这问题经常是由NetworkManager引起的,关闭NetworkManage并取消开机启动network就能正...

取消回复欢迎 发表评论: