🧠 第六章 自然语言处理
📄 一句话概括

5 条提示词哈希到 8 维向量:只差一个「超」字的 P1 和 P2 相似度 0.973, 换了动物的 P1 和 P3 还有 0.886,而同是猫的 P1 和 P4 是 0.914。 最刺眼的是 P3 和 P5——黑狗草地和城市夜景,相似度 0.94。

📝 本节和前面几节的关系

上一节把图变成向量,这一节把提示词变成向量。 两边都变成向量之后,「用图找词」「用词找图」才有可能。

一、打包提示词是什么意思

一条提示词是一串文字:「一只橘猫坐在窗台上,柔光,高清」。 要把它变成一个定长向量,最土的办法是把每个字符的 bigram 哈希到固定几个桶里,累加起来再归一化。 Demo 用 8 个桶。8 维看起来很省,代价是碰撞——不相干的 bigram 会掉进同一个桶。 真实做法是交给 tokenizer 切词,再查训练好的词向量表,最后池化成一个向量。 流程一样,只有「查表」那一步是学出来的。

二、相似度矩阵读出来的东西

P1 和 P2 只差一个「超」字,相似度 0.973。合理。 P1 和 P4 是同一只猫、只换了光,0.914。也合理。 P1 和 P3 是猫换狗,还有 0.886——因为「一只」「坐在」「高清」这些字还在。 P1 和 P5 换成了城市夜景,掉到 0.756。这是差距最大的一对。 四行连起来看,能看出这个表示基本在按「有多少字面重叠」排序,而不是按「意思差多远」。

三、最难看的那个 0.94

P3 是「一只黑狗趴在草地上,逆光,高清」,P5 是「一幅城市夜景,长曝光,高清」。 题材毫不相干,相似度却有 0.94。 原因只有一个:向量只有 8 维,哈希碰撞把不相干的字挤进了同一个桶。 这暴露了一件事——低维哈希不是「压缩」,是「扔掉区分度」。维度不够的时候,所有东西都长得像。 所以真实的句向量维度是 384 到 1536,而且不是哈希出来的,是训练出来的。

四、为什么必须用训练出来的向量

哈希法只抓字面。「高清」和「超高清」很近,因为共享「高清」; 但换成同义不同字的「清晰」,哈希法完全看不出关系。 训练出来的向量抓的是用法:两个词在相似的上下文里反复出现,向量就会靠近。 所以「高清」和「清晰」会靠近,即使一个字都不重。 这一章从 6.3.1 的共现矩阵开始,一路讲到这里,其实就是一句话: 向量应该是统计出来的,不是拼出来的。 哈希是能跑通流程的替代品,用来验证「整条链路通不通」。 验证完就该换掉——这也是我在 Demo 里如实标出 0.94 那个数难看的原因。

五、动手 Demo:提示词 Embedding:8 维哈希打包与相似度矩阵

取 5 条提示词,把每条按字符 bigram 哈希到 8 个桶,累加计数后除以模长做归一化; 打出 5×5 的余弦相似度矩阵;再单独列出四对提示词的相似度,看同义改写、换主体、换题材各掉多少。

for g in bigrams(s):
    h = 0
    for ch in g:
        h = (h * 131 + ord(ch)) % 1000003
    v[h % dim] += 1.0
v = v / (np.linalg.norm(v) + 1e-12)

实跑输出:

--------------------------------------------------------------------
提示词 Embedding:把一句话打包成定长向量
--------------------------------------------------------------------
  提示词条数               5
  向量维度                 8(字符 bigram 哈希到 8 个桶)
  归一化                   逐个除以模长
  P1                       一只橘猫坐在窗台上,柔光,高清
  P2                       一只橘猫坐在窗台上,柔光,超高清
  P3                       一只黑狗趴在草地上,逆光,高清
  P4                       一只橘猫坐在窗台上,硬光,低清
  P5                       一幅城市夜景,长曝光,高清

         P1     P2     P3     P4     P5
  ------------------------------------
  P1   1.00   0.97   0.89   0.91   0.76
  P2   0.97   1.00   0.90   0.96   0.82
  P3   0.89   0.90   1.00   0.78   0.94
  P4   0.91   0.96   0.78   1.00   0.71
  P5   0.76   0.82   0.94   0.71   1.00

  P1 vs P2                 0.973(只差「超」一个字)
  P1 vs P4                 0.914(同一只猫,光不同)
  P1 vs P3                 0.886(猫换狗)
  P1 vs P5                 0.756(完全换题材)

  看出来了吗:P1 和 P3 换了动物,相似度仍然比 P1 和 P5 高——因为「一只」「坐在」这些字还在。
  更难看的是 P3 和 P5:一个是黑狗草地,一个是城市夜景,题材毫不相干,相似度却有 0.94。原因只有一个——向量只有 8 维,哈希碰撞把不相干的字挤进了同一个桶。
  「高清」和「超高清」很接近,是因为字面重叠;如果换成同义不同字的「清晰」,这个哈希法就完全看不出关系了。
  所以哈希只抓字面,不抓语义,维度一低连字面都抓不准。真 embedding 是训练出来的,这是下一章要讲的事。

矩阵对角线全是 1.00,这是自己和自己算余弦的必然结果,没有信息量。 真正要看的是非对角那 20 个数。 P1 那一行从 0.973 到 0.756,跨度 0.217——四条提示词的差别不算小,但也没拉开。 P3 和 P5 的 0.94 是整张表最该记住的数。 两个毫不相干的东西拿到 0.94,说明这个表示已经失去区分能力。 根子在 8 个桶:22 个字左右的提示词会产生 20 多个 bigram,平均每个桶塞两三个,碰撞几乎是必然的。

30 秒实验

  1. 把维度从 8 改成 64,重跑,看 P3 和 P5 相似度掉到多少。
  2. 把「高清」换成「清晰」,看 P1 和 P2 的相似度会不会掉——这是哈希法抓不到同义的证据。
  3. 想一想:为什么训练出来的向量能抓住「高清」和「清晰」的关系?

常见误区

  1. 「哈希也是一种 Embedding」——它只抓字面,不抓语义,维度一低连字面都抓不准。
  2. 「维度低省事」——8 维下所有提示词都长得像,检索完全失效。
  3. 「相似度高就是意思像」——P3 和 P5 的 0.94 是反例。
自测三问(点开对答案) 1. 为什么 P1 和 P2 只差一个字,相似度就这么高? —— 字符 bigram 大部分重叠,哈希桶里的计数几乎一样。 2. P3 和 P5 题材完全不同,相似度却有 0.94,原因是什么? —— 向量只有 8 维,哈希碰撞把不相干的字挤进同一个桶,区分度被扔掉了。 3. 训练出来的向量比哈希法强在哪? —— 它抓的是用法和上下文,所以同义不同字(高清和清晰)也能靠近。

第六章到此结束。下一章换一个完全不同的活:数据标注——这是训练师日常干得最多、也最枯燥的一块。

相关笔记