同一句话在字符层要 33000 个数(11 个码位各一个 3000 维 one-hot),词层 56000 个, 句法层只要 9 个标签,语义层 8 个实数。从 33000 压到 8,压了 4125 倍。
上一节说了「一句话进来要变成什么」,这一节把这四种「变成」摊开看,比一比它们各要多少个数、 各丢掉了什么。
一、四层表示,四种代价
同一句话可以停在四个层面上表示,越往下越抽象,越抽象越省地方: 1. 字符层。11 个码位,每个用 3000 维 one-hot。合计 33000 个数。 2. 词层。7 个词,每个用 8000 维 one-hot。合计 56000 个数。 3. 句法层。3 条依存边,每条 3 个标签。合计 9 个数。 4. 语义层。1 个句向量,8 维。合计 8 个数。 注意词层比字符层还大:词表比字表长,词又比字少得不够多,一乘反而涨了。 这就是 one-hot 的毛病——它不带任何相似性信息。
二、句法层:三条边就说清了谁修饰谁
Demo 里的三条边是:拍 用 手机、拍 拍 照片、拍 施事 小明。 这三条边表达的信息,比 7 个词的顺序多得多:它说清了「拍」是中心,手机是工具,照片是对象, 小明是施事。 而全部成本只有 9 个数。这就是结构化表示的威力——它把人能看懂的关系直接写成了数据。 代价是要有人(或一个句法分析器)把树建出来。建错了,后面全错。 所以现在很少有人手工建树,都让模型自己学。
三、语义层:8 个数代表一整句
Demo 的 8 维向量是我手工定的:前六维分别是拍照、天气、工具、室内、人物、静物,后两维填零占位。 本句和「他用相机拍了几张照片」的余弦是 0.989——几乎一样,因为两句都是「人用工具拍东西」。 和「今天天气很好」的余弦只有 0.229。差得很干净。 这 8 个数是我拍的,不是学出来的。 所以它准不准,取决于我定的维度对不对——这正是「表示学习」要解决的问题:让人定维度,改成让数据定。
四、4125 倍是怎么来的
33000 除以 8,得 4125。这个数字好看,但要看清它压掉了什么。 字符层保留了全部字面,一个字都没丢; 语义层只保留「说的是拍照」这件事,具体用了什么词、什么句式,全没了。 所以压缩不是白来的:你要什么,就留什么。要字面相似度,别用语义向量;要抗同义改写,别用字符。 真正难的不是压,是「压完之后还够用」。这件事没有通用答案,只能按下游任务试。
五、动手 Demo:一句话在四层上的表示与成本
同一句话分别按字符、词、依存句法、语义向量四种方式表示,打出每层要多少个数;把三条依存边列出来; 再用两个手工定的 8 维句向量和本句算余弦,最后算字符层到语义层的压缩倍数。
V_CHAR, V_WORD = 3000, 8000 # 假设的字表、词表大小
cost_char = len(s) * V_CHAR # 11 × 3000
cost_word = len(ws) * V_WORD # 7 × 8000
cost_dep = 3 * 3 # 3 条边 × 3 个标签
cost_sem = 8 # 1 个 8 维向量
实跑输出:
--------------------------------------------------------------------
语言学与计算机科学的交汇:一句话在四层上的表示
--------------------------------------------------------------------
层 单元数 表示形式 元素个数
-----------------------------------------------
字符层 11 个码位 one-hot 3000 维 33000
词层 7 个词 one-hot 8000 维 56000
句法层 3 条依存边 每条 3 个标签 9
语义层 1 个句向量 8 维实数 8
句法层的三条边:
中心词 关系 依存词
---------------------
拍 用 手机
拍 拍 照片
拍 施事 小明
语义层的 8 维向量(手工定的六个维度加两个填充):
本句 [0.8, 0.1, 0.9, 0.2, 0.7, 0.3, 0.0, 0.0]
他用相机拍了几张照片 [0.7, 0.2, 0.9, 0.1, 0.6, 0.4, 0.0, 0.0]
今天天气很好 [0.1, 0.9, 0.0, 0.8, 0.1, 0.0, 0.0, 0.0]
本句 vs 拍照那句 0.989
本句 vs 天气那句 0.229
字符层元素个数 33000
语义层元素个数 8
压缩倍数 4125 倍
从 33000 个数压到 8 个数,还不丢「说的是拍照」这件事——这就是表示学习要干的活。
第一张表最扎眼的是词层 56000 比字符层 33000 还大。 这不是错,是 one-hot 的必然结果:维度等于表大小。 句法层只要 9 个数,却把「谁修饰谁」说清了。这说明表示的好坏不看长度,看它装没装关系。 两个语义余弦 0.989 和 0.229 差距很大,但这个向量是我手写的六维打分, 不是学出来的——它能拉开差距,是因为维度是我照着这两句的差别定的,属于自证。 最后一行的 4125 倍,是字符层个数除以语义层个数。 这个倍数只说明「省了多少」,不说明「丢了多少」。
30 秒实验
- 把字表假设成 6000 维,重跑,看压缩倍数变成多少。
- 给句子再加一条依存边,看句法层成本从 9 变成多少。
- 想一想:为什么 one-hot 表示不出「手机」和「相机」很像?
常见误区
- 「层数越深表示越好」——每一层丢的东西不同,选错层下游就废。
- 「词表示一定比字表示小」——one-hot 下词层反而更大。
- 「压缩越多越先进」——压掉的可能是任务正需要的信息。
自测三问(点开对答案)
1. 为什么词层的 one-hot 总量会比字符层还大? —— 维度等于表大小,词表比字表长得多,词数又没少到能抵消。 2. 句法层只花 9 个数就表达了什么? —— 三条依存边,说清中心词、关系、依存词,也就是谁修饰谁。 3. 从 33000 压到 8,压缩的代价是什么? —— 字面和句式全丢了,只剩一个粗粒度的语义方向。四层看完了,下一节比两条技术路线:手工特征的老路和端到端的新路。
- ☐ (本节完,下一节 6.1.3 自然语言处理的两种途径:传统与深度)