深度学习中的优化器之FTRL(Follow-The-Regularized-Leader)算法原理与实现细节
题目描述
FTRL(Follow-The-Regularized-Leader)是一种在线学习优化算法,特别适用于大规模稀疏数据场景,例如广告点击率(CTR)预测、推荐系统等。它结合了在线梯度下降(OGD)和正则化技术,能高效处理高维稀疏特征,并在保证模型精度的同时进行有效的特征选择和模型稀疏性控制。请你详细讲解FTRL的原理、数学推导、实现步骤及其在深度学习中的应用特点。
解题过程
步骤1:理解在线学习与稀疏性背景
在广告、推荐等场景中,数据通常是流式到达的,特征维度极高(如百万维),但每个样本只有少量特征非零(稀疏性)。传统优化器(如SGD、Adam)可能无法高效处理这种稀疏性,导致计算和存储开销大。FTRL旨在解决以下问题:
- 在线学习:模型随着新数据逐样本更新,无需存储全部历史数据。
- 稀疏解:通过正则化(如L1)使大量不重要的特征权重为零,减少模型复杂度。
- 自适应学习率:根据不同特征的出现频率调整更新幅度,提高收敛效率。
核心思想:FTRL在每次更新时,不仅考虑当前梯度,还通过正则化项控制模型复杂度,从而平衡“跟随最优历史决策”和“保持模型简单性”。
步骤2:从FTRL的数学形式化开始
FTRL是一种基于正则化的在线凸优化框架。设第 \(t\) 步的权重向量为 \(w_t\),损失函数为 \(f_t(w)\),正则化项为 \(R(w)\)。FTRL的更新规则为:
\[w_{t+1} = \arg\min_{w} \left( \sum_{i=1}^{t} \langle g_i, w \rangle + R(w) + \frac{1}{2} \sum_{i=1}^{t} \sigma_i \|w - w_i\|^2 \right) \]
其中:
- \(g_i = \nabla f_i(w_i)\) 是第 \(i\) 步的梯度。
- \(\langle g_i, w \rangle\) 近似损失函数(使用梯度的一阶近似)。
- \(R(w)\) 是正则化项,通常为L1正则 \(\lambda_1 \|w\|_1\) 或L2正则 \(\frac{\lambda_2}{2} \|w\|_2^2\)。
- \(\sigma_i\) 是学习率相关参数,满足 \(\sigma_{1:t} = \sum_{i=1}^{t} \sigma_i\),用于控制每一步的置信度。
直观理解:目标函数包含三部分:
- 历史梯度的一阶线性近似(跟随“领导者”)。
- 正则化项(防止过拟合,促进稀疏性)。
- 二次正则化(稳定更新,避免权重突变)。
步骤3:推导FTRL的具体更新公式
为简化计算,假设 \(R(w) = \lambda_1 \|w\|_1 + \frac{\lambda_2}{2} \|w\|_2^2\)(L1+L2正则),并令 \(\sigma_i = \frac{1}{\eta_i}\),其中 \(\eta_i\) 是学习率。定义累积梯度 \(G_{1:t} = \sum_{i=1}^{t} g_i\) 和累积缩放项 \(\sigma_{1:t} = \sum_{i=1}^{t} \sigma_i\)。
通过求导并令导数为零,可得到闭式更新解。对于每个权重分量 \(w_j\)(第 \(j\) 维):
\[w_{t+1, j} = \begin{cases} 0 & \text{if } |z_{t, j}| \leq \lambda_1 \\ -\frac{1}{\lambda_2 + \sigma_{1:t}} \left( z_{t, j} - \lambda_1 \cdot \text{sign}(z_{t, j}) \right) & \text{otherwise} \end{cases} \]
其中:
- \(z_{t, j} = \sum_{i=1}^{t} (g_{i, j} - \sigma_i w_{i, j})\),称为“累积梯度修正项”。
- \(\text{sign}(\cdot)\) 是符号函数。
推导细节:
- 目标函数关于 \(w_j\) 求导,得到子梯度条件。
- 由于L1正则不可导,需使用次梯度(subgradient)方法。
- 通过分析 \(z_{t, j}\) 的绝对值与 \(\lambda_1\) 的关系,决定权重是否为零(稀疏性来源)。
关键点:当累积梯度修正 \(|z_{t, j}|\) 小于L1正则系数 \(\lambda_1\) 时,权重强制为零;否则,权重按公式更新。这使不重要特征(梯度小)的权重被置零,实现特征选择。
步骤4:设计自适应学习率
FTRL的性能依赖于学习率参数 \(\sigma_i\)。通常采用感知机风格的自适应学习率:
\[\sigma_i = \frac{\beta + \sqrt{\sum_{k=1}^{i} g_k^2}}{\alpha} \]
或更常用的形式:
\[\eta_{t, j} = \frac{\alpha}{\beta + \sqrt{\sum_{i=1}^{t} g_{i, j}^2}} \]
其中:
- \(\alpha, \beta\) 是超参数,控制学习率幅度。
- 分母中梯度平方和累积:对频繁出现的特征(梯度多),学习率小,更新谨慎;对稀疏特征(梯度少),学习率大,更新迅速。
物理意义:类似AdaGrad的自适应机制,为每个特征维度独立调整学习率。
步骤5:FTRL的算法流程
结合上述公式,FTRL的在线更新步骤如下:
初始化:
- 参数:正则化系数 \(\lambda_1, \lambda_2\),学习率参数 \(\alpha, \beta\)。
- 状态变量:\(z_j = 0\)(累积梯度修正),\(n_j = 0\)(梯度平方累积),对所有特征 \(j\)。
循环(对每个样本 \(t=1,2,\dots\)):
- 收到样本特征向量 \(x_t\),预测 \(y_t = \sigma(w_t \cdot x_t)\)(例如逻辑回归)。
- 计算损失梯度 \(g_t = \nabla \text{loss}(y_t, \hat{y}_t)\)。
- 对每个非零特征 \(j \in \{j | x_{t, j} \neq 0\}\):
- 更新梯度平方累积:\(n_j \leftarrow n_j + g_{t, j}^2\)。
- 计算特征学习率:\(\eta_{t, j} = \frac{\alpha}{\beta + \sqrt{n_j}}\)。
- 更新累积梯度修正:
\[ z_j \leftarrow z_j + g_{t, j} - \left( \frac{1}{\eta_{t, j}} - \frac{1}{\eta_{t-1, j}} \right) w_{t, j} \]
(此项来自 $ \sigma_i w_{i, j} $ 的累积,实际实现中可简化)。
- 更新权重:
\[ w_{t+1, j} = \begin{cases} 0 & \text{if } |z_j| \leq \lambda_1 \\ -\frac{1}{\lambda_2 + (1/\eta_{t, j})} \left( z_j - \lambda_1 \cdot \text{sign}(z_j) \right) & \text{otherwise} \end{cases} \]
- 输出更新后的权重 \(w_{t+1}\)。
注意:实践中,步骤3中的更新可优化为惰性计算(lazy update),即仅当特征出现时才更新对应 \(z_j, n_j, w_j\),极大提升稀疏数据下的效率。
步骤6:分析FTRL的特点与优势
- 稀疏性保证:L1正则使不活跃特征的权重精确为零,减少存储和计算。
- 自适应学习:每个特征独立的学习率适应其出现频率,加速收敛。
- 理论保证:FTRL具有次线性遗憾界(sublinear regret),在线学习性能优越。
- 内存高效:仅维护非零特征的中间变量,适合高维场景。
对比其他优化器:
- 与SGD相比:FTRL通过L1正则和自适应学习率,更好地处理稀疏性和非平稳数据。
- 与AdaGrad相比:FTRL显式加入L1正则,直接产生稀疏解,而AdaGrad通常需后处理剪枝。
- 与Adam相比:FTRL更注重稀疏性和在线学习,Adam更适用于稠密深度学习模型。
步骤7:在深度学习中的应用
虽然FTRL源于线性模型(如逻辑回归),但可扩展至深度学习:
- 应用场景:嵌入层(Embedding Layer)的优化,其中嵌入矩阵极度稀疏(如推荐系统中的用户/物品ID)。
- 实现方式:对嵌入参数使用FTRL,对其它层使用Adam/SGD。例如在TensorFlow中,可通过
tfa.optimizers.FTRL优化器指定。 - 优势:嵌入权重稀疏化,减少模型大小,提升服务效率。
示例代码片段(PyTorch风格伪代码):
class FTRLOptimizer:
def __init__(self, params, alpha=0.1, beta=1.0, lambda1=1.0, lambda2=1.0):
self.alpha, self.beta = alpha, beta
self.lambda1, self.lambda2 = lambda1, lambda2
self.z = {p: torch.zeros_like(p) for p in params} # 累积梯度修正
self.n = {p: torch.zeros_like(p) for p in params} # 梯度平方和
def step(self, params, grads):
for p, g in zip(params, grads):
n_prev = self.n[p]
self.n[p] = n_prev + g**2
eta = self.alpha / (self.beta + torch.sqrt(self.n[p]))
sigma = (torch.sqrt(self.n[p]) - torch.sqrt(n_prev)) / self.alpha
self.z[p] = self.z[p] + g - sigma * p
z = self.z[p]
# 权重更新公式
p.data = torch.where(torch.abs(z) <= self.lambda1,
torch.zeros_like(p),
-(z - self.lambda1 * torch.sign(z)) / (self.lambda2 + 1/eta))
步骤8:总结与扩展
- 关键点:FTRL通过正则化跟随历史梯度领导者,平衡准确性和稀疏性。
- 调参经验:\(\lambda_1\) 控制稀疏性(通常1e-4~1e-2),\(\lambda_2\) 控制L2正则强度,\(\alpha, \beta\) 影响学习率(如 \(\alpha=0.1, \beta=1\))。
- 扩展方向:FTRL可结合Proximal梯度方法,或用于分布式在线学习。
通过以上步骤,你可以理解FTRL如何从在线优化目标出发,导出稀疏性更新规则,并应用于大规模稀疏深度学习任务。