版权声明:本文为博主原创文章,转载请注明来自http://blog.csdn.net/jediael_lu/ https://blog.csdn.net/jediael_lu/article/details/77772542
FTRL代码实现请参考:https://github.com/lujinhong/ftrl
1、逻辑回归
FTRL本质上是逻辑回归的一个变种,因此先简单介绍一下逻辑回归的内容。
1.1 sigmoid函数
由于二分类结果是1或者0,这与数学的阶跃函数很类似,但是阶跃函数在x=0的位置会发生突变,这个突变在数学上很难处理。所以一般使用sigmoid函数来拟合:
g ( z ) = 1 1 + e − z (1)
具体应用到逻辑回归算法中:
z = ω 0 + ω 1 x 1 + ω 2 x 2 + . . . . . . + ω n x n = ∑ i = 0 n ω i x i = ω T X (2)
其中
x i
表示样本属性(对于我们而言,就是标签IP)的值,
ω i
表示这个属性对应的系数(也就是算法需要计算的内容)。注意这里将
x 0
与
ω 0
也代入了上述公式,其中前者恒为1。于是问题就变成了在训练样本中,已知属性x与最终分类结果y(1或者0)时,如何求得这些系数
ω i
,使得损失最小。
1.2 极大似然估计MLE与损失函数
在机器学习理论中,损失函数(loss function)是用来衡量模型的预测值
f ( x )
与真实值
Y
的不一致程度,它是一个非负实值函数,损失函数越小,模型越优(还需考虑过拟合等问题)。损失函数是经验风险函数的核心部分,也是结构风险函数重要组成部分。模型的结构风险函数包括了经验风险项和正则项,通常可以表示成如下式子
ω ∗ = arg min ω 1 m ∑ i = 1 m L ( y i , f ( x i ; ω ) ) + λ Φ ( ω ) (3)
其中m表示样本的数量。对于逻辑回归,其loss function是log损失,这可以通过极大似然估计进行推导得到。
首先,给定一个样本
x
,可以使用一个线性函数对自变量进行线性组合,即上述的(2)式子:
z = ω 0 + ω 1 x 1 + ω 2 x 2 + . . . . . . + ω n x n = ∑ i = 0 n ω i x i = ω T X (4)
根据sigmoid函数,我们可以得出预测函数的表达式为:
h ω ( x ) = g ( ω T x ) = 1 1 + e − ω T x (5)
上式表示
y = 1
的预测函数为
h ω ( x )
。在这里,假设因变量
y
服从伯努利分布,取值为
0
和
1
,那么可以得到下列两个式子:
p ( y = 1 | x ) = h ω ( x ) (6)
p ( y = 0 | x ) = 1 − h ω ( x ) (7)
而对于上面的两个表达式,通过观察,我们发现,可以将其合并为以下表达式:
p ( y | x ) = h ω ( x ) y ( 1 − h ω ( x ) ) 1 − y (8)
根据上面的式子,给定一定的样本之后,我们可以构造出似然函数,然后可以使用极大似然估计MLE的思想来求解参数。但是,为了满足最小化风险理论,我们可以将MLE的思想转化为最小化风险化理论,最大化似然函数其实就等价于最小化负的似然函数。对于MLE,就是利用已知的样本分布,找到最有可能(即最大概率)导致这种分布的参数值;或者说是什么样的参数才能使我们观测到目前这组数据的概率最大。使用MLE推导LR的loss function的过程如下。
首先,根据上面的假设,写出相应的极大似然函数(假定有
m
个样本):
L ( ω ) = ∏ i = 1 m p ( y i | x i ; ω ) = ∏ i = 1 m h ω ( x i ) y i ( 1 − h ω ( x i ) 1 − y i (9)
上述式子中的
ω
及
x i
均为向量,并未显示其转置。
直接对上面的式子求导会不方便,因此,为了便于计算,我们可以对似然函数取对数,经过化简可以得到下式的推导结果:
log L ( ω ) = ∑ i = 1 m log [ ( h ω ( x i ) y i ( 1 − h ω ( x i ) ) 1 − y i ) ] = ∑ i = 1 m [ y i log h ω ( x i ) + ( 1 − y i ) log ( 1 − h ω ( x i ) ) ] (10)
因此,损失函数可以通过最小化负的似然函数得到,即下式:
J ( ω ) = − 1 m ∑ i = 1 m [ y i log h ω ( x i ) + ( 1 − y i ) log ( 1 − h ω ( x i ) ] (11)
在周志华版的机器学习中,将sigmiod函数代入
h ω ( x i )
,并使用ln代替log,上述公式表示为:
J ( ω ) = − 1 m ∑ i = 1 m [ y i ln h ω ( x i ) + ( 1 − y i ) ln ( 1 − h ω ( x i ) ] = − 1 m ∑ i = 1 m [ y i ln 1 1 + e − ω x i + ( 1 − y i ) ln e − ω x i 1 + e − ω x i ] = − 1 m ∑ i = 1 m [ ln 1 1 + e ω x i + y i ln 1 e − ω x i ] = 1 m ∑ i = 1 m [ − y i w x i + ln ( 1 + e ω x i ) ] (12)
在某些资料上,还有另一种损失函数的表达形式,但本质是一样的,如下【推导见下面1.4】:
J ( ω ) = 1 m ∑ i = 1 m l o g ( 1 + e − y i ω x ) (13)
1.3 梯度下降
这里就以梯度下降为例对逻辑回归进行求解,其迭代公式的推导过程如下:
∂ J ( ω ) ∂ ω j = − 1 m ∑ i m [ y i ( 1 − h ω ( x i ) ) ⋅ ( − x i , j ) + ( 1 − y i ) h ω ( x i ) ⋅ ( x i , j ) ] = − 1 m ∑ i m ( − y i ⋅ x i , j + h ω ( x i ) ⋅ x i , j ) = − 1 m ∑ i m ( h ω ( x i ) − y i ) x i , j (12)
上述中
x i , j
表示第
i
个样本的第
j
个属性的取值。 于是,
ω
的更新方式为:
ω j + 1 = ω j − α ∑ i = 1 m ( h ω ( x i ) − y i ) x x , j (13)
对于随机梯度下降,每次只取一个样本,则
ω
的更新方式为:
ω j + 1 = ω j − α ( h ω ( x ) − y ) x j (13)
其中
x
为这个样本的特征值,
y
为这个样本的真实值,
x j
为这个样本第
j
个属性的值。
这使用周志华版的损失函数更容易得出这个结论。
1.4 另一种形式的损失函数及其梯度
与上面相同,根据sigmoid函数,我们可以得出预测函数的表达式为:
h ω ( x ) = g ( ω T x ) = 1 1 + e − ω T x (5)
上式表示
y = 1
的预测函数为
h ω ( x )
。
但与上面不同,我们假设样本的分布为{-1,1},则
p ( y = 1 | x ) = h ω ( x ) (14)
p ( y = − 1 | x ) = 1 − h ω ( x ) (15)
对于sigmoid函数,有以下特性(简单推导一下就可以得到):
h ( − x ) = 1 − h ( x ) (14)
于是(14)(15)式可以表示为:
p ( y | x ) = h ω ( y x ) (16)
同样,我们使用MLE作估计,
L ( ω ) = ∏ i = 1 m p ( y i | x i ; ω ) = ∏ i = 1 m h ω ( y i x i ) = ∏ i = 1 m 1 1 + e − y i w x i (17)
对上式取对数及负值,得到损失为:
− log L ( ω ) = − log ∏ i = 1 m p ( y i | x i ; ω ) = − ∑ i = 1 m log p ( y i | x i ; ω ) = − ∑ i = 1 m log 1 1 + e − y i w x i = ∑ i = 1 m log ( 1 + e − y i w x i ) (18)
即对于每一个样本,损失函数为:
L ( ω ) = log ( 1 + e − y i w x i ) (19)
对上式求梯度,容易得到:
∂ J ( ω ) ∂ ω j = − y i x i 1 + e y i ω x i (20)
2、FOBOS与RDA
2.1 FOBOS基本原理
FOBOS算法由John Duchi和Yoram Singer提出,是梯度下降的一个变种。 与梯度下降不同,它将权重的更新分为2个步骤:
W t + 1 2 = W t − η t G t
W t + 1 = arg min { 1 2 ∥ W − W t + 1 2 ∥ 2 + η ( t + 1 2 ) ψ ( W ) }
从上面的2个步骤可以看出: 第一个步骤是一个标准的梯度下降。 第二个步骤是对梯度下降的结果进行微调。这里可以分为2部分:(1)前半部分保证了微调发生在第一个步骤结果(取梯度下降结果)的附近。(2)后半部分用于处理正则化,产生稀疏性。
* 根据次梯度理论的推断,可以得出
W ( t + 1 )
不仅仅与迭代前的状态
W t
有关,而且与迭代后的$$相关*
2.2 L1-FOBOS
FOBOS在L1正则化条件下,特征权重的更新方式为:(推导过程暂略)
ω t + 1 , i = s g n ( ω t , i − η t g t , i ) m a x { 0 , | ω t , i − η t g t , i | − η t + 1 2 λ }
其中
g t , i
为梯度在维度i上的取值
2.3 RDA基本原理
简单截断、TG、FOBOS都是建立在SGD基础上的一个变种,属于梯度下降类型的方法,这类方法的精度比较高,同时也能得到一定的稀疏性。而RDA是从另一个方面来求解,它的精度比FOBOS等略差,但它更有效的提升了稀疏性。
在RDA中,特征权重的更新策略为:
W t + 1 = arg min { 1 t ∑ r = 1 t < G r , W > + ψ ( W ) + β t t h ( W ) }
其中
< G r , W >
表示梯度
G r
对W的积分平均值(积分中值);
ψ ( W )
为正则项;
h ( W )
为一个辅助的严格的凸函数;
β t | t ≥ 1
是一个非负且非自减序列。
2.4 L1-RDA
在L1正则化条件下,RDA的各个维度的权重更新方式为:
ω t + 1 , i = { 0 , − ( t √ r ( g ⎯ ⎯ t , i − λ s g n ( g ⎯ ⎯ t , i ) ) , if | g ⎯ ⎯ t , i | < λ otherwise
亦即当某个维度上的累积梯度平均值的绝对值
| g ⎯ ⎯ t , i |
小于阈值
λ
时,该维度权重被置为0。
3、FTRL
理论及实验均证明,L1-FOBOS这类基于梯度下降的算法有比较高的精度,但L1-RDA却能在损失一定精度的情况下产生更好的稀疏性。 把这二者的优点结合成一个算法,这就是FTRL算法的来源。
3.1 从L1-FOBOS和L1-RDA推导FTRL
我们令
η t + 1 2 = η t = Θ ( 1 t √ )
是一个非增正序列,同时代入L1正则项,得到L1-FOBOS的形式如下:
W t + 1 2 = W t − η t G t
W t + 1 = arg min { 1 2 ∥ W − W t + 1 2 ∥ 2 + η t λ ∥ W ∥ 1 }
将这2个公式合并到一起,得到L1-FOBOS的形式如下:
W t + 1 = arg min { 1 2 ∥ W − W t + η t G t ∥ 2 + η t λ ∥ W ∥ 1 }
将上式分解为N个独立的维度进行最优化求解:
w i = arg min { 1 2 ∥ w i − w t , i + η t g t , i ∥ 2 + η t λ | w t , i | 1 } = arg min { 1 2 ( w i − w t , i ) 2 + 1 2 ( η t g t , i ) 2 + w i η t g t , i − w t , i η t g t , i + η t λ | w i | } = arg min { w i g t , i + λ | w i | + 1 2 η t ( w i − w t , i ) 2 + | η t 2 g 2 t , i − w t , i g t , i | }
上述推导的最后一步是通过除以
η t
得到的。 由于上式中的最后一项
| η t 2 g 2 t , i − w t , i g t , i |
是一个与
w i
无关的量,因此上式可简化为:
w i = arg min { w i g t , i + λ | w i | + 1 2 η t ( w i − w t , i ) 2 }
把N个独立优化的维度重新合并,L1-FOBOS可写成以下形式:
W t + 1 = arg min { G t W + λ ∥ W ∥ 1 + 1 2 η t ∥ W − W t ∥ 2 2 }
另一方面,L1-RDA可以表达为:
W t + 1 = arg min { G ( 1 : t ) W + t λ ∥ W ∥ 1 + 1 2 η t ∥ W − 0 ∥ 2 2 }
其中
G ( 1 : t ) = ∑ s = 1 t G s
。
我们令
σ s = 1 η s − 1 η s − 1
,可以得到
σ ( 1 : t ) = 1 η t
。那么L1-FOBOS与L1-RDA可以写为以下格式:
W t + 1 = arg min { G t W + λ ∥ W ∥ 1 + 1 2 σ ( 1 : t ) ∥ W − W t ∥ 2 2 }
W t + 1 = arg min { G ( 1 : t ) W + t λ ∥ W ∥ 1 + 1 2 σ ( 1 : t ) ∥ W − 0 ∥ 2 2 }
比较以上2式的区别: * (1)L1-FOBOS考虑的是当前梯度的影响,L1-RDA则考虑了累积影响。 * (2)L1-FOBOS限制
W t + 1
不能离
W t
太远,而L1-RDA的W则不能离0太远,因此后者更容易产生稀疏性。
3.2 FTRL权重更新的最终形式
在google2010公布的理论文章中并没有使用L2正则项,但在2013年公布工程实施方案时引入了L2。 因此,综合上述的L1-FOBOS及L1-RDA,FTRL算法的权重更新方式为:
W t + 1 = arg min { G ( 1 : t ) W + λ 1 ∥ W ∥ 1 + λ 2 ∥ W ∥ 2 2 + 1 2 ∑ s = 1 t ( σ s ∥ W − W s ∥ 2 2 ) }
将上式展开,得到
W t + 1 = arg min { ( G ( 1 : t ) − ∑ s = 1 t σ s W s ) W + λ 1 ∥ W ∥ 1 + 1 2 ( λ 2 + ∑ s = 1 t σ s ) ∥ W ∥ 2 + 1 2 ∑ s = 1 t σ s ∥ W s ∥ 2 2 }
由于上式的最后一项相对于W来说是一个常数,同时令
Z t = G ( 1 : t ) − ∑ t ( s = 1 ) σ s W s
,上式可表示为:
W t + 1 = arg min { Z t W + λ 1 ∥ W ∥ 1 + 1 2 ( λ 2 + ∑ s = 1 t σ s ) ∥ W ∥ 2 }
各个维度可以独立表示为:
w i + 1 = arg min { z t , i w i + λ 1 | w i | + 1 2 ( λ 2 + ∑ s = 1 t σ s ) w 2 i }
使用与L1-FOBOS相同的分析方法可以得到:
ω t + 1 , i = { 0 , − ( λ 2 + ∑ t s = 1 σ s ) − 1 ( z t , i − s g n ( z t , i ) λ 1 ) , if | z i | < λ 1 otherwise
根据上面的定义:
σ ( 1 : t ) = ∑ s = 1 t σ s = 1 η t
我们使用下面介绍的学习率,以及令
n i = ∑ g 2 i
,则可以得到FTRL的最终形式:
ω i = { 0 , − ( β + n I √ α + λ 2 ) − 1 ( z i − s g n ( z i ) λ 1 ) , if | z i | < λ 1 otherwise
3.3 学习率
1、per-coordinate learning rate 在FTRL中,学习率的定义如下:
η t , i = α β + ∑ t s = 1 g 2 s , i ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ √
其中
α β
是自定义的参数。
在一般梯度下降算法中,使用的是一个全局的学习率策略:
η t = 1 t √
。这个策略保证了学习率是一个正的非增序列,这个值对于每一个特征都是一样的。
考虑一个极端的情况,我们有多个稀疏特征,其中一个特征
x 1
出现非常频繁,而另一个特征
x 2
很少出现。比如第一个样本,
x 1
和
x 2
同时出现了,但接下来的99个样本都只出现了
x 1
,然后第100个样本
x 2
又出来了,由于此时的学习率为
1 100 √
,远小于第一个样的影响了。也就是说假如第一个样本是正样本,第10个样本是负样本,此时由于学习率的不同,模型会认为
x 2
会是一个有用的正相关的特征,即
ω > 0
。但事实上,这个特征只出现了2次,而且一正一负,因此这应该是一个无用的特征,即
ω = 0
。
在FTRL中,我们会使用一个特征的累积梯度,由于中间的99个数据没有这个特征,因此其对应的梯度为0,因此第二次的负样本对应的学习率只是略小于第一个正样本。
3.4 工程实现计算过程
3.4.1 一些定义
对于每一个样本,我们计算以下数值。
(1)
p t
使用当前的
ω
代入sigmoid函数得出的预测值,即:
p = 1 1 + e − ( ∑ n i = 1 ω i x i )
(2)
g i
损失函数在某一个维度上的梯度,对于逻辑回归而言:
g i = ( p − y ) x i
其中y为当前样本的实际值,即0或者1。
(3)
n i
这是该维度梯度
g 2 i
的累积值,即:
n i = n i + g 2 i
(4)
η i
这是该维度的学习率,它与累积梯度有关。定义为:
η i = α β + ∑ t s = 1 ( g s i ) 2 ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ ‾ √ = α β + n i ‾ ‾ √
其中
α β
为用户定义的2个参数。
(5)
σ i
σ i
是一个中间计算值,没有实际含义,其定义为:
σ i = 1 η t , i − 1 η t − 1 , i = 1 α ( n i + g 2 i ‾ ‾ ‾ ‾ ‾ ‾ ‾ √ − n i ‾ ‾ √ )
(6)
z i
z i
也是一个辅助计算的中间值,它的定义为:
z t , i = g ( 1 : t ) − ∑ s = 1 t σ s , i ω s , i
于是
z i
的更新为:
z t − z t − 1 = g t − σ t ω t
即:
z i = z i + g t − σ i ω i
3.4.2 FTRL算法
(1)设定以下4个输入参数,这些参数根据经验而定,可以参考以下数据:
α = 0.1 , β = 1 , λ 1 = 1 , λ 2 = 1
(2)初始化以下数值:
z i = 0 , n i = 0
(3)对于每一个样本 的所带的每一个维度 ,更新
ω
ω i = { 0 , − ( β + n I √ α + λ 2 ) − 1 ( z i − s g n ( z i ) λ 1 ) , if | z i | < λ 1 otherwise
(4)使用上面更新后的
ω
,预测这个样本 的值,即代入sigmoid函数计算
p t
p = 1 1 + e − ( ∑ n i = 1 ω i x i )
(5)对于每一个样本 的每一个维度 ,更新
g i , σ i , z i , n i
,即上面所说的:
g i = ( p − y ) x i
σ i = 1 α ( n i + g 2 i ‾ ‾ ‾ ‾ ‾ ‾ ‾ √ − n i ‾ ‾ √ )
z i = z i + g t − σ i ω i
n i = n i + g 2 i
4、FTRL的工程应用
这里只列出了google提供的一些建议,我们自身的工程应用并不包含在内。 (1)减少样本的数量 * Poisson Inclusion:以p的概率接受样本 * Bloom Filter Inclusion:只有当特征出现次数达到一定数量后,特征才会被加入模型
(2)使用更少的位来进行浮点数编码 一般而言,特征对应的
ω
在(-2,2)之间,所以我们可以将32,或者64位的浮点数编码规则改为q2.13编码方式,即2位整数,1位小数点,13位小数。
(3)多个类似的模型 把多个同类型/相似的模型放在一起保存,可以不需要记录多个key,只需要记录一次Key,以及各个模型中的
ω
。这可以节省内存、带宽、CPU、存储。
(4)只保存一个模型 在上面的基础上更进一步,所有模型共用一份
ω
,以及以一个bit来记录本模型有哪些特征。当模型更新某个
ω
后,取它与之前那个值的平均值。 与共用一个模型对比,好处是记录了这个模型有哪些有效特征,共用模型就无法区分了。
(5)近似计算学习率 只使用正样本P与负样本数据N来近似估计梯度的平方和,前提是假设特征有类似的分布。
∑ g 2 i = P N P + N
(6)减少负样本数量 减少负样本数量,然后在训练时弥补其损失。
再说一次,代码在:https://github.com/lujinhong/ftrl