# 为“模型复杂度与偏差-方差的关系”导入 `numpy` 并绑定 `np`,用于执行当前任务的数组、数值或随机机制计算。
import numpy as np
# 为“模型复杂度与偏差-方差的关系”导入 `matplotlib.pyplot` 并绑定 `plt`,用于构建当前任务的坐标轴并呈现比较结果。
import matplotlib.pyplot as plt
# 导入 Matplotlib 顶层配置接口并绑定为 `mpl`,用于统一偏差—方差图的中文字体与投影样式。
import matplotlib as mpl
# 设置中文字体
# 注意:这需要在您的环境中安装支持中文的字体,例如 "Source Han Serif SC"
# 如果没有,matplotlib会回退到默认字体,中文可能显示为方框
mpl.rcParams['font.sans-serif'] = ['Source Han Serif SC', 'Noto Serif CJK SC'] # 固定开源中文字体栈并移除专有字体回退
mpl.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
# 建立 `x` 的有序取值网格,用于展示“模型复杂度与偏差-方差权衡”随参数变化的比较结果。
x = np.linspace(0.1, 1, 100)
# 用随复杂度递减的反比曲线表示偏差平方。
bias_sq = 0.8 / (x * 10)
# 用随复杂度递增的直线表示估计方差。
variance = x * 0.4
# 将不可约噪声固定为 0.1,作为总误差曲线的水平下界。
noise = np.full_like(x, 0.1)
# 将偏差平方、方差与不可约噪声相加,得到总误差曲线。
total_error = bias_sq + variance + noise
# 找到总误差曲线的最小值索引,用于标注偏差—方差平衡点。
min_error_idx = np.argmin(total_error)
# 将最小误差索引映射回复杂度横坐标,取得图中最优复杂度位置。
optimal_complexity = x[min_error_idx]
# 创建 `fig, ax` 画布,承载“模型复杂度与偏差-方差权衡”的并排视觉比较。
fig, ax = plt.subplots(figsize=(10, 3.4))
# 以 `x` 为横轴、`bias_sq` 为纵轴绘制曲线,展示“模型复杂度与偏差-方差权衡”。
ax.plot(x, bias_sq, 'r-', label='偏差平方 (Bias²)')
# 以 `x` 为横轴、`variance` 为纵轴绘制曲线,展示“模型复杂度与偏差-方差权衡”。
ax.plot(x, variance, 'b--', label='方差 (Variance)')
# 以 `x` 为横轴、`noise` 为纵轴绘制曲线,展示“模型复杂度与偏差-方差权衡”。
ax.plot(x, noise, 'orange', linestyle=':', label='噪声 (Irreducible Error)')
# 以 `x` 为横轴、`total_error` 为纵轴绘制曲线,展示“模型复杂度与偏差-方差权衡”。
ax.plot(x, total_error, 'k-.', label='总误差 (Total Error)', linewidth=2)
# 在 `optimal_complexity` 处添加垂直参考线,标出“模型复杂度与偏差-方差权衡”的基准或阈值。
ax.axvline(optimal_complexity, color='grey', linestyle='--', label='最佳复杂度')
# 在 `ax` 上填充两条边界之间的区域。
ax.fill_between(x, 0, 1.2, where=x < optimal_complexity, color='lightblue', alpha=0.3, label='欠拟合区域')
# 在 `ax` 上填充两条边界之间的区域。
ax.fill_between(x, 0, 1.2, where=x > optimal_complexity, color='lightcoral', alpha=0.3, label='过拟合区域')
# 将横轴标为“模型复杂度”,明确横向编码的变量。
ax.set_xlabel('模型复杂度', fontsize=16)
# 将纵轴标为“误差”,明确纵向编码的变量。
ax.set_ylabel('误差', fontsize=16)
# 将图题设为“偏差-方差权衡”,直接说明当前图形的比较目的。
ax.set_title('偏差-方差权衡', fontsize=18)
# 显示“模型复杂度与偏差-方差的关系”图例,使颜色或线型与比较对象一一对应。
ax.legend(fontsize=16)
# 为“模型复杂度与偏差-方差的关系”,限定纵轴范围,使比较对象使用一致尺度。
ax.set_ylim(0, 1.2)
# 为“模型复杂度与偏差-方差的关系”,限定横轴范围,使比较对象使用一致尺度。
ax.set_xlim(0, 1)
# 在图中标注“欠拟合 (Underfitting)”,解释“模型复杂度与偏差-方差权衡”的关键位置。
ax.text(optimal_complexity - 0.25, 1.1, '欠拟合\n(Underfitting)', ha='center', fontsize=16)
# 在图中标注“过拟合 (Overfitting)”,解释“模型复杂度与偏差-方差权衡”的关键位置。
ax.text(optimal_complexity + 0.25, 1.1, '过拟合\n(Overfitting)', ha='center', fontsize=16)
# 以 `optimal_complexity` 为横轴、`total_error[min_error_idx]` 为纵轴绘制曲线,展示“模型复杂度与偏差-方差权衡”。
ax.plot(optimal_complexity, total_error[min_error_idx], 'ko', markersize=8)
# 以箭头标注“平衡点”,指出“模型复杂度与偏差-方差权衡”中的候选拐点或阈值。
ax.annotate('平衡点',
# 把注释箭头锚定在总误差最低的复杂度与误差坐标。
xy=(optimal_complexity, total_error[min_error_idx]),
# 将文字置于最低点上方 0.2,避免箭头与误差曲线重叠。
xytext=(optimal_complexity, total_error[min_error_idx] + 0.2),
# 指定 `arrowprops` 为注释箭头样式,细化“模型复杂度与偏差-方差权衡”的输出。
arrowprops=dict(facecolor='black', shrink=0.05),
# 将标注水平居中并设为 12pt,使文字与最优点对齐。
ha='center', fontsize=12)
# 显示偏差平方、方差、不可约噪声与总误差曲线,检查总误差最低点两侧的欠拟合和过拟合区域。
plt.show()