跳到主要内容

让文本和图像变回表格 — 特征转换的最后一公里

这一章是全书的收尾,回答一个之前一直被回避的问题: 前面 11 章的算法全都在吃 「二维数字表格」,可现实世界的数据是文章和图片——它们是怎么变成表格的? 答案平平无奇,却是所有真实项目的第一公里:先转换,再学习。

1. 顶层全景

"This is my car" ──┐
"This is my friend" ──┤── 数格子 ──→ [1,1,1,1,0,0,0]──→ 模型
"This is my book" ──┘ ↑
tf-idf:常见词压分、独家词抬分
一张 8×8 的数字图片 ── 拉平 ──→ 64 个像素值排成一列 ──→ 模型

图说:文本按「词」开列,图像按「像素」开列;
列名不同,套路相同——一切都是表格。

原书给文本数据准备了两种转换:基于单词出现次数的,和基于 tf-idf1;图像只有一条路:直接把像素当数值用。

2. 主走查(上半场):三句话,一张计数表

拿原书的三句英文当语料(机器学习用的原始文本材料):"This is my car" / "This is my friend" / "This is my English book"2。按第 05 章词袋的套路开表:

This is my car friend English book
文本1 1 1 1 1 0 0 0
文本2 1 1 1 0 1 0 0
文本3 1 1 1 0 0 1 1

图说:数字为原书表 4-3。列=词表,行=文本,格子=出现次数。

看一眼就能读出文本的「性格」:This、is、my 三列人人都有——它们不携带任何区分信息;car 只在文本 1 出现,原书说它就是「描述文本的一个重要的单词」3但计数表不懂这个道理:它对所有单词平等计数4,This 与 car 在表里都是干巴巴的 1。

3. 主走查(下半场):tf-idf,给单词发工资

tf-idf 用两个数相乘,给每个词按「重要度」发工资5:

  • tf(词频):这个词在本篇文本里出现得越频繁,分越高;
  • idf(逆文本频率指数):包含这个词的文本越多,分越低——「This 这种出现在许多文本中的单词的 idf 就很小」6

拿文本 1 的 This 和 car 实算一遍(计算式是 scikit-learn 的默认口径,原书只给了结果;归一化一步为演示补算):

tf(词频):文本 1 共 4 个词
tf(This) = tf(car) = 1/4 = 0.25 ← 打成平手

idf(按「文本越多分越低」的常用实现):
This:3 篇全含 → idf = 1.00 ← 最低工资
car:3 篇只有 1 篇含 → idf ≈ 1.69 ← 高工资

相乘:This 0.25 × 1.00 = 0.25
car 0.25 × 1.69 ≈ 0.42

归一化(让每行的整体长度为 1):
This → 0.41 car → 0.70

对照原书表 4-4:文本 1 的 This = 0.41,car = 0.70。
分毫不差。

工资表一眼见义:常见词被压到 0.41,独家词抬到 0.70;文本 3 的 English 和 book 也是 0.57 对 0.34 的格局7。原书补了一句现实注脚:行业术语和专有名词这类只在特定文本出现的词,tf-idf 往往很大——「有时能够很好地表示包含这些单词的文本」8

实测:会加权的赢了

光说不练不算数。原书拿 20 Newsgroups 里 4 个主题(二手车、汽车、计算机图形、医学)的真实帖子做分类,同一个线性模型,只换转换方式9:

转换方式验证正确率
单词出现次数(平等计数)0.794
tf-idf(按重要度加权)0.870

7.6 个百分点的差距,全部来自「给单词发不发工资」这一步。原书的判词:tf-idf「很好地抓住了文本数据的特点」10

4. 图像:拉平成向量,以及扔掉的东西

图像这边没有花活。灰度图像(每个像素只记亮度、不记颜色的图像)的每个像素本来就是一个数,拉平成一行就进表:原书示例里,一张图变成 [8, 0, 12, …, 19] 这样的向量11;实际操作用 Pillow 这类图像库逐个像素读取,输出 [250, 255, 216, …, 89]12

原书用一行灰度手写数字验证:8×8 图片拉平后喂给随机森林,前后两半分别当训练和验证,平均正确率 0.8913。按数字拆开看很有信息量:数字 0 的召回率 0.99(几乎不漏),数字 8 只有 0.73——拉平像素的模型,最容易把「圈圈多」的 8 认丢14

代价:二维关系,一拉就没

拉平的账单,原书写得很清楚:像素本来有二维的邻近关系(相邻的像素共同构成笔画),拉平成一行之后,「这个信息被丢弃了」15。第 07 章的手写数字网络同样是 64 个输入,毛病同源。

原书顺手给了出路:有些模型会保留图像的二维关系直接处理,「图像识别中常用的深度学习使用的就是像素的近邻像素的信息」16——这正是那一族保留二维结构的看图模型的入场券。本书到门口为止:如何保住二维结构,是深度学习教材的课题。

5. 作者的判断与证据

说法性质依据
计数 0.794 对 tf-idf 0.870书内代码运行结果(随机成分:新闻组数据固定,划分固定,可复现)输出在书内9
tf-idf 表中 0.41/0.70/0.57书内给出结果,计算过程未展示——我们补的推算与结果吻合表 4-47
「重要的信息被丢弃了」作者的判断,并指名深度学习是对症的那一挂书内陈述15
手写数字 0.89、数字 8 最弱书内代码运行结果输出在书内13
「先可视化再决定线性回归」第 02 章的规矩,本章再遇:可视化和转换同为「学习之前」的工序书内方法论

6. 边界与局限

  • tf-idf 的 idf 有多种实现(随文本数怎么下降、平滑项各不同),原书只给「文本越多值越小」的方向和结果表,没有给公式——复现时以所用工具库的默认实现为准(补充:不在书里,来自通用知识;我们主走查里用的是 scikit-learn 默认口径,与原书数字吻合)。
  • 词袋与 tf-idf 都继承第 05 章的老病:词序信息全丢。「狗咬人」与「人咬狗」同分;相邻词组(n-gram)是常见缓解,原书未提。
  • 图像拉平的 0.89 是「够用但到顶」的分数;保持二维结构的那族看图模型在同一数据上能显著更高——原书只指了方向,没给对比数字。
  • 版本提示:CountVectorizer/TfidfVectorizerLinearSVC 即可复现 0.794/0.870;图像读入用 Pillow 的 Image.open(...).convert('L') 转灰度17

7. 可带走的

  1. 任何数据进模型前先问:它现在是一张数字表格吗? 不是,先转换;
  2. 文本入表两法:计数(平等)与 tf-idf(按重要度加权)——实测后者多赢 7 个百分点;
  3. tf = 本篇词频,idf = 「包含它的文本越多分越低」;乘积再归一化,常见词压到 0.41、独家词抬到 0.70;
  4. 行业术语、专有名词天然高 tf-idf——它们常常就是文本的身份证明;
  5. 图像入表 = 像素拉平;灰度图每像素一个数,直接可用;
  6. 拉平的代价是二维邻近关系归零:数字 8 认丢(召回 0.73)就是账单;
  7. 保住二维关系是深度学习(那一族看图模型)的入场券——原书点到,止步门前;
  8. 转换不是预处理的小配角:同一模型、同一数据,只换转换方式,分数从 0.794 到 0.870——转换即建模

8. 原文地图

主题原书章原文位置
两种文本转换4.2 文本数据的转换处理text/24-ch04-02-4-2.txt:6(搜「一种是基于单词出现次数的转换」)
三句例句4.2 文本数据的转换处理text/24-ch04-02-4-2.txt:26(搜「This is my car」)
计数表4.2 文本数据的转换处理text/24-ch04-02-4-2.txt:33(搜「文本数据中单词出现的次数」)
car 只在文本 1、重要词4.2 文本数据的转换处理text/24-ch04-02-4-2.txt:45(搜「car 只在文本 1 中出现」)
平等计数4.2 文本数据的转换处理text/24-ch04-02-4-2.txt:46(搜「对所有单词都平等地进行计数」)
tf/idf 定义4.2 文本数据的转换处理text/24-ch04-02-4-2.txt:51(搜「逆文本频率指」) · text/24-ch04-02-4-2.txt:53(搜「包含该单词的文本越多,值就越小」) · text/24-ch04-02-4-2.txt:54(搜「这两个指标相乘得到的结果叫作 tf-idf」)
tf-idf 结果表4.2 文本数据的转换处理text/24-ch04-02-4-2.txt:61(搜「0.41」) · text/24-ch04-02-4-2.txt:65(搜「0.57」)
行业术语 tf-idf 大4.2 文本数据的转换处理text/24-ch04-02-4-2.txt:69(搜「较大的 tf-idf 值」)
4 主题分类、0.794 对 0.8704.2 文本数据的转换处理text/24-ch04-02-4-2.txt:84(搜「rec.autos」) · text/24-ch04-02-4-2.txt:108(搜「0.79376193」) · text/24-ch04-02-4-2.txt:124(搜「0.87014640」) · text/24-ch04-02-4-2.txt:111(搜「很好地抓住了」)
灰度图像定义4.3 图像数据的转换处理text/25-ch04-03-4-3.txt:6(搜「每个像素只表示亮度的图像」)
拉平成向量 [8,0,12]4.3 图像数据的转换处理text/25-ch04-03-4-3.txt:20(搜「[8, 0, 12」)
信息丢弃、深度学习入场券4.3 图像数据的转换处理text/25-ch04-03-4-3.txt:28(搜「重要的信息被丢弃了」) · text/25-ch04-03-4-3.txt:29(搜「像素的近邻像素的」)
Pillow 读取、像素输出4.3 图像数据的转换处理text/25-ch04-03-4-3.txt:31(搜「第三方 Python 包 Pillow」) · text/25-ch04-03-4-3.txt:47(搜「[250, 255, 216」)
手写数字前后半划分4.3 图像数据的转换处理text/25-ch04-03-4-3.txt:69(搜「n_samples // 2」)
按数字的报告、avg 0.894.3 图像数据的转换处理text/25-ch04-03-4-3.txt:75(搜「0.94」) · text/25-ch04-03-4-3.txt:83(搜「0.73」) · text/25-ch04-03-4-3.txt:86(搜「avg / total」)

Footnotes

  1. 出处:「4.2 文本数据的转换处理」第 6 段(text/24-ch04-02-4-2.txt:6,搜「一种是基于单词出现次数的转换」)。

  2. 出处:「4.2 文本数据的转换处理」第 26~28 段(text/24-ch04-02-4-2.txt:26,搜「This is my car」)。

  3. 出处:「4.2 文本数据的转换处理」第 45 段(text/24-ch04-02-4-2.txt:45,搜「car 只在文本 1 中出现」)。

  4. 出处:「4.2 文本数据的转换处理」第 46 段(text/24-ch04-02-4-2.txt:46,搜「对所有单词都平等地进行计数」)。

  5. 出处:「4.2 文本数据的转换处理」第 51~52 段(text/24-ch04-02-4-2.txt:51,搜「逆文本频率指」)。

  6. 出处:「4.2 文本数据的转换处理」第 53~54 段(text/24-ch04-02-4-2.txt:53,搜「包含该单词的文本越多,值就越小」;text/24-ch04-02-4-2.txt:54,搜「这两个指标相乘得到的结果叫作 tf-idf」)。

  7. 出处:「4.2 文本数据的转换处理」表 4-4(第 59~65 段:text/24-ch04-02-4-2.txt:61,搜「0.41」;text/24-ch04-02-4-2.txt:65,搜「0.57」)。文本 1 各词:This/is/my 0.41,car 0.70。 2

  8. 出处:「4.2 文本数据的转换处理」第 69 段(text/24-ch04-02-4-2.txt:69,搜「较大的 tf-idf 值」)。

  9. 出处:「4.2 文本数据的转换处理」第 84 段(text/24-ch04-02-4-2.txt:84,搜「rec.autos」)与第 107~108 段(text/24-ch04-02-4-2.txt:108,搜「0.79376193」)。 2

  10. 出处:「4.2 文本数据的转换处理」第 110~111 段(text/24-ch04-02-4-2.txt:124,搜「0.87014640」)与第 111 段(text/24-ch04-02-4-2.txt:111,搜「很好地抓住了」)。

  11. 出处:「4.3 图像数据的转换处理」第 20 段(text/25-ch04-03-4-3.txt:20,搜「[8, 0, 12」)。

  12. 出处:「4.3 图像数据的转换处理」第 31 段(text/25-ch04-03-4-3.txt:31,搜「第三方 Python 包 Pillow」)与第 47 段(text/25-ch04-03-4-3.txt:47,搜「[250, 255, 216」)。

  13. 出处:「4.3 图像数据的转换处理」第 69 段(text/25-ch04-03-4-3.txt:69,搜「n_samples // 2」)与第 86 段(text/25-ch04-03-4-3.txt:86,搜「avg / total」)。 2

  14. 出处:「4.3 图像数据的转换处理」第 75 段(text/25-ch04-03-4-3.txt:75,搜「0.94」)与第 83 段(text/25-ch04-03-4-3.txt:83,搜「0.73」)。classification_report 中数字 0 的召回率为 0.99,数字 8 为 0.73。

  15. 出处:「4.3 图像数据的转换处理」第 28 段(text/25-ch04-03-4-3.txt:28,搜「重要的信息被丢弃了」)。 2

  16. 出处:「4.3 图像数据的转换处理」第 29 段(text/25-ch04-03-4-3.txt:29,搜「像素的近邻像素的」)。

  17. 出处:「4.2 文本数据的转换处理」第 101 段(text/24-ch04-02-4-2.txt:101,搜「CountVectorizer()」)与第 116 段(搜「TfidfVectorizer()」);灰度转换见「4.3 图像数据的转换处理」第 38 段(text/25-ch04-03-4-3.txt:38,搜「convert」)。