大家好,我是你们的小帅学长。
上一期我们讲了回归拟合线:线性?非线性?怎么选?
但这里有一个更关键的问题,很多人都会忽略,你画的那条回归线,真的可靠吗?
因为一条线“贴合数据”,并不代表它是“正确模型”。
你需要一个工具来做“体检”——残差图(Residual Plot)
01.什么是残差?
定义:残差 = 真实值 − 预测值
residual = y_true − y_pred
它表示,模型“没有解释掉”的那部分信息。
02.残差图在看什么?
残差图通常是:x 轴:自变量或预测值
y 轴:残差
可以把它理解为把“误差”单独拿出来看结构。
03.理想的残差图长什么样?
判断标准为好模型的残差图应该像“随机噪声”。
也就是:围绕 0 上下波动
没有明显趋势
没有结构
这说明,模型已经把“可解释的关系”解释完了。
04.三种典型“问题残差图”
1.出现曲线趋势
表现为残差呈 U 型 / 弯曲,说明了你用了线性模型,但真实关系是非线性
解决方法:用二次、多项式、非线性模型
2.漏斗形(异方差)
表现为左边小、右边大或逐渐扩散
说明了方差不恒定(heteroscedasticity)
解决方法:log 变换、加权回归
3.结构性分层
表现为残差分成几层
说明了你忽略了某个分类变量
解决:分组建模、加入变量
05.论文级残差图模板
回归图告诉你“关系”,残差图告诉你“问题”。下面是一段可直接复用的代码:
import osimport numpy as npimport matplotlib as mplimport matplotlib.pyplot as pltfrom matplotlib import font_manager as fm# =========================# 字体设置# =========================win_fonts = r"C:\Windows\Fonts"for p in [ os.path.join(win_fonts, "times.ttf"), os.path.join(win_fonts, "timesbd.ttf"), os.path.join(win_fonts, "timesi.ttf"), os.path.join(win_fonts, "simsun.ttc"),]: if os.path.exists(p): try: fm.fontManager.addfont(p) except Exception: passmpl.rcParams["font.family"] = ["Times New Roman", "SimSun"]mpl.rcParams["axes.unicode_minus"] = False# =========================# 输出路径# =========================OUT_DIR = r"D:\py_figs"os.makedirs(OUT_DIR, exist_ok=True)# =========================# 构造数据(带非线性)# =========================np.random.seed(42)x = np.linspace(-3, 3, 200)y = x**2 + np.random.normal(0, 1, 200)# =========================# 线性拟合# =========================coef = np.polyfit(x, y, 1)y_pred = np.poly1d(coef)(x)residuals = y - y_pred# =========================# 绘图# =========================fig, axes = plt.subplots(1, 2, figsize=(10,4))axes[0].scatter(x, y, s=12, alpha=0.4)axes[0].plot(x, y_pred, color="red", linewidth=2)axes[0].set_title("Regression / 回归拟合")axes[0].set_xlabel("X")axes[0].set_ylabel("Y")axes[1].scatter(x, residuals, s=12, alpha=0.4)axes[1].axhline(0, color="red", linestyle="--")axes[1].set_title("Residual Plot / 残差图")axes[1].set_xlabel("X")axes[1].set_ylabel("Residual")for ax in axes: for spine in ax.spines.values(): spine.set_linewidth(1.2)# =========================# 保存# =========================out_path = os.path.join(OUT_DIR, "residual_plot.jpg")fig.savefig(out_path, dpi=300, bbox_inches="tight")plt.close()print("Saved:", out_path)

回归线告诉你“看起来对不对”,残差图告诉你“实际上对不对”。
接下来,我们将学习一个非常高频、也是最容易画乱的图:《相关矩阵热力图》。你会遇到这些问题:数字太多看不清、颜色太乱、标注重叠。下一篇我会教你:如何 mask 半矩阵、如何排序让结构更清晰、如何让热力图“干净且高级”。这一篇,会直接提升你的论文图质量。
——期待你的关注——
往期内容:
用Python做科研级画图——分组散点的编码策略
用Python做科研级画图——回归拟合线
用Python做科研级画图——KDE密度
用Python做科研级画图——散点图基础模板
用Python做科研级画图——异常值可视化
用Python做科研级画图——雨云图
用Python做科研级画图——小提琴图