机器学习(三)
前两篇主要围绕线性回归:从代价函数、梯度下降,到多维特征、向量化、特征缩放和多项式回归。它们解决的主要是回归问题,也就是预测连续值,比如房价、利润、温度。
这一篇开始进入分类问题。分类不是预测一个连续数字,而是预测类别。比如是否垃圾邮件、是否患病、是否通过审核,或者图片里是不是某个数字。
这篇也会把过拟合和正则化放进来。因为学到这里我开始意识到,模型不只是要在训练集上表现好,还要在新数据上靠谱。
从回归问题转向分类问题
回归(Regression,回归)的输出是连续值。比如预测房价时,结果可能是 232、460 这样的数字。
分类(Classification,分类)的输出是类别。最简单的是二分类问题,标签通常写成:
这里:
- $0$:负类。
- $1$:正类。
比如:
- 邮件不是垃圾邮件:0。
- 邮件是垃圾邮件:1。
- 没有患病:0。
- 患病:1。
我现在先把分类理解成:模型不是预测“多少”,而是预测“属于哪一类”。
为什么不能直接用线性回归做分类
线性回归的输出是:
这个输出可能小于 0,也可能大于 1。
但如果我要表达“属于正类的概率”,结果最好在 0 到 1 之间。比如 0.8 可以理解成模型认为它有 80% 的可能属于正类。
所以不能直接把线性回归的输出当作概率。我们需要一个函数,把任意实数压到 0 到 1 之间。
这个函数就是 Sigmoid。
Sigmoid 函数
Sigmoid 函数(Sigmoid Function,S 形函数)是:
其中:
逻辑回归(Logistic Regression,逻辑回归)的模型可以写成:
我现在这样理解:
- 先用 $\mathbf{w}\cdot\mathbf{x}+b$ 得到一个线性输出。
- 再用 Sigmoid 把这个输出压到 0 到 1。
- 最后的结果可以看作 $y=1$ 的概率估计。
代码是:
1 | import numpy as np |
如果要对一批样本输出概率,可以写:
1 | def predict_proba(X, w, b): |
这里:
X @ w + b还是线性部分。sigmoid(z)把线性输出变成 0 到 1 之间的值。- 输出可以理解成属于正类的概率。
从概率变成类别
模型输出概率以后,还需要把概率转成类别。
常见做法是用 0.5 作为阈值:
预测为:
否则预测为:
代码可以写成:
1 | def predict_class(X, w, b): |
这段代码先算概率,再用阈值转成类别。
我现在先记住:逻辑回归不是直接输出 0 或 1,而是先输出概率,再根据阈值做判断。
决策边界
决策边界(Decision Boundary,决策边界)可以理解成:模型把不同类别分开的那条线或曲线。
当 Sigmoid 输出等于 0.5 时:
对应:
也就是:
这条线就是决策边界。
我现在这样理解:
- 决策边界一边预测为 1。
- 另一边预测为 0。
- 如果特征是线性的,边界可能是一条直线。
- 如果加入多项式特征,边界也可以变成曲线。
这也把上一篇的多项式特征接起来了:特征工程不只影响回归曲线,也会影响分类边界。
为什么逻辑回归不用平方误差
线性回归常用平方误差。但逻辑回归如果直接用平方误差,代价函数可能不好优化,梯度下降更难找到合适的最小值。
所以逻辑回归使用的是 Logistic Loss。
单个样本的损失可以拆开看:
当 $y=1$ 时:
当 $y=0$ 时:
合并成一个公式:
我现在先从直觉上理解:
- 如果真实标签是 1,但模型预测概率很小,损失会很大。
- 如果真实标签是 0,但模型预测概率很大,损失也会很大。
- 如果模型预测和真实标签一致,损失就会比较小。
逻辑回归的代价函数
整体代价函数是:
这里:
- $m$:训练样本数量。
- $y^{(i)}$:第 $i$ 个样本的真实标签。
- $f_{\mathbf{w},b}(\mathbf{x}^{(i)})$:模型预测为正类的概率。
- 整体代价就是所有样本损失的平均。
代码可以写成:
1 | def compute_logistic_cost(X, y, w, b): |
这段代码对应的就是逻辑回归的代价函数。
f_wb 是模型预测为 1 的概率。后面两项分别处理真实标签为 1 和真实标签为 0 的情况。
逻辑回归的梯度下降
逻辑回归的梯度形式看起来和线性回归很像:
代码是:
1 | def compute_logistic_gradient(X, y, w, b): |
虽然形式像线性回归,但这里的 $f_{\mathbf{w},b}$ 已经不是直接的线性输出,而是经过 Sigmoid 之后的概率。
所以我不能只看公式长得像,就以为它们完全一样。模型输出和代价函数其实都变了。
欠拟合、适度拟合和过拟合
学到逻辑回归之后,过拟合问题会更明显。其实它不只出现在分类里,回归里也会出现。
欠拟合(Underfitting,欠拟合)是模型太简单,连训练数据的主要趋势都学不好。
适度拟合(Just Right,合适拟合)是模型复杂度比较合适,既能抓住主要规律,也没有过度追逐噪声。
过拟合(Overfitting,过拟合)是模型太复杂,在训练集上表现很好,但对新数据可能不好。
我现在对过拟合的理解是:模型把训练集里的细节记得太死,甚至把噪声也当成规律。
这时训练集效果好,不一定说明模型真的好。还要看它在没见过的数据上表现怎么样。
解决过拟合的常见办法
课程里提到的思路可以先记成三类:
- 增加训练数据。
- 减少特征数量。
- 使用正则化。
增加数据可以让模型看到更多真实情况。减少特征可以降低模型复杂度。正则化则是在不一定删除特征的情况下,限制模型参数不要太夸张。
这里我先重点整理正则化。
正则化的直觉
正则化(Regularization,正则化)就是在代价函数里增加一个惩罚项,让模型不要把参数 $w$ 调得过大。
带正则化的线性回归代价函数是:
这里:
- 前半部分是预测误差。
- 后半部分是正则化惩罚。
- $\lambda$:控制惩罚强度。
- 通常不正则化 $b$。
代码是:
1 | def compute_linear_cost_reg(X, y, w, b, lambda_): |
我现在把正则化理解成:模型不能只想着把训练误差压低,还要付出“参数太大”的代价。
正则化在线性回归中的梯度
加入正则化后,$w$ 的梯度会多一项:
$b$ 的梯度还是:
代码是:
1 | def compute_linear_gradient_reg(X, y, w, b, lambda_): |
关键变化是:
1 | dj_dw = dj_dw + (lambda_ / m) * w |
这说明正则化没有改变梯度下降的大框架,只是在 $w$ 的梯度里加了惩罚项。
正则化在逻辑回归中的代价函数
逻辑回归也可以加正则化:
代码是:
1 | def compute_logistic_cost_reg(X, y, w, b, lambda_): |
这段代码就是在逻辑回归原来的代价函数后面,加上正则化惩罚项。
前半部分负责分类错误的损失,后半部分限制参数不要过大。
正则化在逻辑回归中的梯度
逻辑回归加入正则化后,$w$ 的梯度同样多一项:
代码是:
1 | def compute_logistic_gradient_reg(X, y, w, b, lambda_): |
这里和线性回归的正则化梯度很像。区别在于,逻辑回归里的 error 来自 Sigmoid 后的概率输出。
lambda 怎么理解
$\lambda$ 是正则化强度。
我现在把它理解成模型的“约束力度”:
- $\lambda = 0$:没有正则化,模型可能更容易过拟合。
- $\lambda$ 合适:模型更平滑,泛化能力可能更好。
- $\lambda$ 太大:模型被限制太死,可能欠拟合。
所以 $\lambda$ 不是越大越好。它要在模型太自由和太受限制之间找平衡。
阶段总结
到这里,吴恩达机器学习第一阶段里最基础的几条线,我算是先搭起了骨架。
一开始我只是知道“机器学习是让机器从数据里学规律”。现在至少能把几个核心概念串起来:
- 监督学习里有回归和分类。
- 线性回归让我理解了模型、参数、代价函数和梯度下降。
- 多维特征、向量化和特征缩放让我看到,机器学习不只是公式,还有数据表示和训练效率。
- 多项式回归和特征工程让我意识到,输入特征本身也会影响模型能学到什么。
- 逻辑回归让我看到,分类问题不是简单换个标签,而是模型输出和损失函数都要重新设计。
- 过拟合和正则化提醒我,训练集上效果好不等于模型真的好。
这三篇笔记不是把机器学习学完了,只是先把最基础的骨架搭起来:问题类型、模型表示、代价函数、优化方法和泛化能力。
后面继续学深度学习和联邦学习时,这些概念应该还会反复出现。到那时我再回头看,应该会比现在更能理解为什么神经网络也离不开损失函数、梯度下降和正则化这些东西。





