mathjax | title | sub-nav-group | sub-nav-parent | sub-nav-title |
---|---|---|---|---|
include |
优化 |
batch |
flinkml |
Optimization |
- Table of contents {:toc}
FlinkML 中的优化框架是一个面向开发人员的包,这个包可以解决机器学习任务中经常遇到的优化问题。在谈论监督式学习时,这涉及找到一个模型,用一组参数
\begin{equation} \label{eq:objectiveFunc} f(\wv) := \frac1n \sum_{i=1}^n L(\wv;\x_i,y_i) + \lambda, R(\wv) \ . \end{equation}
这里
在监督式学习中,我们用损失函数来衡量模型的拟合程度,损失函数通过对比模型做出的预测
常用的损失函数有:
- 平方损失: $ \frac{1}{2} \left(\wv^T \cdot \x - y\right)^2, \quad y \in \R $
- 转折点损失: $ \max \left(0, 1 - y ~ \wv^T \cdot \x\right), \quad y \in {-1, +1} $
- 逻辑损失: $ \log\left(1+\exp\left( -y ~ \wv^T \cdot \x\right)\right), \quad y \in {-1, +1}$
机器学习中的[正则化] (https://en.wikipedia.org/wiki/Regularization_(mathematics)) 会惩罚需要被评价的模型,为了减少过拟合,最常见的惩罚是
-
$L_1$ :$R(\wv) = \norm{\wv}_1$ -
$L_2$ :$R(\wv) = \frac{1}{2}\norm{\wv}_2^2$
为了找到一个 (局部) 最小值,梯度下降法会朝着与当前参数 (权重) 相关
在小批次的随机梯度下降中,我们则从一个数据集中采样随机数据集,并在每一批次上计算梯度。在算法的每一轮迭代中我们根据从每一个批次中计算得到的梯度,对权重只更新一次。
一个重要的参数是学习率
目前随机梯度下降的实现使用所有的分区,这样能让一批次的梯度下降变更加有效。只要一个采集操作被引入到 Flink 中,真实的小批次随机梯度下降算法就会被执行。
随机梯度下降的实现可以由以下参数控制:
参数 | 描述 |
---|---|
正则化惩罚 |
要应用的正则化方程. (默认值: NoRegularization) |
正则化常数 |
使用的正则化量. (默认值: 0.1) |
损失函数 |
要被优化的损失函数. (默认值: None) |
迭代数 |
最大迭代次数. (默认值: 10) |
学习率 |
梯度下降法中的初始学习率. 这个值控制了梯度下降法要沿着梯度的反方向移多远. (默认值: 0.1) |
聚合阀值 |
当被设置时,如果目标函数 |
学习率方法 |
(默认值: LearningRateMethod.Default) |
衰退值 |
(默认值: 0.0) |
FlinkML 支持含 L1, L2 和无正则化的随机梯度下降。正则化类型必须实现 RegularizationPenalty
接口,该接口根据梯度和正则化类型计算新的权重。
下表包含了支持的正则化函数。
类别名称 | 正则化函数 |
---|---|
无正则化 | |
L1正则化 | |
L2正则化 |
需要被最小化的损失函数需要实现 LossFunction
接口,该接口定义了计算损失及其梯度的方法。
任何一个定义了自己 LossFunction
或使用 GenericLossFunction
类会从一个偏损失函数和一个预测函数构造损失函数。
以下是一个实例:
val lossFunction = GenericLossFunction(SquaredLoss, LinearPrediction)
支持的偏损失函数请参阅此处. 支持的预测函数请参阅here.
函数名 | 描述 | 损失 | 损失导数 |
---|---|---|---|
平方损失 |
回归任务中最常用的损失函数. |
||
逻辑损失 |
分类任务中最常用的损失函数. |
||
转折点损失 |
可用于分类任务的损失函数. |
$\begin{cases} -y&\text{if } y ~ \wv^T <= 1 \\ 0&\text{if } y ~ \wv^T > 1 \end{cases}$ |
函数名 | 描述 | 预测 | 预测梯度 |
---|---|---|---|
线性预测 |
线性模型比如线性回归和线性分类最常用的函数. |
这里:
-
$j$ 是迭代数 -
$\eta_j$ 是每一步$j$ 的步长 -
$\eta_0$ 是初始学习率 -
$\lambda$ 是正则化常量 -
$\tau$ 是衰退常量, 该常量会使得学习率变成一个递减函数$j$ ,也就是说,随着迭代次数的增加,学习率会衰减。衰减的精准率是由函数特定的,请参阅 **反缩放 (Inverse Scaling) ** 和 Wei Xu 方法 (Wei Xu's Method) (该方法是 反缩放 方法的一个延伸)。
函数名 | 描述 | 函数 | 称呼为 |
---|---|---|---|
默认 |
决定步长的默认方法。该方法相当于当 |
LearningRateMethod.Default |
|
常数 |
步长在整个学习任务中保持不变. |
LearningRateMethod.Constant |
|
Leon Bottou 方法 |
这是 sklearn 中 |
LearningRateMethod.Bottou |
|
反缩放 |
一个决定步长的非常常用的方法. |
LearningRateMethod.InvScaling |
|
Wei Xu 方法 |
由 Wei Xu 在 Towards Optimal One Pass Large Scale Learning with Averaged Stochastic Gradient Descent 的方法 |
LearningRateMethod.Xu |
在随机梯度下降的 Flink 实现中,假如在一个 DataSet[LabeledVector]
给定一组实例,并选择性地给定一些初始初始权重,我们可以使用 GradientDescent.optimize()
来找到给定数据的最优权重。
用户能提供一个包含 WeightVector
元素的初始的 DataSet[WeightVector]
,或者使用所有集合均为0的默认权重。
一个 WeightVector
就是一个含权重的容器类 (container class),这个类把截距从权重向量中分离出来。这允许我们避免把正则化运用到截距上。
{% highlight scala %} // 创建一个随机梯度下降实例 val sgd = GradientDescent() .setLossFunction(SquaredLoss()) .setRegularizationPenalty(L1Regularization) .setRegularizationConstant(0.2) .setIterations(100) .setLearningRate(0.01) .setLearningRateMethod(LearningRateMethod.Xu(-0.75))
// 获取数据 val trainingDS: DataSet[LabeledVector] = ...
// 根据所提供的数据优化权重 val weightDS = sgd.optimize(trainingDS) {% endhighlight %}