1. 向量 #

1.1 为什么需要向量 #

1.2 一个生活化的比喻 #

1.3 高维向量是什么 #

2. 向量从哪来 #

2.1 大模型如何学会向量 #

3. 相似度度量类型 #

3.1 欧几里得距离 #

欧几里得距离是最直观、最常用的一种相似度度量方法。简单说,它就是两个点之间直线距离。

3.1.1. 核心定义 #

在几何中,欧几里得距离衡量的是两点之间的真实“直线”长度。在AI中,我们把数据点(如图像、文本的数值表示)视为多维空间中的点,用这个距离来判断它们的相似程度。

3.1.2. 数学公式 #

对于两个n维向量 $ A $ 和 $ B $:

二维空间 (点 (x1, y1) 和 (x2, y2)):

$$ d(A,B) = \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2} $$

这就是我们熟悉的勾股定理求斜边长度。

3.1.3 演示 #

3.1.4 python 代码 #

# 导入numpy库,用于数值计算
import numpy as np

# 定义计算两个向量欧几里得距离的函数
def euclidean_distance(a, b):
    # """多行注释,描述函数功能"""
    """
    计算两个向量的欧几里得距离
    :param a: 一维list或numpy数组
    :param b: 一维list或numpy数组
    :return: 距离(float)
    """
    # 将输入a转换为numpy数组
    a = np.array(a)
    # 将输入b转换为numpy数组
    b = np.array(b)
    # 计算欧几里得距离并返回
    return np.sqrt(np.sum((a - b)**2))

# 示例

# 定义第一个向量
vec1 = [0,0]
# 定义第二个向量
vec2 = [3,4]
# 调用函数计算两个向量的欧几里得距离
distance = euclidean_distance(vec1, vec2)
# 打印欧几里得距离的结果
print(f"欧几里得距离: {distance}")

3.2 余弦相似度 #

余弦相似度衡量的是两个向量方向的夹角,而不是两点之间的直线距离。在语义搜索里,它比欧几里得距离更常用。

3.2.1 核心定义 #

把每个向量看成从原点出发的箭头。余弦相似度看的是两支箭头是否指向同一方向:

与欧几里得距离的关键区别:

3.2.2 数学公式 #

对于两个 $ n $ 维向量 $ A $ 和 $ B $:

$$ \text{similarity}(A,B) = \cos(\theta) = \frac{A \cdot B}{|A| \times |B|} $$

其中:

二维情形下,若 $ A=(x_1,y_1) $,$ B=(x_2,y_2) $:

$$ \cos(\theta) = \frac{x_1 x_2 + y_1 y_2}{\sqrt{x_1^2+y_1^2} \times \sqrt{x_2^2+y_2^2}} $$

3.2.3 演示 #

3.2.4 python 代码 #

# 导入numpy库用于数值计算
import numpy as np

# 定义第一个向量
vec1 = np.array([1, 2])
# 定义第二个向量
vec2 = np.array([2, 3])

# 定义计算余弦相似度的函数
def cosine_similarity(a, b):
    # 计算两个向量的点积
    dot_product = np.dot(a, b)
    # 计算第一个向量的范数
    norm_a = np.linalg.norm(a)
    # 计算第二个向量的范数
    norm_b = np.linalg.norm(b)
    # 返回余弦相似度的计算结果
    return dot_product / (norm_a * norm_b)

# 调用余弦相似度函数计算vec1和vec2的相似度
similarity = cosine_similarity(vec1, vec2)
# 打印余弦相似度结果
print(f"余弦相似度: {similarity}")

/ 输出一例结果 余弦相似度: 0.992583 /

4. 获取文本向量 #

4.1 准备环境 #

uv add sentence-transformers

4.2 单条文本转向量 #

# 导入 os,用于设置环境变量
import os
# 从 sentence_transformers 导入 SentenceTransformer
from sentence_transformers import SentenceTransformer

# 加载本地 Embedding 模型(首次运行会自动下载)
model = SentenceTransformer("C:/Users/Administrator/.cache/modelscope/hub/models/BAAI/bge-small-zh-v1.5")

# 指定要转成向量的文本
text = "苹果是一种甜甜的水果"

# 编码为向量(numpy 数组)
vector = model.encode(text)

# 打印文本、向量维度和前 5 个数字
print(f"文本: {text}")
print(f"向量维度: {len(vector)}")
print(f"前 5 维: {vector[:5].tolist()}")

4.3 用拿到的向量算相似度 #

# 导入 numpy 包
import numpy as np

# 导入用于句子嵌入的 SentenceTransformer 模型
from sentence_transformers import SentenceTransformer

# 定义一个计算两个向量之间余弦相似度的函数
def cosine_similarity(a, b):
    # 将输入 a 转为 numpy 数组
    a = np.array(a)
    # 将输入 b 转为 numpy 数组
    b = np.array(b)
    # 计算余弦相似度并返回
    return float(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)))

# 加载本地保存的中文句嵌入模型
model = SentenceTransformer("C:/Users/Administrator/.cache/modelscope/hub/models/BAAI/bge-small-zh-v1.5")

# 定义第一个要比较的文本
text_a = "我喜欢吃苹果"
# 定义第二个要比较的文本
text_b = "梨是很好吃的水果"
# 定义第三个要比较的文本
text_c = "篮球打起来很过瘾"

# 将三段文本编码为向量
vectors = model.encode(
    [text_a, text_b, text_c]
)
# 获取第一个文本的向量
vec_a, vec_b, vec_c = vectors[0], vectors[1], vectors[2]

# 计算 vec_a 与 vec_b 的余弦相似度
sim_ab = cosine_similarity(vec_a, vec_b)
# 计算 vec_a 与 vec_c 的余弦相似度
sim_ac = cosine_similarity(vec_a, vec_c)

# 打印 text_a 和 text_b 的余弦相似度
print(f"「{text_a}」vs「{text_b}」:", round(sim_ab, 4))
# 打印 text_a 和 text_c 的余弦相似度
print(f"「{text_a}」vs「{text_c}」:", round(sim_ac, 4))

5. 向量的用途 #

5.1 语义搜索 #

5.2 推荐系统 #

5.3 检索增强生成 #

5.4 多模态 #