2026.09.14 10:22
学习路线
Python -> Python数据分析 -> LangChain -> LangGraph -> FastAPI + SQLAIchemy -> 机器学习 -> 神经网络 -> NLP -> Coze -> Dify -> 大模型应用基础 -> 大模型微调 -> 多模态 -> vibeCoding -> Hermes -> Docker
复习巩固总结
1. 梯度下降法
1.1 单变量
输入: 初始化位置 ,每步距离为 (学习率)。输出: 从 走到山底。
- 令初始化位置为山的任意位置
- 在当前位置环顾四周,如果四周都比 高 → 返回 (已经在底);否则做第 3 步
- 在当前位置环顾四周,寻找坡度最陡的方向,令其为 方向
- 沿着 方向往下走,长度为 ,到达新位置
- 在 环顾四周:四周都比 高 → 返回 ;否则回到第 3 步
太大容易跨过谷底来回晃; 太小走得太慢。单变量时「最陡方向」就是导数的负方向(导数 往左走,导数 往右走)。
循环迭代:求当前点的梯度,更新当前权重。下一个点 = 当前点 − 学习率 × 损失对参数的偏导:
- :学习率(步长)。不能太大也不能太小。机器学习里常见
- 「当前点 − 学习率 × 损失函数」:减的不是 本身,是 对 的导数
举个例子
,求导 。 时 最小。起点 ,学习率 。每次:
| 步 | 计算 | |
|---|---|---|
| 1 | 初始化 | |
| 2 | ||
| 3 | ||
| 4 | ||
| 5 |
第 步时 已经极接近最优值 , 也接近最小值。
1.2 多变量
单变量时梯度是一个数(导数);多个参数时梯度是向量:每个分量是对一个参数的偏导。更新公式不变,只是 、梯度都变成向量。
举个栗子
,求 使 最小。最低点在 。
起点 ,学习率 。下一步 = 当前点 学习率 梯度:
| 步 | 计算 | |
|---|---|---|
| 起点 | 初始化 | |
| 1 | ||
| 2 | ||
| 继续减 | 越来越靠近 | |
| 第 步 | 已极接近最优 | 也接近最小值 |
和单变量同一套路:每步按各偏导同时改所有参数,直到接近谷底。
1.3 手算 - 银行信贷案例
| 编号 | 姓名 | 月工资 | 存款余额 | 房产面积 | 授信额度 |
|---|---|---|---|---|---|
| 1 | 张一 | 6000 | 12000 | 55 | 30000 |
| 2 | 张二 | 8000 | 10000 | 65 | 45300 |
| 3 | 张三 | 7500 | 16000 | 60 | 46000 |
| 4 | 赵六 | 10000 | 15000 | 75 | 55500 |
| 5 | 钱七 | 9000 | 21000 | 70 | 58000 |
| 6 | 孙八 | 12000 | 19000 | 85 | 75400 |
| 7 | 周九 | 11000 | 26000 | 90 | 81000 |
| 8 | 吴十 | 13000 | 32000 | 80 | 76800 |
已知三件套:数据、假设函数、损失函数。权重 这里写成 。
假设函数( 写成 ,且 ):
损失函数用均方误差,前面再除以 ,求导时平方带来的 能消掉:
, 是第 个样本的预测, 是真实授信额度。
下个点 = 当前点 − 学习率 × 损失对参数的偏导:
对 求导,拆开看第 个分量(标量):
带入更新公式(8 个样本,在每个特征分量上求偏导再取平均):
本例 (偏置 + 工资、存款、面积),。 时 ,那一项就是误差本身的平均。
假设 、,即起始点为[1,1,1,1],只是为了能算出 。此时 。偏置项:
| 计算 | ||
|---|---|---|
| 1 张一 | ||
| 2 张二 | ||
| 3 张三 | ||
| 4 赵六 | 同理 | |
| 5 钱七 | 同理 | |
| 6 孙八 | 同理 | |
| 7 周九 | 同理 | |
| 8 吴十 | 同理 |
平均梯度(8 个数相加再除以 ):
更新偏置:
同一批误差 ,分别乘工资、存款、面积再平均:
,从 更新:
第 1 轮结束: 变成
后面同样的步骤再迭代多轮,直到 稳定。工资、存款量级大,乘上误差后梯度会到上亿,一步就把 撑到几十万——所以线性回归里常要先做标准化 / 归一化,把各列特征拉到相近尺度。
1.4 算法分类
1.4.1 全梯度下降 FGD(Full Gradient Descent)
每次迭代用全部 个样本的梯度(也叫批量梯度下降 Batch GD)。上面示例就是使用的这个,因为每次都用全部数据集,训练速度较慢,样本一多每走一步都要把全表扫一遍
1.4.2 随机梯度下降 SGD(Stochastic Gradient Descent)
每次迭代随机抽 1 个样本,只用这一条的梯度更新:
是这一步抽到的那个人。简单、高效,但不稳定:每步只看一条,碰上噪声样本容易被带偏
1.4.3 小批量梯度下降 mini-batch
每次从 个样本里随机抽一小撮,个数记 :
是这一批抽中的下标。课件把名字写成 mini-bantch,指的就是 mini-batch。
结合了 SGD 的「胆大」(走得快)和 FGD 的「心细」(方向相对稳),表现正好夹在两者中间。目前用得最多:既躲开了 FGD 算得慢、成本大,也躲开了纯 SGD 收敛晃。
- :退化成 SGD
- :退化成 FGD
1.4.4 随机平均梯度下降 SAG(Stochastic Average Gradient)
每次仍随机抽 1 个样本算新梯度,但更新时用的是:这个新梯度 + 以前抽过的样本所存梯度 的平均值(不是只看当前这一条)。
记每个样本各存一份梯度 。抽到第 个样本后,只重算 ,其余格子不动,再拿列表里的均值去更新:
比纯 SGD 稳(均值把噪声抹平),又不必像 FGD 每步扫完全部数据。标准实现会给全部 个样本各留一格(没抽到过的先当 );课件是「抽到几个就平均几个」,意思一样,只是列表慢慢变长。
训练初期往往不好、优化偏慢:一开始那些格子是 ,而 SAG 每轮更新都还掺着上一轮存下来的梯度,旧值要把新方向往回拉一把,等列表里的梯度慢慢被换新之后才顺起来。
1.4.5 对比
| 算法 | 每步用几个样本 | 优点 | 缺点 |
|---|---|---|---|
| FGD | 全部 个 | 方向准。§43 手算的就是这个 | 数据大就慢 |
| SGD | 随机 个 | 简单、快。SGDRegressor | 不稳定,噪声样本会带偏 |
| mini-batch | 随机 个() | 快和稳折中,目前用得最多 | 要选 |
| SAG | 抽 个重算,用历史梯度均值更新 | 后期接近 FGD 的稳、又省扫描 | 初期慢(梯度先当 ,还掺旧值) |
1.5 正规方程 vs 梯度下降
1.5.1 正规方程
,一次矩阵运算给出答案,不需要学习率,一蹴而就。
- 适用:小数据、要算得比较准的场景(房屋那 4 行、信贷这 8 行用手都能推)
- 缺点:运算量大;容易受噪声、特征强相关影响(课件「收到噪声」应为受到)
- 没有逆就解不了(特征线性相关等)
- 求逆非常耗时,矩阵一大还可能内存溢出
- 数据本身不是线性关系,这条闭式解用不了或效果差——它是给线性最小二乘准备的。非线性就要换模型;梯度下降可以继续用在别的可微损失上
1.5.2 梯度下降
- 要选学习率 ,太大晃、太小爬
- 要迭代:从某个起点反复走,直到 差不多停住
- 特征很多也能用:不必求 ,参数上亿也走得动
- 更普适:迭代计算,适合嘈杂、大数据(课件「糟杂」即嘈杂)。各种可微的损失函数都能用;深度学习里参数动辄上亿,只能靠迭代找近似最优
1.5.3 对比
| 梯度下降 | 正规方程 | |
|---|---|---|
| 学习率 | 要选 | 不需要 |
| 怎么求 | 迭代多步 | 一次算完 |
| 特征很多 / 数据很大 | 能用,深度学习主要靠它 | 求逆太慢或没逆 |
| 噪声、特征相关 | 仍能走(SGD 还会抖) | 容易被带偏,相关时可能没逆 |
| 适用损失 | 各种可微损失 | 基本是线性最小二乘 |
| 典型场景 | 嘈杂、大数据、深度模型 | 小数据、要精确的线性回归 |
2. 回归模型_评估方法
模型训完之后,还要看它在没见过的数据上预测得准不准。衡量的仍是预测值和真实值的差距,常用三个测评函数:MAE、MSE、RMSE。
2.1 平均绝对误差 MAE(Mean Absolute Error)
每个误差先取绝对值再平均,单位和 一样,大误差不会被平方放大:
2.2 均方误差 MSE(Mean Squared Error)
每个误差先平方再平均。大偏差会被放大,训练线性回归时最常用它当损失:
2.3 均方根误差 RMSE(Root Mean Squared Error)
MSE 再开平方根,就是 RMSE:
RMSE 是 MSE 的平方根,某些情况下比 MSE 更有用:单位变回和 相同(体重是 kg 就还是 kg,不会是 kg²),数字也更好跟原始标签对上看差了多少。
| 公式要点 | 单位 | 特点 | |
|---|---|---|---|
| MAE | 绝对误差的平均 | 与 相同 | 不容易被个别离谱点拉爆 |
| MSE | 平方误差的平均 | 的平方 | 惩罚大误差,训练常用 |
| RMSE | 与 相同 | 评估时比 MSE 好看懂,但对异常点更敏感 |
2.4 三种指标对比
例子:真实点来自 ( 是噪声),用直线 去拟合。点会在直线上下乱跳,算出来大约:
,RMSE 就是 MSE 开方。MAE 和 RMSE 数值接近,都说明整体误差不大;MAE 或 RMSE 越小,误差越小。
RMSE 公式里有平方,大误差会被放大,所以大多数情况下 。两个误差分别是 和 时:
RMSE 会放大「错得比较狠」的那些样本;MAE 只是绝对误差的平均,每个点一视同仁。
结论: MAE、RMSE 都能反映真实误差(课件「反应」即反映),但 RMSE 对异常点更敏感。数据里有个别离谱点时,RMSE 会明显被拉高,MAE 动得少一些。
2.5 再对比:误差被放大之后
还是橙色直线 ,但真实点改成在直线上再叠一层越来越大的波动(,意思是):
随 变大,后面的点会离直线越来越远。算出来大约:
和上一张(MAE≈3.73,RMSE≈4.75)比,三个数都变大了。RMSE 几乎是 MAE 的两倍(),因为后半段那些飞出去的点被平方放大了。
MAE 和 RMSE 都能反映真实误差,但不能说 RMSE 更好,也不该只盯着 RMSE 把误差压下去:
- 若训练时只把 RMSE 压得很低,说明模型把异常点(噪声)也拟合得很紧
- 这样很容易过拟合
- 所以评估要几个指标一起看,不要只信一个数
3. 线性回归
利用回归方程(函数)对一个或多个自变量(特征值)和因变量(目标值)之间关系进行建模的一种分析方式。
| 类型 | 公式 | 说明 | 例子 |
|---|---|---|---|
| 一元线性回归 | 目标值只与一个特征有关 | 身高 → 体重 | |
| 多元线性回归 | 目标值与多个特征有关 | 房价 |
| 名称 | 公式 | 含义 |
|---|---|---|
| 最小二乘 | 每个样本误差的平方和 | |
| MSE 均方误差 | 每个样本误差的平方和 / 样本总数 | |
| MAE 平均绝对误差 | 每个样本误差的绝对值和 / 样本总数 |
3.1 一元线性回归 - 使用正规方程LinearRegression
数学模型:
# 导包
from sklearn.linear_model import LinearRegression
# 案例:演示线性回归API入门
# 1. 准备数据
x_train = [[160], [166], [172], [174], [180]] # 训练集的特征
y_train = [56.3, 60.6, 65.1, 68.5, 75] # 训练集的标签
x_test = [[176]] # 测试集的特征
# 2. 数据的预处理,这里不需要
# 3. 特征工程(特征提取,特征预处理),这里不需要
# 4. 模型训练
# 4.1 创建模型对象
estimator = LinearRegression()
# 4.2 具体的训练动作
estimator.fit(x_train, y_train)
# 4.3 因为是线性回归模型,我们可以查看下:斜率(w,权重),截距(b,偏置)
print(f'斜率(w,权重):{estimator.coef_},截距(b,偏置):{estimator.intercept_}')
# 0.92942177 -93.27346938775517
# 5. 模型评估
y_pre = estimator.predict(x_test)
print(f'模型预测:{y_pre}') # 70.3047619
# 6. 模型评估
| 含义 | |
|---|---|
fit_intercept | LinearRegression 是否计算偏置 。默认 True;若数据已经中心化、不需要截距,可设 False |
coef_ | 拟合后的权重 (多个特征就是一排数) |
intercept_ | 拟合后的偏置 |
内部用正规方程那套最小二乘一次求出 、
3.2 多元线性回归 - 使用梯度下降SGDRegressor
正规方程法存在的问题:
- 运算量太大时,可能造成内存溢出( 要求和、求逆)
- 假设矩阵没有逆,则可能无解
这两种情况就改用梯度下降,波士顿房价预测示例如下:
"""
案例:
演示:随机梯度下降法 线性回归对象 完成 波士顿房价预测案例
回顾:
线性回归算法 属于 有监督学习之 有特征,有标签,且标签是连续的
线性回归分类:
一元线性回归:1个特征列,1个标签列
多元线性回归:多个特征列,1个标签列
线性回归大白话解释:
它是用线性公式来描述 特征 和 标签 之间的关系的,方便做预测,公式如下:
一元线性回归:y = w * x + b
多元线性回归:y = w1 * x1 + w2 * x2 + ... + wn * xn + b = w的转置 * x + b
如何衡量线性回归模型的好坏?
思路:
预测值和真实值之间的误差,误差越小,模型越好 => 损失函数
具体的方案:
1. 最小二乘法: 每个(样本)误差平方和
2. 均方误差(MSE) 每个(样本)误差平方和 / 样本总数
3. 均方根误差(RMSE) 每个(样本)误差平方和 / 样本总数 的 平方根
4. 平均绝对误差(MAE) 每个(样本)误差绝对值和 / 样本总数
如何让损失函数最小?
思路1:梯度下降法
全梯度下降(Full Gradient Descent,FGD)
随机梯度下降(Stochastic Gradient Descent,SGD)
小批量梯度下降(推荐,Mini-batch Gradient Descent,MBGD)
随机平均梯度下降(Stochastic Average Gradient Descent,SAG)
思路2:正规方程法
机器学习开发流程:
1. 加载数据
2. 数据的预处理
3. 特征工程(特征提取,特征预处理...)
4. 模型训练
5. 模型预测
6. 模型评估
"""
# 导包
from sklearn.preprocessing import StandardScaler # 特征处理
from sklearn.model_selection import train_test_split # 数据集划分
from sklearn.linear_model import LinearRegression # 正规方程的回归模型
from sklearn.linear_model import SGDRegressor # 梯度下降的回归模型
from sklearn.metrics import mean_absolute_error, mean_squared_error, root_mean_squared_error # 均方误差评估
from sklearn.linear_model import Ridge, RidgeCV # 岭回归
import pandas as pd # 数据处理
import numpy as np # 数组处理
# 1. 加载波士顿房价数据
data_url = "https://raw.githubusercontent.com/Csengupta1101/Datasets/main/BostonHousing.csv"
raw_df = pd.read_csv(data_url, storage_options={"User-Agent": "Mozilla/5.0"})
data = raw_df.drop(columns=["medv"]).values # 前 13 列是特征
target = raw_df["medv"].values # 最后一列房价是标签
# 2. 数据的预处理,按照 8:2 切分 训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(data, target, test_size=0.2, random_state=23)
# 3. 特征工程(特征提取,特征预处理...)
# 3.1 创建标准化对象
transfer = StandardScaler()
# 3.2 对训练集进行标准化
x_train = transfer.fit_transform(x_train)
# 3.3 对测试集进行标准化
x_test = transfer.transform(x_test)
# 4. 模型训练
# estimator = LinearRegression(fit_intercept=True) # 正规方程法 线性回归对象
# 4.1 创建 线性回归 随机梯度下降 模型对象
# 参1:fit_intercept:是否计算截距(Bias,偏置),默认是True
# 参2:learning_rate:学习率模式 -> 常量,即:不会发生改变
# 参3:eta0:学习率
estimator = SGDRegressor(fit_intercept=True, learning_rate="constant", eta0=0.01)
# 4.2 模型训练
estimator.fit(x_train, y_train)
# 4.3 打印模型计算出的 w(权重,weight)和 b(偏置,bias)
print(f'权重:{estimator.coef_}')
print(f'偏置:{estimator.intercept_}')
# 5. 模型预测
y_pre = estimator.predict(x_test)
# 6. 模型评估
# MSE: 均方误差,每个样本的误差平方和 / 样本总数
print(f'均方误差:{mean_squared_error(y_test, y_pre)}') # 参1:测试集的真实标签,参2:测试集的预测标签
# RMSE: 均方根误差,均方误差的平方根
print(f'均方根误差:{root_mean_squared_error(y_test, y_pre)}') # 参1:测试集的真实标签,参2:测试集的预测标签
# MAE: 平均绝对误差,每个样本的误差绝对值和 / 样本总数
print(f'平均绝对误差:{mean_absolute_error(y_test, y_pre)}') # 参1:测试集的真实标签,参2:测试集的预测标签
| 参数 / 属性 | 含义 |
|---|---|
loss | 损失函数。线性回归用平方损失。课件写 squared_loss,那是旧名字,现在写 squared_error |
fit_intercept | 是否计算偏置,同上面 |
learning_rate | 学习率怎么变。'constant' 固定为 eta0;也可以随迭代变小 |
eta0 | 学习率的起始值,默认 0.01 |
coef_ / intercept_ | 同样是拟合后的 、 |
在后续的深度学习中,学习率随迭代变小的一种策略叫 'invscaling':
eta = eta0 / pow(t, power_t=0.25), 是第几次更新,步子会越走越短,减轻后期晃。
大数据、特征很多、正规方程求不动逆时,改用这个。
4. 拟合
拟合(fitting):用在机器学习领域,用来表示模型对样本点的拟合情况。也就是模型在训练集和测试集上的表现情况。
| 情况 | 训练集 | 测试集 | 曲线长什么样 |
|---|---|---|---|
| 欠拟合 under-fitting | 很差 | 很差 | 直线硬切弯数据,趋势都没学到 |
| 正好拟合 Just right | 好 | 好 | 平滑曲线跟着大趋势走,不追每个点 |
| 过拟合 over-fitting | 很好 | 很差 | 折线穿过几乎每个点,把噪声也记住了 |
- 欠拟合产生的原因:模型过于简单
- 过拟合产生的原因:模型太过于复杂、数据不纯、训练数据太少
- 泛化(Generalization):模型在新数据集(非训练数据)上表现好坏的能力。具体的、个别的扩大为一般的能力。模型的拟合情况=泛化能力
- 奥卡姆剃刀原则:给定两个具有相同泛化误差的模型,较简单的模型比较复杂的模型更可取
4.1 欠拟合
解决办法: 从数据、模型、算法三个角度想。
添加其他特征
有时欠拟合就是特征项不够,可以加别的特征项。三类常用手段:
- 组合:把已有特征拼在一起(乘法 / 加法,见 DAY4 特征组合)
- 泛化:把具体值做成更宽的表征
- 相关性:把和目标相关、但还没进模型的特征加进来
# 1. 定义函数,模拟:欠拟合
def dm01_under_fitting():
# pass
# 1. 准备数据
# 1.1 指定随机种子,则每次生成(噪声)的数据都是固定的
np.random.seed(23)
# 1.2. 随机生成x轴 100 个数据,模拟:特征
# 参1:x轴最小值 参2:x轴最大值 参3:生成个数
x = np.random.uniform(-3, 3, size=100)
# 1.3. 基于x轴值,通过线性公式,生成y轴 100 个数据,模拟:标签
# 线性公式:y = kx + b = 0.5 * x ** 2 + x + 2 + 噪声
# 参1:平均值 参2:标准差 参3:生成个数
y = 0.5 * x ** 2 + x + 2 + np.random.normal(0, 1, size=100)
# 1.4 查看生成的 x轴(特征)和 y轴(标签)的数据
# print(f'x轴(特征):{x}')
# print(f'y轴(标签):{y}')
# 2. 数据预处理,把x轴(特征)转成 多行1列的形式
X = x.reshape(-1, 1)
# print(f'处理后的特征:{X}')
# 3. 特征工程,这里不做了,直接用100条数据,先训练,后预测
# 4. 训练模型
# 4.1 创建模型对象
estimator = LinearRegression() # 正规方程 线性回归模型
# 4.2 模型训练
estimator.fit(X, y) # 参1:处理后的特征数据 参2:标签数据
# 5. 模型预测
y_pre = estimator.predict(X) # 处理后的特征数据
# 6. 模型评估
print(f'均方误差:{mean_squared_error(y, y_pre)}') # 参1:真实值,参2:预测值
# 7. 绘图
plt.scatter(x, y) # 以散点图的形式绘制 真实值
plt.plot(x, y_pre, color='red') # 以线图的形式绘制 预测值
plt.show()
4.2 正好拟合
添加多项式特征项
模型过于简单时的常用套路:线性模型加上二次项或三次项,让模型能弯、泛化能力更强,示例如下:
# 2. 定义函数,模拟:恰好拟合
# def dm01_under_fitting():
def dm02_just_fitting():
# ...
# 2. 数据预处理,把x轴(特征)转成 多行1列的形式
# 2.1 把上述的x轴(特征)转成 多行1列的形式,即:[[1], [2], [3], ..., [100]]
X = x.reshape(-1, 1)
# print(f'处理后的特征:{X}')
# 2.2 因为目前特征列只有1列,模型过于简单,会出现欠拟合的问题,我们增加1列 特征列,从而增加模型的复杂度
# 即:把数据从 [[1], [2], [3], ..., [100]] => [[1, 1], [2, 4], [3, 9], ..., [100, 10000]]
X2 = np.hstack([X, X ** 2]) # 该函数作用:横向拼接,即:拼接2个数组,拼接后数组的行数不变,拼接后数组的列数等于拼接前的列数之和
# ...
# 7. 绘图
plt.scatter(x, y) # 以散点图的形式绘制 真实值
# np.sort(x):对x轴(特征)进行排序,默认是:升序
# np.argsort(x):对x轴(特征)进行排序,返回的是排序后的索引
# 例如:排序前x轴是 [11, 33, 22] -> 对应索引:[0, 1, 2]
# 排序后:x轴是 [11, 22, 33] -> 对应索引:[0, 2, 1]
# plt.plot(x, y_pre, color='red') # 以线图的形式绘制 预测值
plt.plot(np.sort(x), y_pre[np.argsort(x)], color='red')
plt.show()
4.3 过拟合
解决办法:
重新清洗数据
异常点过多、数据不纯的地方再处理一遍(异常值检测、去噪声),少让模型去记脏特征。
增大训练量
原来那点数据被训练得太过了;样本变多,同样复杂度的模型更难把噪声当成规律,过拟合会缓解。
正则化
专门用来压过拟合,机器学习和深度学习里都大量用。做法如 正则化。
减少特征维度,防止维灾难
特征太多、样本太少时,空间被撑得很空,学不充分,泛化差。降维(少特征)等于把模型从「太复杂」往回拉。
4.3.1 代码示例
# 3. 定义函数,模拟:过拟合
def dm03_over_fitting():
# ...
# 2.2 因为目前特征列只有1列,模型过于简单,为了模拟过拟合,我们增加9列 特征列,从而增加模型的复杂度
# 即:把数据从 [[1], [2], [3], ..., [100]] => [[1, 1², 1³, ..., 1⁹], [2, 4, 8, ..., 512], [3, 9, 27, ..., 729], ..., [100, 10000, 1000000, ..., 1000000000]]
# 该函数作用:横向拼接,即:拼接多个数组,拼接后数组的行数不变,拼接后数组的列数等于拼接前的列数之和
# X2 = np.hstack([X, X ** 2])
X3 = np.hstack([X, X ** 2, X ** 3, X ** 4, X ** 5, X ** 6, X ** 7, X ** 8, X ** 9])
# ...
4.3.2 正则化
训练时有些特征会把模型搞复杂,或某个特征异常值较多。正则化就是尽量减弱这个特征的影响(甚至删掉)。
做法:在损失函数里加正则项,压住异常点把 拉得过大 / 过小。分成 L1、L2 两种。
4.3.2.1 L1 正则化
在损失里加上各权重绝对值之和(L1 范数):
- :惩罚系数(sklearn 里叫
alpha)。越大,对特征权重罚得越狠,权重被往 0 拉的幅度越大。这里的 不是梯度下降那节的学习率。 - L1 会让权重趋向 0,甚至等于 0。等于 0 的那些特征等于失效,所以 L1 能做特征筛选。
使用 L1 的线性回归叫 Lasso:
from sklearn.linear_model import Lasso
# 4. 定义函数,模拟:L1正则化
def dm04_l1_regularization():
# ...
# 4. 训练模型
# 4.1 创建模型对象
# estimator = LinearRegression() # 正规方程 线性回归模型
# 改为创建 L1正则化对象
estimator = Lasso(alpha=0.1) # alpha:正则化系数(惩罚系数),默认是1
# ...
4.3.2.2 L2 正则化
在损失里加上各权重的平方和(L2 范数的平方,3.3):
- :同样是惩罚系数。越大,对特征权重罚得越狠。
- L2 会让权重趋向 0,一般不等于 0(减弱影响,不删特征)。
图像是抛物线 。离 0 越远斜率越陡(P1),越靠近 0 斜率越缓(P2),所以会往 0 靠,但钉不死在 0 上。
使用 L2 的线性回归叫岭回归:
from sklearn.linear_model import Ridge
# 5. 定义函数,模拟:L2正则化
def dm05_l2_regularization():
# ...
# 4. 训练模型
# 4.1 创建模型对象
# estimator = Lasso(alpha=0.1) # alpha:正则化系数(惩罚系数),默认是1
# 改为创建 L2正则化对象
# estimator = Ridge(alpha=0.1)
estimator = Ridge(alpha=10)
# ...
机器学习
52. L1和L2正则化解释
52.6 拓展:底层实现
这里的「调参」不是网格搜索怎么选 alpha,而是:惩罚系数 在更新 时底层到底加了什么、每一步怎么把权重往 0 拉。前面损失已经写成「MSE + 正则项」,优化时对整段 求导,梯度多出来的那一块就是正则在干活。偏置 一般不加正则(sklearn 里 intercept_ 不进 L1/L2)。下面学习率仍用 ,避免和惩罚系数 撞名。
52.6.1 L1 底层实现逻辑
损失:
的导数是符号函数( 为 , 为 )。 处不可导,次梯度是 ;课件写成 ,意思是钉在原点时不再往两边推。梯度下降一步:
越大,每步额外往 推的那一截 越长。数据梯度(MSE 那项)如果不够大,这一截会把 整段削过 0。实现上等价于先按 MSE 走半步得到 ,再做软阈值(把绝对值小于门槛的直接打成 0):
- : 变成 正好 0 → 这个特征被关掉(特征筛选)
- :绝对值缩小 ,符号不变 → 还留着,但影响变弱
sklearn 的 Lasso 常用坐标下降:一次只动一个 ,对这一维做上面的软阈值,扫完全部权重再重复,直到收敛。没有像岭回归那样一步求逆的闭式解,因为绝对值不可导、损失也不是严格光滑的碗。
调大:门槛 升高,更多 被打成 0,模型更稀疏。Lasso(alpha=0.1) 就是把这个门槛设成 量级去拟合。
52.6.2 L2 底层实现逻辑
损失:
平方项对 的导数是 (处处可导,0 处导数也是 0)。梯度下降一步:
前面那个 就是权重衰减:每步先把当前 按比例缩小一点,再减去数据梯度。 越大,缩小得越狠。因为乘的是小于 的正数,只能越乘越小,到不了正好 0(除非本来就是 0)。离 0 越远( 很大), 越大、拉得越猛;靠近 0 时拉力变弱,所以会贴着 0,钉不死。
岭回归还有闭式解,正规方程里给 加上 :
对角加 之后矩阵更好求逆(特征相关、 没逆时也能解),这就是 L2 既能压过拟合、又能补正规方程没逆的原因。Ridge(alpha=10) 比 alpha=0.1 加在对角上的数更大,权重被压得更扁。
52.6.3 L1 和 L2 底层实现对比
| L1(Lasso) | L2(Ridge) | |
|---|---|---|
| 正则项 | ||
| 对 多出来的梯度 | (常数力) | (和 成正比) |
| 每步在干什么 | 按固定步长往 0 削,过门槛就打成 0 | 先按比例缩小 ,再减数据梯度 |
| 能到 0 吗 | 能,正好 0 → 特征筛选 | 一般不能,只是趋近 0 |
| 闭式解 | 没有(坐标下降 / 软阈值) | 有, |
| 调大 | 更多权重变 0,更稀疏 | 所有权重一起变小,仍都在 |
| 图像直觉 | V 字,拐角在 0,能卡在原点 | 抛物线,0 处切线水平,滑不到死点 |
一句话:L1 用「砍一刀」调参,不重要的特征直接砍掉;L2 用「按比例缩」调参,特征都留着,只是声音变小。两种 都不是学习率,学率 管步子多大, 管往 0 拉多狠。
53. 逻辑回归大纲
线性回归的标签是连续的(房价、授信额度);逻辑回归的标签是离散的(是/否、A/B)。它仍是有监督学习:有特征、有标签,但干的是分类,而且课件这一章主要讲二分类。
53.1 它是什么、怎么判
逻辑回归 = 有监督学习,有特征、有标签,且标签是离散的(分类)= 适用于二分类。
原理一条链:
- 先按线性回归算出一个实数(可正可负、可很大很小)
- 丢进 Sigmoid,压成 之间的概率
- 拿你写的阈值去切:课件例子是 判 A(正样本),否则判 B(负样本)
阈值不一定是 ,业务上可以自己定。概率本身是连续的,分类结果是离散的——名字里带「回归」,干的却是分类。
53.2 大纲
| 模块 | 内容 |
|---|---|
| 逻辑回归简介 | 应用场景、数学知识(Sigmoid、概率) |
| 逻辑回归原理 | 线性式 + Sigmoid + 阈值如何变成二分类 |
| 逻辑回归 API 和案例 | sklearn 怎么调、跑通一个小例子 |
| 分类问题评估 | 混淆矩阵、精确率、召回率、F1-score、AUC、ROC |
| 电信客户流失预测 | 整套流程落到真实业务 |
评估里两个最常用的分数先记公式(后面展开):
精确率:预测成正的里面,有多少真是正的。召回率:真正的正样本里,有多少被找出来了。
53.3 混淆矩阵先认格子
四个英文拆开记:
| 词 | 意思 |
|---|---|
| True | 真(预测对了) |
| False | 假(预测错了) |
| Positive | 正例(模型说是正类) |
| Negative | 反例(模型说是负类) |
| 预测值(正例) | 预测值(反例) | |
|---|---|---|
| 真实值(正例) | 真正例 TP(True Positive) | 伪反例 FN(False Negative) |
| 真实值(假,反例) | 伪正例 FP(False Positive) | 真反例 TN(True Negative) |
- TP:真是正的,也预测成正的
- FN:真是正的,却预测成负的(漏检)
- FP:真是负的,却预测成正的(误报)
- TN:真是负的,也预测成负的
精确率分母是「预测为正」那一列(TP+FP);召回率分母是「真实为正」那一行(TP+FN)。F1 是两者的调和平均,AUC / ROC 看阈值从 0 扫到 1 时整体分得开不开。
54. 逻辑回归_简介
大纲里这一块是两件事:用在哪、数学上靠什么函数把线性预测变成概率。
54.1 应用场景
逻辑回归是解决二分类问题的利器:输出只有两边,是或不是。课件四个例子:
| 场景 | 正 / 负 |
|---|---|
| 预测疾病 | 阳性 / 不是阳性 |
| 银行信贷 | 放贷 / 不放贷 |
| 情感分析 | 正面 / 负面 |
| 广告点击率 | 点击 / 不点击 |
同类的还有:垃圾邮件与否、客户流失与否、刷卡欺诈与否。只要标签是两档离散值,就可以先拿逻辑回归试。
54.2 数学基础:Sigmoid 函数
Sigmoid 也叫 S 型函数,在神经网络里常当激活函数。线性回归吐出来的是任意实数,分类要的是 之间的概率,中间就靠它压。
54.2.1 公式与作用
这里是线性回归的预测值(,可正可负、可到 )。作用:把 映射到 。
几个常用点:
54.2.2 数学性质
- 单调递增:线性预测越大,概率越大,不会扭回来
- 拐点在 :曲线在这儿从下凸换成上凸,也是默认阈值常取 的原因
- 两端饱和:离 0 很远时曲线几乎贴着 0 或 1,梯度很小
图上看:横轴是线性预测值,纵轴是概率 。默认阈值 时, 判正样本, 判负样本(对应 / )。
54.2.3 导数(后面求梯度会用)
求导不用再碰指数,只要当前的 。 时导数最大();靠近 0 或 1 时导数接近 0——这也是两端饱和、学得慢的原因。
手推一眼:令 ,则 ,
54.2.4 和逻辑回归怎么接上
原理还是那条链,课件强调中间那一步:
把(线性回归处理后的)值 → 通过 Sigmoid 激活函数映射到 之间 → 结合阈值,划分正负样本。
这就是逻辑回归在干的二分类。输出的概率可以读成条件概率:给定这组特征,属于正类的把握有多大,记 。
「A 发生的情况下,B 发生的概率,记作 」。条件概率的定义是:
逻辑回归里 A 是「看到了这组特征 」,B 是「标签为正」,要的就是 。