【零基础学AI】第 25 章——计算机怎样处理文字

第 25 章 计算机怎样处理文字

文章目录

前面几章的图片已经是一组像素数字。现在把输入换成"我用电脑学习 Python",程序不能直接用汉字做矩阵乘法。它需要先确定输入单位,给这些单位编号,再把编号转换成向量。

本章从字符、词和子词切分开始,运行一个小型子词合并程序,再比较几组句子的相似度。需要第 13 章的数组与向量知识,以及第 21 章的输入、参数和网络直觉。随附 Notebook已经实际执行。

🌈 关于《AI 零基础 36 讲》

🧠 零基础也能开始学 AI

《AI 零基础 36 讲》是一套面向初学者的 AI 入门教程。课程从认识和使用 AI 开始,逐步学习

Python、数据处理、机器学习与深度学习,再进入大模型应用开发,最后完成个人知识库助手的综合实践。

📖 本篇是正式讲解文章

通过具体例子、原创图示和操作结果讲清概念。涉及编程的章节提供可运行代码,方便你边读边试。

🎯 读完以后,动手检验

建议按专栏顺序学习,并完成对应的课后训练,检查自己能否独立运用本章知识。

博客专栏:《AI 零基础 36 讲》

同一句话,为什么会切出不同数量

看一条原创教学句子"我用电脑学习Python"。按字符切分,会得到 12 个字符;按本章给定的词表,可以切成"我、用、电脑、学习、Python"五个单位。Token 就是模型处理文本时采用的切分单位,可能是一个字符、一个词,也可能是一个词的一部分。

python 复制代码
from examples.text_core import load_data, tokenize_words
data = load_data()
text = data["sentences"][0]
print(list(text))
print(tokenize_words(text, data["vectors"]))

词表切分结果为 ['我', '用', '电脑', '学习', 'Python']。这里的函数采用从当前位置选最长已知词的规则。例如词表同时有"学"和"学习",遇到"学习"时优先选择两个字的词。

中文没有用空格标出所有词的边界,固定词表可能遇到歧义。英文的空格也不能保证一个完整单词只占一个 Token,因为实际分词器可能继续做子词切分。因此 Token 数量依赖具体规则、词表与输入文字,本章五个 Token 的结果不能套到所有模型。代码中的 list(text) 是 Python 字符切分,对于本章普通文字足够直观,复杂组合 emoji 的显示单元还可能由多个 Unicode 字符组成。

用子词覆盖未见过的组合

按完整词建立词表,会遇到新词、词形变化和拼写组合。子词方法把经常出现的片段保存下来,用多个片段表达更长的输入。BPE 是一种常见的相邻片段合并方法,入门规则可在 Hugging Face 的 BPE 教程学习。

我们自行设置六个英文教学词及频次,low 出现 5 次,lower 2 次,lowest 1 次,new 3 次,newer 2 次,newest 1 次。先把每个词切成字母,统计相邻片段对的出现次数,优先合并最常见的一对,再重新统计。

第一轮中 l 与 o 相邻的次数是 5+2+1=8,o 与 w 也有 8 次。为了得到固定结果,本章并列时按字典序选取,因此先合成 lo。下一轮把 lo 和 w 合成 low。六轮真实运行结果如下。

轮次 合并的两个片段 加权次数 新片段
1 l 与 o 8 lo
2 lo 与 w 8 low
3 e 与 w 6 ew
4 n 与 ew 6 new
5 e 与 r 4 er
6 e 与 s 2 es
python 复制代码
from examples.text_core import load_data, train_bpe, tokenize_bpe
rules, splits, alphabet = train_bpe(load_data()["bpe_word_counts"])
print(splits["lower"])
print(splits["lowest"])
print(tokenize_bpe("newlow", rules, alphabet))

结果依次为 ['low', 'er']、['low', 'es', 't']、['new', 'low']。newlow 是专门构造的未见组合字符串,不是本章要求读者记忆的真实英语词。它没有进入词频表,但能用已有片段表示。lowest 中保留下来的单个 t 也说明,子词不一定恰好等于有语言意义的词根或词缀。

这里实现的是字符级、词内合并的缩小版 BPE,没有真实模型的全部预处理、特殊 Token 和字节回退。它只能处理给定基础字符,不覆盖任意文字。实际字节级 BPE 还会用字节作基本单位,本章程序没有实现那一部分。随附合并记录保留每轮的片段与次数,读者无需下载模型就能复核算法。

编号只是向量表的行号

词表是已知 Token 的集合。给词表里的每个 Token 分配一个整数编号,程序就能用编号定位一行向量。Embedding 通常指这种把离散单位映射成连续向量的表示。

本章词表按固定字符串顺序排列。"我、用、电脑、学习、Python"的编号为 13、20、21、10、0。这些数字是任意编号,不表达含义远近。编号 20 和 21 相邻,不能推出"用"和"电脑"语义最接近;交换词表编号并同步交换向量表行,查到的表示仍然相同。

python 复制代码
from examples.text_core import load_data, vocabulary_and_matrix
data = load_data()
ids, matrix = vocabulary_and_matrix(data["vectors"])
print(matrix.shape)
print(ids["电脑"], ids["计算机"])
print(matrix[ids["电脑"]], matrix[ids["计算机"]])

向量表为 26×4,两词的编号不同,但查到的向量均为 [1, 0, 0, 0]。词数和维度分别是两个轴,编号只决定取哪一行。

先用一张透明的教学向量表

真实模型中的词向量往往通过训练得到,各维度通常不能直接读成一个确定主题。为了看清机制,本章手工指定四个方向,分别代表电脑与编程学习、猫与家具、下雨与雨具、购物与水果。这张表是原创教学设定,没有训练或下载语义模型,也不能当作实际语义模型测评。

"电脑"和"计算机"都取 [1,0,0,0],"小猫""猫咪""桌子""书桌"都取 [0,1,0,0]。"我""在""上"等词取零向量。这种设置刻意把相近主题放到同一方向,却也把猫和桌子压成了同样的表示。它保留了我们选择的内容,丢掉了我们没有表示的差别。

句向量是整句话的向量。本章把各 Token 向量取平均。"我用电脑学习Python"中五个 Token,有三个落在第一方向,另外两个为零,所以得到 [0.6,0,0,0]。平均是为了便于演示,不能理解成所有句向量模型的完整计算方式。真实的句子表示方法还可能结合上下文和专门训练目标。

python 复制代码
from examples.text_core import load_data, sentence_vector
data = load_data()
vector, tokens, ids = sentence_vector(data["sentences"][0], data["vectors"])
print(tokens)
print(vector)

输出五个词和 [0.6 0. 0. 0.]。这一步将变长 Token 序列压成固定四维向量。平均同时丢掉词序,"猫在桌上"和调整顺序后的文字可能得到相同表示,后面要始终记着这个限制。

余弦看方向,字面计数看重合

第 13 章介绍过点积。余弦相似度用两向量的点积除以各自长度的乘积,考察方向关系。对非零实向量,它在 -1 至 1 之间,同方向为 1,垂直为 0,反方向为 -1。本章所有计数和人工向量都非负,因此这里实际结果在 0 至 1 之间。

python 复制代码
from examples.text_core import cosine
print(round(cosine([1, 2], [10, 20]), 6))
print(cosine([1, 0], [0, 1]))
print(cosine([1, 0], [-1, 0]))

结果为 1.0、0.0、-1.0。把向量整体乘以正数不会改变方向,所以第一个结果仍为 1。余弦也没有自动计算事实真假,它只能比较已经选定的表示。

我们另外建立字符计数向量。所有句子使用同一张字符表,每个位置记录某个字符在句子中出现几次。这样计算出的相似度反映字符重合,是词法层面的近似比较。本章使用"词法"这个词概括文字表面的重合,具体实现采用字符列计数。

看五组句子的真实计算结果

比较 字符计数余弦 人工主题向量余弦
我用电脑学习Python/我在计算机上学编程 约 0.192450 1.000000
我用电脑学习Python/我今天在电脑上买水果 约 0.273861 约 0.447214
我用电脑学习Python/今天下雨带雨伞 0.000000 0.000000
小猫坐在桌子上/猫咪趴在书桌旁 约 0.428571 1.000000
猫在桌上/猫不在桌上 约 0.894427 1.000000

第一组用了不同说法,字符重合低。人工表预先把电脑、计算机、学习、编程等词放在同方向,因此主题余弦为 1。这个结果来自我们指定的表示,不能用它证明程序自主学会了近义关系。

第二组共享"我"和"电脑"等字面信息,字符分数反而比第一组高。但它多了购物与水果方向,和编程学习句向量夹角增大,主题分数降到约 0.447214。第三组在本章表中没有共享方向,因此两个分数都为零。

第四组谈的是相近场景,但"坐"和"趴"并非相同动作。人工向量把动作词设为零,丢掉了这个区别。第五组则更直接,"不"同样被设为零,肯定句与否定句的主题向量方向完全相同,分数仍为 1。高分只说明表示相近,没有检查两句陈述是否能同时成立。

因此词法相似和语义相似要分别观察。真实训练出的语义表示能够利用比字符重合更丰富的信息,但结果仍受训练、上下文和任务影响。拿到一个很高的相似度分数以后,还需单独检查否定、数字、时间和主体关系。本章的透明小表让这些遗漏直接显露出来。

未知词和零向量怎样处理

本章词表遇到"量子"会明确报错,不会悄悄丢掉两个字。修复示例先用已有词"电脑"运行;若只想看新文字的字符,可以得到 ['量','子'],但这并没有为两个字提供语义向量。真实分词器可能使用未知 Token、子词或字节规则,具体方法要按所选模型核对。

零向量没有方向,余弦分母为零。本章"我在上"的词全被设成零,不能拿它计算方向相似。修复版捕获错误,明确说明原因,再对有内容的向量运算,没有擅自把零向量相似度写成 1。

运行 Notebook 后,试着给数据文件中的"坐"和"趴"增加不同方向,观察第四组的结果怎么变化。保存原文件副本,并把修改说成新的教学设定。完成【零基础学AI】第 25 章课后练习与答案后,下一章会让每个 Token 根据其他位置的信息,计算注意力权重并汇总向量。

相关推荐
一知半解仙11 分钟前
乌镇2026:当“智能互联网”第一次被数据照进现实
人工智能·物联网·机器人·开源
泯泷37 分钟前
AI 最坑的失败:不是不会做,而是"假装做完了"
人工智能·llm·agent
Alluxio1 小时前
Alluxio + OCI:为 AI 工作负载实现亚毫秒访问延迟与可扩展吞吐
运维·数据库·人工智能·分布式·缓存·ai·语言模型
johnsong1 小时前
Claude Fable 5.2 登顶:65 分、单发做游戏,和一份 $26.54 一单的账单
人工智能·游戏
凌杰1 小时前
AI 学习笔记:Transformer 架构详解
人工智能
硅谷秋水2 小时前
扩展机器人智能体的在线探索能力
人工智能·语言模型·机器人
Eyfcom2 小时前
〖高级算法实战 04〗物流定价博弈论:动态定价算法如何平衡运力供需与利润?
人工智能·物流管理系统·高级算法实战·众包物流
锋行天下2 小时前
服务器 Python 2.7 装不了 langgraph-cli?用本地生成 Dockerfile 曲线救国
人工智能·后端·python