文章目录
- 【95.Python+AI】向量嵌入(Embedding)到底是什么:为什么它能表示"语义"
- 导入语
- 1 ~> 起点:计算机只认数字,怎么"表示"一个词
- 1.1 演进脉络
- 2 ~> one-hot:最朴素的方案与两大致命伤
- 2.1 方案:一人一个坑位
- 2.2 致命伤一:维度爆炸
- 2.3 致命伤二:语义鸿沟
- 3 ~> word2vec:让词义"住"进向量里
- 3.1 核心思想:近朱者赤
- 3.2 著名的向量算术
- 3.3 遗留问题:一词一向量
- 4 ~> BERT:同一个词,不同语境,不同向量
- 4.1 上下文嵌入
- 4.2 从词向量到句向量
- 5 ~> 相似度的数学本质:为什么是余弦
- 5.1 两个候选方案的较量
- 5.2 Python实测:眼见为实
- 5.3 降维可视化:亲眼看看语义空间
- 思考 && 总结
- 结尾
【95.Python+AI】向量嵌入(Embedding)到底是什么:为什么它能表示"语义"
📖文章简介:本文系统讲解向量嵌入(Embedding)的本质,是理解RAG、语义搜索、推荐系统的数学地基。文章从"计算机不懂文字"这一根本矛盾切入,沿着技术演进路线逐层拆解三种表示方案:one-hot编码(最朴素的离散表示,以及它维度爆炸、语义鸿沟两大致命缺陷)、word2vec(分布式表示的突破,"国王-男人+女人≈女王"的向量运算奇迹从何而来)、BERT上下文嵌入(同一个"苹果"在水果句和手机句里为什么有不同向量)。深入讲解语义距离的数学本质——为什么用余弦相似度而不是欧氏距离,配Python代码实测"猫/狗/汽车"的相似度关系;并用matplotlib将768维向量降维可视化,让你亲眼看到语义相近的词在空间中聚成一簇。配以Mermaid流程图展示表示方案的演进脉络,适合想真正搞懂Embedding而不是只会调API的开发者阅读参考。
🎬 个人主页:源码骑士
❄专栏传送门:《Android开发基础》《python基础课程》
⭐️热衷从源码视角拆解技术底层原理,将复杂架构讲得通俗易懂
🎬 源码骑士的简介:
5年Android Framework系统开发经验,曾主导多项系统级性能优化专项
技术栈覆盖Android系统全链路(Binder/Handler/AMS/WMS/启动流程)及Java后端全家桶(Spring + MyBatis + Redis + Oracle)
累计产出原创技术文章100+篇,文章以流程图为特色,被读者评价为"看一篇胜过啃一周源码"
导入语
用过Embedding API的同学都有过这种"会用但心虚"的感觉:把一句话POST上去,返回768个浮点数,然后把这串数字存进向量数据库、算个相似度,搜索就"神奇地"work了。
可一旦有人追问:这768个数字凭什么代表这句话的意思?"猫"和"狗"的向量为什么比"猫"和"汽车"的向量更接近?多数人就答不上来了,只能含糊一句"模型学出来的"。
答不上来,后面所有东西都是空中楼阁:为什么Chunk切分影响检索质量、为什么换个Embedding模型要全量重建索引、为什么余弦相似度是0.7算"相关"——这些问题的答案全藏在Embedding的原理里。这篇文章就把这层窗户纸捅破,从one-hot一路讲到BERT,让你知其然更知其所以然。
1 ~> 起点:计算机只认数字,怎么"表示"一个词
所有的矛盾从一个简单的事实开始:计算机的世界里没有文字,只有数字。想让机器处理语言,第一步就是把每个词变成一组数字——这一步叫"表示"(Representation)。
表示方案的好坏只有一个评判标准:数字之间的关系,能不能反映语言之间的关系。意思相近的词,数字也应该相近——这个朴素的要求,就是三种方案几十年演进的主线。
1.1 演进脉络
2 ~> one-hot:最朴素的方案与两大致命伤
2.1 方案:一人一个坑位
词表里有5个词,就用5维向量,每个词独占一个位置:
词表:["猫","狗","苹果","汽车","跑"]猫 →[1,0,0,0,0]狗 →[0,1,0,0,0]苹果 →[0,0,1,0,0]汽车 →[0,0,0,1,0]跑 →[0,0,0,0,1]2.2 致命伤一:维度爆炸
真实词表动辄几十万词——每个词要用几十万维的向量表示,其中99.999%是0。存储和计算都是灾难。
2.3 致命伤二:语义鸿沟
更要命的是语义全丢了。算一下"猫"和"狗"的相似度:对应位置相乘再相加,结果恒等于0。在one-hot的世界里,"猫"和"狗"的关系 = "猫"和"汽车"的关系 = 毫无关系。词与词之间是两两孤立的孤岛,机器永远不可能知道猫和狗都是动物。
one-hot的失败给出了一个深刻的教训:表示方案的价值不在"区分"词(这个one-hot做得很好),而在"关联"词。谁能让数字承载关联,谁就是下一代方案。
3 ~> word2vec:让词义"住"进向量里
3.1 核心思想:近朱者赤
2013年谷歌提出的word2vec,思想朴素得像句谚语:一个词的含义,由它经常和哪些词一起出现决定。“猫"的上下文里常见"喵、毛、宠物、抓”,“狗"的上下文里常见"汪、毛、宠物、遛”——上下文高度重叠,含义自然相近。
模型干的活:给每个词学一个几百维的稠密向量,使得上下文相似的词,向量也相似。
3.2 著名的向量算术
学出来的向量空间里,语义关系变成了几何关系:
国王 - 男人 + 女人 ≈ 女王 几何解读:"国王"到"男人"的差向量 ≈ 性别方向的偏移 把这个偏移加到"女人"上,落点恰好在"女王"附近这不是魔术,是训练目标的自然结果:“国王"和"女王"的上下文几乎完全一样,唯一的系统性差异就在性别上——这个差异被向量精准地捕捉成了一个"方向”。语义,第一次变成了可以加减的数字。
3.3 遗留问题:一词一向量
word2vec有一个绕不过去的硬伤:一个词只有一个向量。"苹果"在"我吃了一个苹果"和"苹果发布了新手机"里是同一个向量——多义词的所有含义被平均成了一个四不像的表示。
4 ~> BERT:同一个词,不同语境,不同向量
4.1 上下文嵌入
2018年BERT登场,规则改写了:向量不再属于"词",而属于"这个词在这个句子里"。
句子一:"我吃了一个苹果"→"苹果"的向量落在【水果】区域附近 句子二:"苹果发布了新手机"→"苹果"的向量落在【科技公司】区域附近 同一个词,两个向量,各自贴合语境实现这一点的关键机制是注意力(第39篇讲过Transformer):生成"苹果"的向量时,模型会回头看整句话——看到"吃了"就往水果靠,看到"发布、手机"就往公司靠。
4.2 从词向量到句向量
RAG时代我们嵌的不是单个词而是整段文本,句子级Embedding(OpenAI的text-embedding系列、BGE、M3E)就是在BERT类架构上针对"检索"这个任务专门训练的:让"含义相近的句子"在向量空间里离得近——哪怕它们字面完全不同。“如何退款"和"钱怎么退回来”,没有一个字相同,但向量几乎贴在一起。这就是语义搜索碾压关键词搜索的底气。
5 ~> 相似度的数学本质:为什么是余弦
5.1 两个候选方案的较量
欧氏距离:量两个点之间"直线多远"问题:向量一长(文本长、数值大),距离天然变大 → 长文本和短文本永远"看起来不相似",哪怕语义一致 余弦相似度:量两个向量"方向差多少"cos θ=(A·B)/(|A|×|B|)只关心方向,不关心长度 → 免疫文本长短的影响语义藏在"方向"里——这是word2vec时代就确立的经验(“性别方向”“首都方向”),所以检索场景几乎清一色用余弦。取值范围[-1, 1],1表示方向完全一致。
5.2 Python实测:眼见为实
importnumpyasnp# 用三个简化的三维向量模拟(真实是768/1536维,原理相同)vec_cat=np.array([0.9,0.8,0.1])# 猫:动物属性高vec_dog=np.array([0.85,0.9,0.15])# 狗:动物属性高vec_car=np.array([0.1,0.2,0.95])# 汽车:机械属性高defcosine(a,b):returnnp.dot(a,b)/(np.linalg.norm(a)*np.linalg.norm(b))print(cosine(vec_cat,vec_dog))# ≈ 0.999 语义相近 → 方向几乎重合print(cosine(vec_cat,vec_car))# ≈ 0.49 语义疏远 → 方向差得远换成真实API验证也是同样的结论——“猫/狗"的余弦相似度稳定高于"猫/汽车”。这串数字终于回答了导入语的问题:Embedding表示语义的方式,就是把语义翻译成几何。
5.3 降维可视化:亲眼看看语义空间
# pip install scikit-learn matplotlibfromsklearn.decompositionimportPCAimportmatplotlib.pyplotasplt words=["猫","狗","老虎","汽车","卡车","公交","苹果","香蕉","橙子"]vectors=[get_embedding(w)forwinwords]# 调你的Embedding APIpoints=PCA(n_components=2).fit_transform(vectors)plt.figure(figsize=(8,6))plt.rcParams["font.sans-serif"]=["SimHei"]# Windows中文显示for(x,y),winzip(points,words):plt.scatter(x,y)plt.annotate(w,(x,y),fontsize=13)plt.title("Embedding空间的PCA降维投影")plt.show()跑完你会看到一幅非常治愈的图:猫狗虎挤成一团,汽车卡车公交另成一团,水果们远远地聚在第三角——九个词、三簇,没人告诉机器分类标准,语义自己在空间里完成了聚类。这张图值得放进你的每一次技术分享里。
思考 && 总结
- 表示问题的评判标准只有一个:数字之间的关系能否反映语言之间的关系——one-hot输就输在它只"区分"不"关联"。
- one-hot两大致命伤:维度爆炸(几十万维全是0)和语义鸿沟(任意两词相似度恒为0)。
- word2vec的突破是"近朱者赤":上下文相似的词向量相似,语义关系变成了几何关系——"国王-男人+女人≈女王"是训练目标的自然产物。
- BERT解决多义词:向量属于"词在句子中"而非"词本身";句子级Embedding让"字面不同、含义相同"的句子在空间里贴近,这是语义搜索的地基。
- 余弦相似度量的是方向:语义藏在方向里,方向免疫文本长短——所以检索场景用余弦而非欧氏距离。
搞懂了"语义是怎么变成数字的",下一个工程问题随之而来:手里握着一千万个向量,用户一个查询过来,怎么在毫秒级找出最相似的那几个?暴力比对一千万次显然不现实——下一篇讲向量检索算法ANN,看HNSW、IVF、PQ各显神通。
结尾
各位小伙伴,本文的内容到这里就全部结束了,源码骑士在这里再次感谢您的阅读!
源码骑士 — Android Framework & 全栈开发
👀关注:跟博主一起从源码视角深耕底层原理,见证每一次成长
❤️点赞:让优质内容被更多人看见,让知识传递更有力量
⭐收藏:把核心知识点存好,在需要时随时查、随时用
💬评论:分享你的经验或疑问,评论区一起交流避坑
🔄一键四连:不要忘记给博主"一键四连"哦!
🗡️寄语:技术之路难免有困惑,但同行的人会让前进更有方向
结语:Embedding的浪漫之处在于,它把人类语言中最微妙的"意思",翻译成了数学中最刚硬的"方向"——从此语义可度量、可比较、可检索。理解了这层翻译,RAG的每一环对你都将不再是黑盒。不要忘记给博主"一键四连"哦!