Cosine 余弦相似度并行计算的数学原理与Python实现

背景

Cosine 我在LLM与RAG系列课程已经讲了很多次了,这里不在熬述,它在LLM分析中,尤其是在语义相似度的计算中至关重要,在dot attention机制中,也会看到他的身影。这里讲的是纯数学上的运算与python是如何运用相关库进行并行计算的原理及实践。完全掌握了他,在看vector db 里面的语义相似度,你可能会豁然开朗。实现总是如此的优雅。

Cosine的定义,两个向量(A, B), 他们的余弦相似度为:

Cosine(A,B) = (A * B)  /  (len(A) * len (B))

其实就是距离在M维坐标系的分别投影,前面也说了很多次了,不明白可以参看LLM与RAG系列课程。下面举个例子,很简单的初中数学,两个二维向量A,B,如果他们维度所包含的分量都相等,那么Cosine = 1, 很好理解:A(x, y), B(x, y)

A  *  B =  (x, y) * (x, y)= x^2 + y^2

len(A) = sqrt(x^2 + y^2)

len(B) = sqrt(x^2 + y^2)

最后答案就是 Cosine(A, B) = 1

如果是N维向量,很显然,相同。

Cosine(A,B) = (A * B)  /  (len(A) * len (B))

问题来了,我如果给你很多个A,很多个B,要你求所有A,B之间的 Cosine,要怎么处理?最笨的办法就是写个  def cosine(A,B)   return  (A * B)  /  (len(A) * len (B)),  然后写一个二层for循环,case by case,这样的代码交给CPU 做AI,肯定是不合适的。怎么优化呢?那就是线性代数的魅力来了,Matrix 运算。我们看看怎么做。

向量内积

向量内积,不要总想着二,三维,那是初中,高中的东西。在LLM的世界,高维向量普遍存在,在Choma vector db 提供的基础 embedding中,嵌入向量为 384 维度。那还算比较小的。大一点的上千维度都很正常。向量的内积,很简单,就是M维向量的M维度分别相乘后相加,放到Matrix 的指定位置就对了,python 实现更简单,就是 A dot B, 一个 dot 解决了(M , N)与 (N , J)维度的matrix 乘法。有点线性代数功底的都知道:(M , N)* (N , J) = (M, J)。 可是问题来了,在LLM的世界中,因为嵌入向量都是 M维,表达方式都是 (M , N), (J, N) 这种是没办法做 向量内积的,怎么办?很简单,转置一下,(M , N)* (J, N)T = (M, J)。 以前总觉得现线性代数没啥用,现在看到了它的魅力,你要用它的时,如果你概念基础扎实,马上就上手了。讲到了这里,看下 python 的例子:

arr1 = np.array([[1, 2, 3], [2, 3, 5], [1, 4, 3]])
arr2 = np.array([[4, 5, 6], [1, 2, 3]])
print(np.dot(X, Y.T))

非常简洁的代码,看下输出:

nice。不要小看他,它相当于是将将arr1的三个二维向量与arr2的两个二维向量在 O(0)同时完成了计算结果。而且 python 的 numpy 底层是经过 compiler 优化的,性能还是非常出色。

向量外积 

是一个线性代数中的概念,指的是两个向量的张量积(tensor product),其结果是一个矩阵。

具体来说,假设 X_norm 是一个形状为 (m,) 的一维数组(向量),而 Y_norm 是一个形状为 (n,) 的一维数组(向量)。那么,np.outer(X_norm, Y_norm) 将返回一个形状为 (m, n) 的二维数组(矩阵),其中第 i 行第 j 列的元素是 X_norm[i] 和 Y_norm[j] 的乘积。

用数学符号表示,如果 X_norm = [x_1, x_2, ..., x_m] 和 Y_norm = [y_1, y_2, ..., y_n],那么(X_norm, Y_norm)的外积 将产生一个矩阵,其元素为:

python 代码实现:

import numpy as np 
X_norm = np.array([1, 2]) 
Y_norm = np.array([3, 4, 5]) 

result = np.outer(X_norm, Y_norm)
print(result)

向量的长度

就是 2-范数或称为欧几里得范数,各维度平方相加开根号。

就是上面说的 len

p.linalg.norm 是 NumPy 中的一个函数,用于计算向量或矩阵的范数。具体来说,np.linalg.norm(X, axis=1) 是在 NumPy 数组 X 上沿着指定的轴(在这里是 axis=1)计算向量的 2-范数(或称为欧几里得范数)。

假设 X 是一个形状为 (m, n) 的二维数组(或矩阵),其中 m 是行数,n 是列数。那么 np.linalg.norm(X, axis=1) 会返回一个长度为 m 的一维数组,其中每个元素是 X 中对应行的 2-范数。

还是上面那个例子,看下代码与运行结果:

arr1 = np.array([[1, 2, 3], [2, 3, 5], [1, 4, 3]])
arr2 = np.array([[4, 5, 6], [1, 2, 3]])

X_norm = np.linalg.norm(arr1, axis=1)
Y_norm = np.linalg.norm(arr2, axis=1)

发现维度没变,还是之前的,shape 都相同。只是做了平方求和开根号的处理。

LLM中的应用

到了这里,我们发现,如果我们使用:

X = np.array([[1, 2, 3], [2, 3, 5], [1, 4, 3]])
Y = np.array([[4, 5, 6], [1, 2, 3]])
similarity = np.dot(X, Y.T) / np.outer(X_norm, Y_norm)

他就是关于X的每个二维的分量与Y的每个二维分量之间的 Cosine。因为它同时完成了对应每个位置的 (A * B)  /  (len(A) * len (B))

我们看看结果:

数学含义也很明确,比如在 X的 [1,2,3] 对 Y的 [1,2,3]时, Cosine = 1,非常完美的三行代码。不要看不起它,他在vector db 中起着举足轻重的作用。今天介绍到这里,如果你对LLM感兴趣,可以读下我的其他专栏,同步更新中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/762838.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Ubuntu机器安装rdkit指定版本,通过conda安装不需要make,有手就行。

阿里云购买Ubuntu 22.0机器 IP没错,访问外网没问题 图片中的命令放在下面了。 useradd test-user -s /bin/bash mkdir /home/test-user chown -R test-user: /home/test-user passwd test-uservi /etc/sudoers wget -c https://repo.anaconda.com/archive/Anacon…

全同态加密在大模型应用中应用

密码学简介 上文的图例基本展示了常见加密体系。加密体系,如果用比较正式的描述方法,无疑是做了三件事: 首先,通过一个生成算法 𝐾𝑒𝑦𝐺𝑒𝑛(1&#x1d70…

小白学习手册:轻松理解MQ消息队列

目录 # 开篇 RabbitMQ介绍 通讯概念 1. 初始MQ及类型 2. MQ的架构 2.1 RabbitMQ的结构和概念 2.2 RabbitMQ消息流示意图 3. MQ下载使用 3.1 Docker下载MQ参考 3.2 进入RabbitMQ # 开篇 MessagesQueue 是一个抽象概念,用于描述消息队列系统的一般特性和功能…

计算机视觉 | 基于 PointNet 网络的飞机零件 3D 点云分割

目录 一、简要介绍二、环境设置2.1 实验配置2.2 必要库安装 三、数据集解析3.1 数据集加载3.2 数据文件夹结构3.3 点云数据可视化3.4 数据获取与预处理3.5 数据集定义 四、模型组网4.1 PointNet 介绍4.2 Paddle模型组网4.3 模型概要 五、模型训练六、模型预测七、总结 Hi&#…

亚马逊广告如何设置关键词竞价获取最优广告投入产出比 (ACOS)

在投放亚马逊商品广告的时候,从我们通常的理解来说,关键词竞价CPC设置的越高,广告投入产出比 (ACOS)越高,所以我们通常希望CPC越低越好,但是从我们实际投放广告来看,CPC与ACOS并不是线性相关。有时候CPC设定…

外卖点餐二合一小程序源码系统 单店多店都可使用 自由下单 带完整的安装代码包以及搭建部署教程

系统概述 外卖点餐二合一小程序源码系统是一款集外卖点餐和店铺管理功能于一体的综合性系统。它不仅适用于单店模式,也能满足多店连锁经营的需求。无论是小型餐厅还是大型餐饮企业,都可以通过该系统轻松实现线上业务的拓展和管理。 该系统基于先进的技…

69. x 的平方根(简单)

69. x 的平方根 1. 题目描述2.详细题解3.代码实现3.1 Python方法一:逐个遍历方法二:二分查找 3.2 Java 1. 题目描述 题目中转:69. x 的平方根 2.详细题解 不能使用系统内置的函数,寻找某个数(假定为x)的…

哈希表(C++实现)

文章目录 写在前面1. 哈希概念2. 哈希冲突3. 哈希函数4.哈希冲突解决4.1 闭散列4.1.1 线性探测4.1.2 采用线性探测的方式解决哈希冲突实现哈希表4.1.3 二次探测 4.2 开散列4.2.2 采用链地址法的方式解决哈希冲突实现哈希表 写在前面 在我们之前实现的所有数据结构中(比如&…

【详解】RV1106移植opencv-mobile库

文章目录 前言一、烧入镜像二、编译项目1.创建项目文件 三、移植四、运行文件五、总结 前言 硬件:瑞芯微Rv1106【Luckfox Pro\Max Pico、网线一根、USB线、串口助手、摄像头 软件:ubuntu 20.4 编译器:arm-rockchip830-linux-uclibcgnueabihf…

昇思25天学习打卡营第6天|网络构建

网络构建 概念模型模型参数 概念 神经网络模型是由神经网络层和Tensor操作构成的,mindspore.nn提供了常见神经网络层的实现,在MindSpore中,Cell类是构建所有网络的基类,也是网络的基本单元。一个神经网络模型表示为一个Cell&…

入选顶会ICML,清华AIR等联合发布蛋白质语言模型ESM-AA,超越传统SOTA

作为细胞内无数生化反应的驱动力,蛋白质在细胞微观世界中扮演着建筑师和工程师的角色,不仅催化着生命活动,更是构筑、维系生物体形态与功能的基础构件。正是蛋白质之间的互动、协同作用,支撑起了生命的宏伟蓝图。 然而&#xff0…

RK3568驱动指南|第十五篇 I2C-第166章 初步认识I2C

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工…

无线物联网练习题

文章目录 选择填空简答大题 选择 不属于物联网感知技术的是(A) A:ZigBee B:红外传感器 C:FRID D:传感器 ZigBee是一种无线通信技术,虽然它常用于物联网中作为设备之间的通信手段,但它本身并不是一种感知技术 关于物联网于与互联网的区别的描述&#xff…

在线疫苗预约小程序的设计

管理员账户功能包括:系统首页,个人中心,工作人员管理,管理员管理,用户管理,疫苗管理,论坛管理,公告管理 微信端账号功能包括:系统首页,公告,疫苗…

机器人控制系列教程之并联机器人简介

背景 根据其构件的连接是否构成闭环形式,机器人可分为串联机器人和并联机器人两种。对于串联机器人,其所有的构件以串联的结构形式连接起来,在空间组成一种开环结构,因而具有工作空间大,灵活性好等优点,但…

MySQL之高可用性和应用层优化(一)

高可用性 故障转移和故障恢复 在应用中处理故障转移 有时候让应用来处理故障转移会更加简单或者更加灵活。例如,如果应用遇到一个错误,这个错误外部观察者正常情况下是无法察觉的,例如关于数据库损坏的错误日志信息,那么应用可…

C++算法学习心得八.动态规划算法(6)

1.最长递增子序列(300题) 题目描述: 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。 子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如&…

Kaggle竞赛——房价预测

目录 1. 特征分析1.1 数据集导入1.2 统计缺失值1.3 可视化缺失值1.4 缺失值相关性分析1.5 训练集和测试集缺失数据对比1.6 统计特征的数据类型1.7 数值型特征分布直方图1.8 数值型特征与房价的线性关系1.9 非数值型特征的分布直方图1.10 非数值型特征箱线图1.11 数值型特征填充…

代码随想录算法训练营第55天(py)| 单调栈 | 42. 接雨水*、84.柱状图中最大的矩形

42. 接雨水* 力扣链接 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 思路1 暴力 按列来计算。每一列雨水的高度,取决于,该列 左侧最高的柱子和右侧最高的柱子中,…

WMS、ERP、MES之间的关系

WMS(仓库管理系统)、ERP(企业资源计划)、MES(制造执行系统)是企业管理和运作中常见的三种系统,它们在不同的层面上发挥作用,但之间又有紧密的联系。三者之间的区别如下: …