一句话「小明用手机拍了一张照片」11 个字,按词表最长匹配切成 7 个词,平均词长 1.57 字; 判意图时「拍照」命中 2 个词胜出; 和「他用相机拍了几张照片」的 bigram 余弦 0.435,和不相关的一句是 0.000。
前五章从职业讲到深度学习。从这一章起进入自然语言处理——也就是让机器处理人话。 第一节先把这门活的范围划清楚。
一、这道沟到底在哪
人能读一句话,是因为脑子里有词、有语法、有常识。机器眼里只有一串编码。 自然语言处理要干的事,就是在「一串编码」和「一句话的意思」之间搭桥。 这座桥有三段:先把串切成人能叫出名字的单位(词),再给这些单位贴上标签(词性、实体、关系), 最后算出它们的向量表示。 三段做完,才有后面的分类、检索、翻译、对话。缺一段,后面全是空中楼阁。 所以这门学科的入门不是学模型,是先认清「一句话进来要变成什么」。
二、先切成什么:字还是词
中文和英文最大的差别在这里:英文有空格,词是现成的;中文没有。 Demo 里同一句话,按字切是 11 个单元,按词表最长匹配是 7 个词,平均词长 1.57 字。 为什么不用字?因为单个字带的信息太少——「手」和「机」分开,跟「手机」是两回事。 为什么不用词?因为词表永远不全。「摆龙门阵」这种说法,词表里没有就得拆碎。 实践中的折中是「子词」:把罕见词拆成常见片段。这样词表可控,又不会把常用词拆散。 这个思路后面讲大模型时还会遇到。
三、四个最小任务
Demo 拿一句话跑了四件事,这四件事基本覆盖了 NLP 的底层动作: 1. 切分。把串切成单位。11 个字切成 7 个词。 2. 标注。给每个单位贴标签。这句的词性序列是名词、动词、名词、动词、助词、数量词、名词。 3. 分类。整句归到某个类别。 三个候选意图里「拍照」命中「拍」「照片」两个词,得 2 分,另外两个 0 分。 4. 相似度。两句有多像。 和「他用相机拍了几张照片」算是 0.435,和「今天天气很好」算是 0.000。 这四个动作能组合出几乎所有上层任务:搜索是相似度,审核是分类,信息抽取是标注,翻译是切分加生成。
四、0.435 这个数说明了什么
两句说的是同一件事,余弦只有 0.435,不到一半。为什么这么低? 因为 bigram 只数相邻两字的字面重叠。 「小明」和「他」完全不同,「一张」和「几张」也不同,只有「拍」「照片」附近能对上。 这说明字面相似度天生偏低。真实系统不会只用它,要么换词向量算,要么加同义词表。 但 0.435 对 0.000 这个对比是有意义的:它至少把「有关」和「无关」分开了。 很多工程问题的第一版就停在这个水平——够用,而且能解释。 先要能解释,再要准。反过来做,出了问题查不下去。
五、动手 Demo:一句话跑通四个最小任务
取一句话,先按字切一遍、再用手工词表做最长匹配切一遍;给切出来的词贴词性; 用三张关键词表判意图,看谁得分高;最后和另外两句各算一次字符 bigram 余弦,比出有关和无关的差距。
keys = sorted(lex, key=lambda x: -len(x[0])) # 长的先试
while i < len(s):
for k, t in keys:
if s.startswith(k, i):
out.append(k)
i += len(k)
break
else:
out.append(s[i]) # 未登录字
i += 1
实跑输出:
--------------------------------------------------------------------
什么是自然语言处理:一句话跑通四个最小任务
--------------------------------------------------------------------
输入句子 小明用手机拍了一张照片(11 字)
任务 1:切分
按字切 11 个单元
按词表最长匹配 7 个词
切分结果 小明 / 用 / 手机 / 拍 / 了 / 一张 / 照片
平均词长 1.57 字
任务 2:标注词性
词性序列 小明/名词 用/动词 手机/名词 拍/动词 了/助词 一张/数量词 照片/名词
未登录词 0 个
任务 3:分类(判意图)
候选意图 命中的词 得分
-------------------------
拍照 拍、照片 2
通话 — 0
上网 — 0
判为 拍照(得分 2)
任务 4:算相似度
对比句 他用相机拍了几张照片
余弦相似度 0.435
完全不同的一句 今天天气很好 → 0.000
四个任务分别对应分词、标注、分类、相似度,这就是自然语言处理最底层的四类动作。
切分那段两个数:11 和 7。 平均词长 1.57 字,这个数在中文里算正常(常用词两字居多,掺了单字虚词就拉低了)。 词性序列里没出现「未登录」,是因为这句话我特意选了词表覆盖得到的。 换个新词,「未登录」立刻会冒出来。 意图打分那三行说明一件事:分类可以不靠模型,靠命中计数就能跑通。当然它只在关键词明确时管用。 相似度 0.435 对 0.000——同一件事的两句话连一半都不到,这是字面匹配的天花板,不是代码写错。
30 秒实验
- 把这句话换成「他用手机拍了一张照片」,看余弦涨到多少。
- 往词表里加三个词,让「一张照片」整体成一个词,看词数变成几个。
- 想一想:为什么中文分词比英文难?
常见误区
- 「NLP 就是聊天机器人」——聊天只是它的一小块,切分、标注、检索都算。
- 「分词是小事」——切错了,后面每一步都建在错的基础上。
- 「相似度低就是不像」——字面相似度天生偏低,同义改写它看不出来。
自测三问(点开对答案)
1. 为什么中文必须先分词,英文不用? —— 英文有空格天然分界,中文没有,词的边界得算出来。 2. 为什么实践中用子词而不是整词? —— 整词词表永远不全,子词能在「词表可控」和「不拆散常用词」之间折中。 3. 两句说同一件事,余弦却只有 0.435,说明什么? —— 字面重叠天生偏低;同义改写靠 bigram 匹配不出来。范围划清了,下一节往下一层看:一句话在四个层面上分别长什么样。
- ☐ (本节完,下一节 6.1.2 底层原理:语言学与计算机科学的交汇)