机器学习进阶(17):偏差和方差
第十七篇:偏差和方差——为什么模型总是在“学不够”和“学太多”之间摇摆
在机器学习里,有一个特别常见的现象:
模型太简单时,效果不好。
模型太复杂时,效果也不好。
好像模型总是在两个极端之间来回摇摆:
一边是:
学得不够,抓不住规律。
另一边是:
学得太多,把噪声也当成规律。
这背后其实对应的是两个非常核心的概念:
偏差(Bias)
和
方差(Variance)
很多人第一次看到这两个词,会觉得有点抽象。
但如果你结合前面已经学过的内容,其实它们并不难理解。
1. 先用一句非常直观的话理解这两个词
偏差可以理解为:
模型的想法是不是太简单了。
方差可以理解为:
模型会不会太容易被数据里的细节影响。
如果你把模型当成一个学生,可以这样想:
偏差高的学生:
对知识理解得太粗,很多题型都做不好。
方差高的学生:
特别依赖做过的题型,一换题就容易慌。
理想状态是:
既理解核心规律,又不会对训练样本过度依赖。
2. 什么是偏差(Bias)
偏差大的模型,通常有一个特点:
模型本身表达能力不够。
也就是说,它即使努力学习,也很难把数据里的真实规律学完整。
比如:
用一条直线去拟合明显弯曲的曲线。
不管你怎么调参数,它都不可能贴合数据趋势。
这种情况下:
训练集表现不好
测试集表现也不好
这就是典型的:
欠拟合(underfitting)
偏差大的模型通常会:
- 过于简单
- 忽略重要特征关系
- 无法表达复杂模式
常见例子:
- 用线性模型处理明显非线性问题
- 决策树深度太浅
- KNN 的 K 设得太大
- GBDT 的树太少
这些情况,本质都是:
模型能力不够,学不到真正规律。
3. 什么是方差(Variance)
方差大的模型,通常有另一种问题:
对训练数据太敏感。
训练数据稍微变化一点,模型结果就变化很大。
这种模型通常会:
把训练集学得非常细致
甚至把噪声也学进去
结果就是:
训练集表现很好
测试集表现明显下降
这就是典型的:
过拟合(overfitting)
方差大的模型通常会:
- 对局部数据过度拟合
- 边界特别复杂
- 对新数据不稳定
常见例子:
- 决策树太深
- KNN 的 K 太小
- SVM 的 C 和 gamma 太大
- GBDT 树太多或学习率太高
这些情况,本质都是:
模型太灵活,把训练集记住了。
4. 一个经典类比:射箭靶子
偏差和方差,经常用射箭来类比。
假设靶心代表真实规律。
高偏差
箭都集中在一个地方,但离靶心很远。
说明模型很稳定,但方向错了。
学得不够。
高方差
箭落得到处都是,非常分散。
说明模型不稳定,对数据变化太敏感。
学得太细。
理想情况
箭集中在靶心附近。
说明模型既稳定,又抓住了规律。
这才是我们真正想要的状态。
5. 为什么模型复杂度会影响偏差和方差
一般来说:
模型越简单:
偏差越高
方差越低
模型越复杂:
偏差越低
方差越高
也就是说:
简单模型不容易过拟合,但容易学不够。
复杂模型更容易学到规律,但也更容易学过头。
这就是为什么模型选择永远不是:
越复杂越好
也不是:
越简单越安全
而是:
找到一个刚刚好的复杂度。
6. 一张非常经典的关系图
如果你把:
横轴看成模型复杂度
纵轴看成误差
通常会看到三条曲线:
训练误差:
随着模型复杂度增加,持续下降。
验证误差:
先下降,再上升。
偏差:
随着模型复杂度增加而下降。
方差:
随着模型复杂度增加而上升。
验证误差最低的位置,就是偏差和方差比较平衡的地方。
这就是:
偏差-方差权衡(bias-variance tradeoff)
7. 为什么很多调参,其实都在调偏差和方差
你回头看前面学过的内容,会发现很多操作本质都在调这两件事。
比如:
KNN 中:
K 太大 → 模型过于平滑 → 高偏差
K 太小 → 模型对样本敏感 → 高方差
决策树中:
树太浅 → 高偏差
树太深 → 高方差
随机森林中:
树数量增加 → 降低方差
GBDT 中:
学习率太大 → 方差高
学习率较小 → 更稳
SVM 中:
C 太小 → 偏差高
C 太大 → 方差高
正则化:
增加正则 → 降低方差
你会发现:
很多看起来完全不同的算法,其实都在处理同一个问题:
如何让模型既能学习规律,又不过度依赖训练数据。
8. 一个简单代码例子帮助理解
我们继续用多项式回归来观察偏差和方差变化:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import make_pipeline
np.random.seed(0)
X = np.linspace(0, 10, 30)
y = np.sin(X) + np.random.normal(0, 0.2, 30)
X = X.reshape(-1,1)
degrees = [1, 3, 15]
plt.scatter(X, y)
for d in degrees:
model = make_pipeline(
PolynomialFeatures(d),
LinearRegression()
)
model.fit(X, y)
X_plot = np.linspace(0,10,200).reshape(-1,1)
plt.plot(X_plot, model.predict(X_plot), label=f"degree={d}")
plt.legend()
plt.title("偏差-方差示例")
plt.show()
你通常会看到:
degree=1:
模型太简单 → 高偏差
degree=3:
拟合较好 → 平衡状态
degree=15:
曲线乱抖 → 高方差
9. 为什么理解偏差和方差很重要
因为它会改变你看待模型的方式。
很多人一开始会觉得:
模型效果不好 → 我要换一个更复杂的模型
但有时候问题其实不是模型不够复杂,而是:
模型已经太复杂了。
或者:
数据本身噪声很大。
或者:
特征不合适。
理解偏差和方差以后,你就会知道:
什么时候应该让模型更强一点
什么时候应该让模型收一点
而不是一味堆复杂度。
10. 这一篇真正想让读者建立的感觉
机器学习不是一味追求复杂模型。
而是:
找到一个刚刚好的模型复杂度。
既不过度简化世界,
也不过度迷恋训练集。
偏差和方差这两个概念,其实是在提醒我们:
模型能力越强,越需要克制。
真正好的模型,不是最复杂的那个,而是最合适的那个。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)