Embedding 如何表示语义相似度?

Embedding 如何表示语义相似度?余弦相似度和向量空间怎么理解?
上篇我们聊了 Embedding 的本质——它是怎么把"苹果"变成一串数字的。但光有数字还不够,机器怎么知道两个数字串"像不像"?
这才是 Embedding 真正厉害的地方。
为什么"苹果"会有三个意思?
你跟朋友发消息说"今天买了袋苹果",对方秒懂你说的是水果。
换成"我准备换苹果了",对方立刻反应过来你聊的是手机。
公司开会时说"今年苹果的股价又涨了",大家心照不宣指的是那家科技公司。
这三个"苹果",文字一模一样,发音一模一样。但人类看一眼就知道意思完全不同。
问题来了:机器怎么分辨?
人类靠的是经验和上下文。机器靠的是——向量空间。

Embedding 把语言翻译成了地址
还记得上篇说的吗?Embedding 本质上是个"翻译官"。
它把任何文本翻译成一段固定长度的数字。这段数字不是乱写的——它记录了这句话的"语义特征"。
你把"我爱吃苹果"这句话扔进 Embedding 模型,它吐出来的可能是一串 768 位的数字。
这串数字不是随机生成的。每一位数字都对应着某种语义维度:可能是"水果属性"、"科技属性"、"积极情感"、"消极情感"……
语义相近的句子,翻译出来的数字也"相近"。
这就好像每句话都有一个专属地址。意思相近的句子,地址也相近。意思完全不同的句子,地址可能隔着十万八千里。

向量空间:语义的地图
想象你手里有一张地图。
地图上有"开心"、"高兴"、"快乐"这几个词,它们挤在一起。
地图另一头是"难过"、"悲伤"、"伤心",它们也挤在一起。
这两堆词分别代表了"积极情感"和"消极情感"。
而"苹果"这个词?它正好坐落在"水果"和"科技公司"两个区域的交界处。
这张地图,就是向量空间。
真实模型里的向量空间可不止两维,可能是 768 维,也可能是 1536 维。但原理是一样的——每个维度代表一种语义特征,每个句子在这个多维空间里都有一个位置。
语义相似的句子,在这个空间里位置相近。语义相反的句子,位置相对。
两个文本向量离得越近,意思越可能相近。就像现实世界里的邻居。

怎么衡量"有多像"?余弦相似度登场
好了,现在我们知道每个句子在向量空间里有个位置。
但机器怎么计算"这两个句子有多像"?
这就需要一个数学工具——余弦相似度。
它不是量两个点的直线距离,而是看两个向量的"夹角"。
夹角越小,方向越一致,语义越接近。夹角越大,方向越偏离,语义越不同。
你可能会问:为什么看夹角而不是看距离?
因为夹角只看"方向",不看"长度"。
两个句子意思完全一样,但一个长一个短。距离可能差很远,但方向几乎一样。余弦相似度告诉你:它们其实很"像"。
就像两个人朝同一个方向走,一个走了100米一个走了10米。目的地可能不同,但方向一致,说明他们要去的地方"语义相近"。

实操一下:看相似度数值长什么样
说理论太虚,我们来点真的。
用 Python 加载一个 Embedding 模型,把两句话丢进去:
from sentence_transformers import SentenceTransformer
import numpy as np
model = SentenceTransformer('all-MiniLM-L6-v2')
# 两句意思相近的话
text1 = "The is a happy person"
text2 = "The is a very happy person"
vec1 = model.encode(text1)
vec2 = model.encode(text2)
# 计算余弦相似度
cos_sim = np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))
print(f"相似度: {cos_sim:.2f}")结果是多少?0.94。
将近满分。机器告诉你:这两句话意思高度接近。
换一组试试:
text1 = "今天天气真好"
text2 = "这件衣服真难看"
vec1 = model.encode(text1)
vec2 = model.encode(text2)
cos_sim = np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))
print(f"相似度: {cos_sim:.2f}")结果是多少?0.26。
机器的判断是:这两句话几乎不相关。
是不是很像给句子量体温?0.9 以上是"高烧"——意思很接近。0.5 左右是"低烧"——有点关系但不确定。0.3 以下是"正常"——八竿子打不着。

向量数据库:让搜索从"找关键词"变成"找意思"
现在你明白了 Embedding 和余弦相似度。
但实际应用中,你可能有几十亿句话。查询一句话和哪句最像,怎么找?
总不能遍历几十亿次、每次都计算余弦相似度吧?
向量数据库就是干这个的。
它专门存储 Embedding 产生的向量,并且针对"在高维空间里找最近的邻居"这个需求做了优化。
常见的有 Pinecone、Milvus、Redis(支持向量索引)、Chroma 等等。
工作流程是这样的:
你输入"用户想找什么",这句话先被 Embedding 模型翻译成向量。然后向量数据库用特殊算法(比如 HNSW、IVF)快速找到和它夹角最小的那几个向量。最后返回对应的原始文本。
这就是所谓的"语义搜索"——不是匹配关键词,而是理解你要找的意思。
比如你搜"拍照好看的手机",返回的不是包含"手机"的文章,而是真正讨论"摄影功能强"的文章。
甚至你搜"How to lose weight fast",向量数据库能找到中文的"快速减肥方法",因为它们在这个语义空间里位置很近。

这只是第一把钥匙
从"苹果"到"今日阳光明媚",机器理解语义的过程,本质上是把模糊的人类语言翻译成精确的数学语言。
Embedding 给了每句话一个坐标。余弦相似度能量出任意两个坐标有多"像"。
有了这两样东西,AI 第一次真正"读懂"了文本的意思,而不只是匹配字符。
但问题来了:Embedding 模型那么多,维度有 128 的、384 的、768 的、1536 的,中文的、英文的、收费的、免费的……
到底该怎么选?选错了会怎样?
下篇我们就来聊聊:文本 Embedding 模型怎么选?维度、中文效果和成本怎么看?
