看本节内容之前建议读一下上节内容的代码流程,对代码流程有个概念以后,你基本就能知道这里讲的在代码层面到底有多简单了,其实就像是一个函数名不同一样,传入不同的参数就能基于你的参数做一些计算得到一些结果,所以你要做的是去理解算法核心思想、适用场景。至于具体怎么算的,什么概率论啊什么微积分啊,跟我的计算机说去吧~
Python 中的机器学习库提供了丰富的梯度下降算法实现,从基础 SGD 到各种自适应学习率算法。选择合适的优化器和参数通常取决于具体问题和数据特征:
-
SGD:基础优化器,配合动量使用效果更好
-
Adam:最流行的自适应学习率算法,适用于大多数情况
-
RMSprop:适用于非平稳目标和循环神经网络
-
Adagrad:适用于稀疏数据
-
Adadelta:Adagrad 的改进版,无需设置学习率
通用建议:
-
首选
Adam或AdamW:作为默认起点,它们通常能快速收敛且效果不错。 -
追求最佳性能时:许多研究表明,精心调参的
SGD with Momentum最终能达到比 Adam 更好的泛化性能,但这需要大量的时间和计算资源进行调参。 -
处理稀疏数据:
AdaGrad,Adadelta,RMSProp及其变种是较好的选择。 -
如果你不知道选什么:从
AdamW(weight_decay=0.01,learning_rate=0.001) 或Adam开始,这通常是一个安全且高效的选择。
1. Scikit-learn 中的 SGD 模型
SGDClassifier 和 SGDRegressor
from sklearn.linear_model import SGDClassifier, SGDRegressor
# 创建 SGD 分类器实例
model = SGDClassifier(
loss='hinge', # 损失函数:
# - 'hinge': 线性SVM (默认)
# - 'log_loss': 逻辑回归
# - 'modified_huber': 平滑的hinge损失
# - 'squared_hinge': 平方hinge损失
# - 'perceptron': 感知器损失
# - 'squared_error': 平方误差(回归)
# - 'huber': Huber损失(回归)
# - 'epsilon_insensitive': ε-不敏感损失(回归)
# - 'squared_epsilon_insensitive': 平方ε-不敏感损失(回归)
penalty='l2', # 正则化类型:
# - 'l2': L2正则化(默认)
# - 'l1': L1正则化
# - 'elasticnet': L1和L2组合
alpha=0.0001, # 正则化强度,必须为正浮点数,值越大正则化越强
# 取值范围: (0, ∞)
l1_ratio=0.15, # Elastic Net混合参数,0<=l1_ratio<=1
# l1_ratio=0 表示L2惩罚,l1_ratio=1表示L1惩罚
fit_intercept=True, # 是否计算截距项
# - True: 计算截距(默认)
# - False: 不计算截距
max_iter=1000, # 最大迭代次数(epochs)
# 取值范围: [1, ∞)
tol=1e-3, # 停止准则的容忍度,如果损失下降小于此值则停止
# 取值范围: [0, ∞)
shuffle=True, # 是否在每个epoch后打乱数据
# - True: 打乱(默认)
# - False: 不打乱
verbose=0, # 详细程度
# - 0: 不输出(默认)
# - 1: 偶尔输出
# - >1: 每个epoch都输出
epsilon=0.1, # 对于huber, epsilon_insensitive,
# squared_epsilon_insensitive损失函数的epsilon参数
# 取值范围: [0, ∞)
learning_rate='optimal',# 学习率计划:
# - 'constant': 固定学习率 η = eta0
# - 'optimal': 根据1/(alpha * (t + t0))递减,使用Leon Bottou的公式
# - 'invscaling': 逐渐减小学习率,eta = eta0 / pow(t, power_t)
# - 'adaptive': 当损失不再下降时,保持学习率不变
eta0=0.0, # 初始学习率,当learning_rate='constant'或'invscaling'时使用
# 取值范围: (0, ∞)
power_t=0.5, # 逆缩放学习率的指数,当learning_rate='invscaling'时使用
# 取值范围: (0, ∞)
early_stopping=False, # 是否使用早停法验证收敛
# - True: 使用
# - False: 不使用(默认)
validation_fraction=0.1,# 早停法验证集比例,当early_stopping=True时使用
# 取值范围: (0, 1)
n_iter_no_change=5, # 早停法容忍的不改进迭代次数
# 取值范围: [1, ∞)
class_weight=None, # 类别权重
# - None: 所有类别权重为1(默认)
# - 'balanced': 自动调整权重与类别频率成反比
# - dict: 手动指定每个类别的权重
warm_start=False, # 是否使用前一次调用的解作为初始化
# - True: 使用
# - False: 不使用(默认)
average=False # 是否计算平均SGD权重
# - True: 计算
# - False: 不计算(默认)
)
# 训练模型
model.fit(X_train, y_train)
2. Keras/TensorFlow 中的优化器
基础 SGD 优化器
算法思路
基础SGD:每次更新只使用一个或一小批(mini-batch)训练样本计算梯度。这引入了噪声,但大大加快了计算速度,并有助于跳出局部最优点。
问题:更新方向完全依赖于当前批次的梯度,方向不稳定,容易震荡,收敛速度慢。
动量 (Momentum):模拟物理中的动量概念。参数的更新方向不仅由当前的梯度决定,还会累积之前的梯度方向。这有两个好处:
-
加速收敛:在梯度方向一致的维度上,更新速度会越来越快。
-
减少震荡:在梯度方向改变频繁的维度上,更新幅度会因相互抵消而减小,从而更稳定地走向最优点。
from tensorflow.keras.optimizers import SGD
optimizer = SGD(
learning_rate=0.01, # 学习率或学习率计划
# 可以是浮点数,也可以是LearningRateSchedule实例
momentum=0.0, # 动量参数,加速相关方向的梯度下降
# 取值范围: [0, 1)
nesterov=False, # 是否应用Nesterov动量
# - True: 应用
# - False: 不应用(默认)
name='SGD', # 优化器名称
# 默认: 'SGD'
weight_decay=None, # 权重衰减(L2惩罚)
# 默认: None
clipnorm=None, # 梯度裁剪按范数
# 默认: None
clipvalue=None, # 梯度裁剪按值
# 默认: None
global_clipnorm=None, # 全局梯度裁剪按范数
# 默认: None
use_ema=False, # 是否使用指数移动平均(EMA)
# 默认: False
ema_momentum=0.99, # EMA动量参数
# 默认: 0.99
ema_overwrite_frequency=None # EMA覆盖频率
# 默认: None
)
Adam 优化器 (Adaptive Moment Estimation)
from tensorflow.keras.optimizers import Adam
optimizer = Adam(
learning_rate=0.001, # 学习率或学习率计划
# 默认: 0.001
beta_1=0.9, # 一阶矩估计的指数衰减率
# 取值范围: [0, 1),默认: 0.9
beta_2=0.999, # 二阶矩估计的指数衰减率
# 取值范围: [0, 1),默认: 0.999
epsilon=1e-07, # 数值稳定性的小常数
# 默认: 1e-07
amsgrad=False, # 是否应用AMSGrad变体
# - True: 应用
# - False: 不应用(默认)
name='Adam', # 优化器名称
# 默认: 'Adam'
# 以下参数与SGD相同
weight_decay=None,
clipnorm=None,
clipvalue=None,
global_clipnorm=None,
use_ema=False,
ema_momentum=0.99,
ema_overwrite_frequency=None
)
RMSprop 优化器 (Root Mean Square Propagation)
from tensorflow.keras.optimizers import RMSprop
optimizer = RMSprop(
learning_rate=0.001, # 学习率或学习率计划
# 默认: 0.001
rho=0.9, # 折扣因子
# 取值范围: [0, 1),默认: 0.9
momentum=0.0, # 动量参数
# 默认: 0.0
epsilon=1e-07, # 数值稳定性的小常数
# 默认: 1e-07
centered=False, # 是否计算中心化的RMSProp
# - True: 中心化
# - False: 不中心化(默认)
name='RMSprop', # 优化器名称
# 默认: 'RMSprop'
# 以下参数与SGD相同
weight_decay=None,
clipnorm=None,
clipvalue=None,
global_clipnorm=None,
use_ema=False,
ema_momentum=0.99,
ema_overwrite_frequency=None
)
Adagrad 优化器 (Adaptive Gradient Algorithm)
from tensorflow.keras.optimizers import Adagrad
optimizer = Adagrad(
learning_rate=0.001, # 学习率或学习率计划
# 默认: 0.001
initial_accumulator_value=0.1, # 累加器的初始值
# 默认: 0.1
epsilon=1e-07, # 数值稳定性的小常数
# 默认: 1e-07
name='Adagrad', # 优化器名称
# 默认: 'Adagrad'
# 以下参数与SGD相同
weight_decay=None,
clipnorm=None,
clipvalue=None,
global_clipnorm=None,
use_ema=False,
ema_momentum=0.99,
ema_overwrite_frequency=None
)
Adadelta 优化器 (Adaptive Delta)
from tensorflow.keras.optimizers import Adadelta
optimizer = Adadelta(
learning_rate=0.001, # 学习率或学习率计划
# 默认: 0.001
rho=0.95, # 折扣因子
# 取值范围: [0, 1),默认: 0.95
epsilon=1e-07, # 数值稳定性的小常数
# 默认: 1e-07
name='Adadelta', # 优化器名称
# 默认: 'Adadelta'
# 以下参数与SGD相同
weight_decay=None,
clipnorm=None,
clipvalue=None,
global_clipnorm=None,
use_ema=False,
ema_momentum=0.99,
ema_overwrite_frequency=None
)
AdamW 优化器 (Adam with Weight Decay)
from tensorflow.keras.optimizers import AdamW
optimizer = AdamW(
learning_rate=0.001, # 学习率或学习率计划
# 默认: 0.001
weight_decay=0.004, # 权重衰减系数
# 默认: 0.004
beta_1=0.9, # 一阶矩估计的指数衰减率
# 默认: 0.9
beta_2=0.999, # 二阶矩估计的指数衰减率
# 默认: 0.999
epsilon=1e-07, # 数值稳定性的小常数
# 默认: 1e-07
amsgrad=False, # 是否应用AMSGrad变体
# 默认: False
name='AdamW', # 优化器名称
# 默认: 'AdamW'
# 以下参数与SGD相同
clipnorm=None,
clipvalue=None,
global_clipnorm=None,
use_ema=False,
ema_momentum=0.99,
ema_overwrite_frequency=None
)
3. PyTorch 中的优化器
PyTorch 中的优化器与 Keras 类似,但有一些语法差异:
import torch
import torch.optim as optim
import torch.nn as nn
# 定义模型
model = nn.Linear(10, 1)
# SGD 优化器
optimizer = optim.SGD(
model.parameters(), # 要优化的参数
lr=0.01, # 学习率 (learning rate)
momentum=0.9, # 动量因子
dampening=0, # 动量阻尼
weight_decay=0, # 权重衰减 (L2惩罚)
nesterov=False # 是否使用Nesterov动量
)
# Adam 优化器
optimizer = optim.Adam(
model.parameters(), # 要优化的参数
lr=0.001, # 学习率
betas=(0.9, 0.999), # 用于计算梯度及其平方的移动平均的系数
eps=1e-08, # 数值稳定性的小常数
weight_decay=0, # 权重衰减
amsgrad=False # 是否使用AMSGrad变体
)
# 训练循环
for epoch in range(num_epochs):
# 前向传播
outputs = model(inputs)
loss = criterion(outputs, labels)
# 反向传播和优化
optimizer.zero_grad() # 清空梯度
loss.backward() # 反向传播
optimizer.step() # 更新参数
4. XGBoost 和 LightGBM 中的梯度提升
这些库虽然不是直接的梯度下降实现,但内部使用梯度下降的变种:
XGBoost 参数
import xgboost as xgb
model = xgb.XGBClassifier(
learning_rate=0.1, # 学习率/收缩率,减少每一步的权重更新
# 取值范围: (0, 1],默认: 0.3
n_estimators=100, # 提升轮数(树的数量)
# 默认: 100
max_depth=6, # 树的最大深度
# 默认: 6
min_child_weight=1, # 子节点所需的最小实例权重总和
# 默认: 1
gamma=0, # 分裂所需的最小损失减少量
# 默认: 0
subsample=1.0, # 训练实例的子采样比例
# 取值范围: (0, 1],默认: 1.0
colsample_bytree=1.0, # 构建每棵树时列的子采样比例
# 取值范围: (0, 1],默认: 1.0
reg_alpha=0, # L1正则化项权重
# 默认: 0
reg_lambda=1, # L2正则化项权重
# 默认: 1
scale_pos_weight=1, # 正类权重的平衡
# 默认: 1
)
LightGBM 参数
import lightgbm as lgb
model = lgb.LGBMClassifier(
learning_rate=0.1, # 学习率
# 默认: 0.1
n_estimators=100, # 提升轮数(树的数量)
# 默认: 100
max_depth=-1, # 树的最大深度,-1表示无限制
# 默认: -1
num_leaves=31, # 树的最大叶子数
# 默认: 31
min_child_samples=20, # 叶子节点最小数据量
# 默认: 20
subsample=1.0, # 训练实例的子采样比例
# 默认: 1.0
colsample_bytree=1.0, # 构建每棵树时列的子采样比例
# 默认: 1.0
reg_alpha=0.0, # L1正则化项权重
# 默认: 0.0
reg_lambda=0.0, # L2正则化项权重
# 默认: 0.0
)
136

被折叠的 条评论
为什么被折叠?



