跳转至

P2-13.1 图表(plot)会揭示什么

Section ID: P2-13.1 Version: v2026.07.23

在 Part 2 Chapter 11,我们用 NumPy 数组确认计算;在 Part 2 Chapter 12,我们用 Pandas DataFrame 读取表格数据。现在,我们把同样的数字改成图形来观察。

表格适合查看精确数值。但当数字变多时,只看表格就很难回答下面这些问题。

  • 数值是在上升还是下降?
  • 有没有某个值特别突兀?
  • 两个值是否一起变化?
  • 数据是否集中在某一侧?
  • 计算结果的形状是否和我预想的差不多?

图表不是把数字装饰得更好看的工具。它是用来检查表格里不容易立刻看出的形状(shape)、变化(trend)、关系(relationship)和分布(distribution)的工具。先抓住这个工具,到了 Part 3,你才能把学习曲线、误差分布、变量关系读成可解释的形状,而不只是一串数字

本节说明 plotFigureAxes、分布(distribution)、异常值(outlier)的基本区分。上一章 Pandas 讨论的是,一组数字应该怎样读成“案例与变量的表”;这一节讨论的是,对于表里不直接显现的变化和关系,要用什么样的形状去确认。作图不是结果美化阶段,而是先检查那些在表格中容易漏掉的模式,例如 loss 的变化、分布是否偏斜、变量之间是否有关联。Chapter 14 会继续讨论:看完这些图之后,怎样把“改了什么”“哪里和预期不同”记录下来。继续到图表选择和保存时,也请一起参考概念词汇表

核心判断标准:图表(plot)会揭示什么

  • 能把图表解释为“检查数据形状的工具”。
  • 能说明表格擅长精确值,而图表擅长检查模式。
  • 能说明图表可以用来检查变化、关系、分布与异常值。
  • 能把 Matplotlib 中的 Figure 区分为“整张图”,把 Axes 区分为“真正绘制数据的坐标区域”。
  • 能说明图表给人的印象并不总是原因或结论。

三个判断标准

标准 为什么重要 本节需要达到的理解程度
为什么只靠表格还不够 它能明确表格与图表的角色差异。 理解有些形状和趋势不会直接从数字列表中显现。
图表擅长展示什么 它让后面的图表选择变成“围绕问题阅读”,而不是背图表名字。 把图表理解成能更快读取变化、比较、分布等问题的工具。
应该先决定什么 它促使你先立解释问题,再去记图表名称。 理解应先决定要问什么问题,再决定图表类型。
术语 本节先抓住的含义
plot 用视觉方式检查数值数据的形状、变化和关系的图。
Figure 放置整张图表的大区域。
Axes 实际绘制数据的一个坐标区域。
distribution 显示数值集中在哪里、分散到什么程度的形状。
outlier 与其他数值相比显得特别突出的值。

表格擅长看值,图表擅长看形状

先看下面这张表。

epoch loss
1 2.40
2 1.65
3 1.12
4 0.86
5 0.79

从表格里,你可以读到每个精确数值。但如果你想快速确认训练是否进行得顺利,很多时候比起一个个值,更重要的是整体走势。

把同样的数据画成折线图(line plot)后,就能更快看出 loss 大致是在下降。

问题情境:表格中的数字很精确,但很难一眼抓住数值会怎样随着重复步骤变化。 输入(input):5 个 epoch 编号和每个 epoch 对应的 5 个 loss 值。 期望输出(output):一张显示 epoch 增加时 loss 如何变化的折线图。 要确认的概念:表格揭示的是数值本身,图表更快揭示的是变化的形状,因此像训练损失这样带有顺序的值,通常更自然地用折线图来读。

# 这个例子用 Matplotlib 绘制 loss、分布和关系,让表格中不明显的模式变得可见。
import matplotlib.pyplot as plt

epochs = [1, 2, 3, 4, 5]
loss = [2.40, 1.65, 1.12, 0.86, 0.79]

fig, ax = plt.subplots()
ax.plot(epochs, loss, marker="o")
ax.set_xlabel("epoch")
ax.set_ylabel("loss")
ax.set_title("Loss decreases over epochs")
plt.show()

运行上面的代码后,你可以看到一条“随着 epoch 增加,loss 下降”的曲线形状。

Loss decreases over epochs

本书的资产文件夹中,也保留了可以把同一示例重新生成成文件的保存型脚本。直接在屏幕上确认时,可以像上面那样使用 plt.show();需要重新生成文档中使用的 PNG 时,则运行 p2_13_1_plot_questions.py

这个例子里重要的不是代码语法,而是“loss 会不会随着重复学习而下降?”这个问题。

表格告诉你的是精确数值,图表展示的是变化的形状

再往前一步看,即使汇总数字看起来一样,图形的形状也可能不同。比如,两次动作记录的单次汇总均值都可能是 1.5,但一边可能从头到尾几乎平稳,另一边可能在中间明显升高后又下降。只看表里的均值,两者会显得相似;而折线图会让你重新确认,这种看起来相似是否真的代表同样的模式。

动作记录 平均值 图表更容易看出的点
A 1.5 是否几乎一直保持平稳
B 1.5 是否在中间明显升高又下降

也就是说,图表不是把数字写得更漂亮的工具,而是让你重新检查:那些在“单行汇总中的一个代表值”里容易被忽略的运动形状,究竟是什么样子。

把同一个场景写得更像表格一些,可以是下面这样。

action_id sensor_a_mean sensor_a_std early_segment_mean late_segment_mean
B-201 27.0 0.4 26.8 27.2
B-202 27.0 1.6 25.5 28.5

这张表说明:均值可以相同,但波动程度和区段模式可能不同。所以,如果表格已经让你怀疑“均值一样,但结构可能不同”,图表就是把这种怀疑进一步变成可见形状的下一步。

这里要注意的是,图表也许能更清楚地显示“是否存在模式差异”,但它不会自动解释这种差异的原因。

问题情境:你想直接用折线图比较两个“均值相同但模式不同”的动作。 输入(input):两个动作在各个区段上的数值列表。 期望输出(output):两条均值相同但形状不同的折线。 要确认的概念:折线图可以重新揭示那些被“平均值”这类单一汇总数掩盖掉的差异。

# 这个例子用 Matplotlib 绘制 loss、分布和关系,让表格中不明显的模式变得可见。
import matplotlib.pyplot as plt

steps = [1, 2, 3, 4]
action_a = [1.0, 2.0, 2.0, 1.0]
action_b = [1.5, 1.5, 1.5, 1.5]

fig, ax = plt.subplots()
ax.plot(steps, action_a, marker="o", label="action A")
ax.plot(steps, action_b, marker="o", label="action B")
ax.set_xlabel("segment")
ax.set_ylabel("signal level")
ax.set_title("Same mean, different pattern")
ax.legend()
plt.show()

看这张图时,读者应先检查下面几点。

  • 即使均值看起来相近,内部结构也可能不同。
  • 表格会让人产生“看起来一样”的怀疑,图表则让你检查那是否真的是模式差异。
  • 图表会揭示那些单靠一个均值容易漏掉的模式差异。
  • 即使均值相同,模式也可能不同,但图表不会自动说明其原因。

图表揭示的四个问题

这里把图表视为用来回答以下四类问题的工具。

问题 图表帮助做什么 例子
变化(trend) 看数值如何随时间或顺序移动 按训练 epoch 观察 loss
关系(relationship) 看两个值是否一起变化 学习时间与分数
分布(distribution) 看数值集中在哪里 分数分布、误差分布
异常值(outlier) 看是否存在特别突出的值 传感器错误、输入错误

这四个问题以后会不断出现。

  • 在机器学习里,会看训练中的 loss 和 metric。
  • 在数据分析里,会看变量之间的关系与分布。
  • 在深度学习里,会看学习曲线、预测误差、嵌入可视化等。

所以目标不是“我会画图”,而是“我会问这些数字正在形成什么样的形状”。

同样的数字,会因为问题不同而看起来不同

例如,再看四位学生的数据。

name study_hours score
Kim 2 62
Park 4 71
Lee 6 82
Choi 8 88

如果你想看这张表里的数值本身,直接读表就可以。但如果你想问“学习时间增加时,分数也会一起提高吗?”,散点图(scatter plot)会更自然。

问题情境:当你想看两个值是否一起变化时,点的位置安排有时比表格更容易读。 输入(input):学习时间列表 study_hours 和分数列表 scores。 期望输出(output):把每个学生表示成一个点的散点图。 要确认的概念:散点图能同时展示两个变量的关系候选与分散程度。

# 这个例子用 Matplotlib 绘制 loss、分布和关系,让表格中不明显的模式变得可见。
import matplotlib.pyplot as plt

study_hours = [2, 4, 6, 8]
scores = [62, 71, 82, 88]

fig, ax = plt.subplots()
ax.scatter(study_hours, scores)
ax.set_xlabel("study hours")
ax.set_ylabel("score")
ax.set_title("Study hours and score")
plt.show()

输出结果会显示为四个点。点朝右上方延伸的形状,会让你继续追问两个值是否一起增大。

Study time and score relationship

这张图不会证明原因。它只是帮助你快速检查两个值是否呈现出一起变化的形状。

这个区分很重要。

  • 图表可以让某种东西看起来像“有关系”。
  • 但“看起来像有关系”不等于已经证明原因。
  • 图表是判断的起点,不是判断的终点。

在 Matplotlib 中,先区分 Figure 和 Axes

Matplotlib 官方文档说明,数据是画在 Figure 上的图形。Figure 是整张图,它里面可以包含一个或多个 AxesAxes 则是实际绘制数据的坐标区域。

这里先这样理解。

术语 直观理解
Figure 整张纸
Axes 真正画坐标和数据的那一格
plotscatterhist 决定在 Axes 上如何画数据的函数

因此,这里把下面这种形式当作默认示例。

问题情境:你想先用最小代码看清 Matplotlib 是怎样一起创建 FigureAxes 的。 输入(input):一小组 x 值、一小组 y 值,以及一次 plt.subplots() 调用。 期望输出(output):在一个 Figure 和一个 Axes 上画出的简单折线图。 要确认的概念:plt.subplots() 会同时创建整张图和真正绘制用的坐标区域。

1
2
3
4
# 这个例子用 Matplotlib 绘制 loss、分布和关系,让表格中不明显的模式变得可见。
fig, ax = plt.subplots()
ax.plot([1, 2, 3], [2, 4, 3])
plt.show()

plt.subplots() 会同时创建一个 Figure 和一个 Axes。然后再通过 ax.plot(...) 这样的写法,把数据画到 Axes 上。

你也常会看到更短的写法,例如 plt.plot(...)。但如果先熟悉 fig, ax = plt.subplots() 这种形式,之后要在同一画面里放多张图,或者调整标题、坐标轴名称、图例时,就更容易理解整个流程。

问题在前,图表类型在后

Matplotlib 官方文档提供了很多 plot type。折线图(plot)、散点图(scatter)、柱状图(bar)、直方图(hist)等基本形式最有代表性。

但从一开始就背图表种类,并不是好方法。应该先决定问题。

应先提出的问题 常见适合的图表
想看顺序上的变化吗? 折线图(line plot)
想看两个值之间的关系吗? 散点图(scatter plot)
想比较不同类别的大小吗? 柱状图(bar chart)
想看值集中在哪里吗? 直方图(histogram)

这张表不是规则,而是出发点。真正的图表选择会随着数据形状、读者的问题、想传达的信息而变化。

图表会把数字压缩到一个画面里

图表会把很多数字压缩到一个画面中。因此它能让你快速看见模式,但也因此需要小心。

例如:

  • 改变坐标轴范围(axis range)会让变化看起来更大或更小。
  • 点很少却用线连起来时,会显得比实际更连续。
  • 颜色或面积用得过重时,不重要的差异也会显得很大。
  • 只画平均值时,分布与异常值可能会消失。

看图时,要始终带着下面这些问题。

  1. x 轴和 y 轴分别是什么?
  2. 一个点或一条线表示什么?
  3. 是否存在缺失值或被隐藏的范围?
  4. 图表展示的是观察结果,还是解释?

如果不问这些问题,图表反而可能制造误解。

养成用小段代码确认图表的习惯

图表不是只在最终报告里才使用。学习过程中,它也是快速确认“我的计算是不是朝着正确方向前进”的工具。

例如,只看平均值时,你可能会错过数据的形状。

问题情境:只靠一个平均值,很难知道分数分布集中还是分散,所以你想直接查看分布。 输入(input):若干学生的分数列表 scores。 期望输出(output):显示各分数区间数量的直方图。 要确认的概念:想看分布,就要可视化“数值集中在哪些区间”,而不只是计算平均值。

# 这个例子用 Matplotlib 绘制 loss、分布和关系,让表格中不明显的模式变得可见。
import matplotlib.pyplot as plt

scores = [45, 62, 71, 73, 82, 88, 90]

fig, ax = plt.subplots()
ax.hist(scores, bins=5)
ax.set_xlabel("score")
ax.set_ylabel("count")
ax.set_title("Score distribution")
plt.show()

输出结果会展示分数集中在哪些区间。

Score distribution histogram

这段代码并不计算平均分,而是查看分数集中在哪里。

P2-13.2 会更具体地处理这些基础图表。本节先把图表接受为“检查数字形状的工具”。

如果把本节的角色压缩成一句话,就是下面这样。

前面刚带来的东西 这一节在做什么 下一章会继续什么
用 NumPy 数组和 Pandas 表确认过的数字 用图表快速读取数字的形状、变化与关系 用 Git 记录和可复现性标准,留下“看完图之后改了什么”的记录

用案例来看

案例 1. 明明有 loss 表,却还是感受不到训练是否顺利时

假设一位学习者已经把每个 epoch 的 loss 值整理成表。所有数字都看得到,但只看表格,很难快速判断 loss 是否平稳下降,中间有没有突然跳动,整体走势是否和预期相似。

人先使用的标准往往是“数值都写出来了,应该够了”。但随着数值变多,比起单个数字,更重要的常常是整体形状与流动。图表正是让你看到这种数字的形状的工具。

这也是为什么本节把图表解释为询问变化、关系、分布、异常值的工具,而不是装饰。表格擅长精确值,图表擅长检查模式。因此它们不是彼此竞争,而是在回答不同的问题。

当你把同样的数据画成折线图时,可验证的结果会更清楚。如果比起表格,更容易看出 loss 是否整体下降、是否在某个 epoch 摇摆、值大致集中在哪里,那么作图的理由就清楚了。

检查清单

  • 能说明表格和图表各自擅长回答什么问题吗?
  • 能说明变化、关系、分布与异常值都可以用图表来检查吗?
  • 能直观地说出 FigureAxes 的差别吗?
  • 能说出折线图、散点图、柱状图、直方图分别常用于什么问题吗?
  • 读图时,能同时检查坐标轴含义、点的含义、隐藏范围与过度解读风险吗?
  • 能记住图表只是判断的起点,而不会自动证明原因或结论吗?

来源与参考资料