Bootstrap

排序算法模型(1):对数几率回归(Logistic Regression)

对数几率回归(LR)是机器学习的入门分类器,属于广义线性回归,解决了线性回归不擅长的分类问题,常用于二分类。由于点击率的预估(CTR)模型往往被理解为判别“曝光后被点击”与“曝光后未被点击”的二分类模型,因此早期的CTR模型经常选择LR。由于模型的复杂度低,可以并行加速等特点,LR在今天依旧被作为很多个性化推荐产品最早一版的CTR排序模型。

函数模型

LR使用的是sigmoid函数模型:
h θ ( x ) = g ( θ T x ) = 1 1 + e − θ T x h_\theta(x)=g(\theta^Tx)=\frac{1}{1+e^{-\theta^Tx}} hθ(x)=g(θTx)=1+eθTx1
假设 y y y可以取 0 0 0 1 1 1。其概率分别用 P ( y = 0 ) P(y=0) P(y=0) P ( y = 1 ) P(y=1) P(y=1)表示,则:
P ( y = 1 ∣ x ; θ ) = h θ ( x ) P ( y = 0 ∣ x ; θ ) = 1 − h θ ( x ) P ( y ∣ x ; θ ) = h θ ( x ) y ( 1 − h θ ( x ) ) 1 − y P(y=1|x;\theta)=h_\theta(x) \\ P(y=0|x;\theta)=1-h_\theta(x) \\ P(y|x;\theta)=h_\theta(x)^y(1-h_\theta(x))^{1-y} P(y=1∣x;θ)=hθ(x)P(y=0∣x;θ)=1hθ(x)P(yx;θ)=hθ(x)y(1hθ(x))1y

损失函数

假设样本独立,则有似然函数:
L ( θ ) = p ( y ⃗ ∣ X ; θ ) = ∏ i = 1 m P ( y ( i ) ∣ x ( i ) ; θ ) L ( θ ) = ∏ i = 1 m h θ ( x ( i ) ) y ( i ) ( 1 − h θ ( x ( i ) ) ) 1 − y ( i ) L(\theta)=p(\vec{y}|X;\theta)=\prod^m_{i=1}P(y^{(i)}|x^{(i)};\theta)\\ L(\theta)= \prod^m_{i=1}h_\theta(x^{(i)})^{y^{(i)}}(1-h_\theta(x^{(i)}))^{1-y^{(i)}} L(θ)=p(y X;θ)=i=1mP(y(i)x(i);θ)L(θ)=i=1mhθ(x(i))y(i)(1hθ(x(i)))1y(i)
取对数后得到对数似然函数:
l ( θ ) = ∑ i = 1 m [ y ( i ) ln ⁡ h θ ( x ( i ) ) + ( 1 − y ( i ) ) ln ⁡ ( 1 − h θ ( x ( i ) ) ) ] l(\theta)=\sum^m_{i=1}[y^{(i)}\ln{h_\theta(x^{(i)})}+(1-y^{(i)})\ln(1-h_\theta(x^{(i)}))] l(θ)=i=1m[y(i)lnhθ(x(i))+(1y(i))ln(1hθ(x(i)))]
θ \theta θ求偏导后得到: ∂ l ( θ ) ∂ θ j = ∑ i = 1 m [ y ( i ) − g ( θ T x ( i ) ) ] x j ( i ) \frac{\partial l(\theta)}{\partial \theta_j}=\sum^m_{i=1}[y^{(i)}-g(\theta^Tx^{(i)})]x^{(i)}_j θjl(θ)=i=1m[y(i)g(θTx(i))]xj(i)
有了关于 θ \theta θ的偏导公式后,我们就可以得到参数 θ \theta θ的学习公式:
θ j : = θ j + α [ y ( i ) − g ( θ T x ( i ) ) ] x j ( i ) \theta_j:=\theta_j+\alpha[y^{(i)}-g(\theta^Tx^{(i)})]x^{(i)}_j θj:=θj+α[y(i)g(θTx(i))]xj(i)
上式和线性回归的学习公式的形式一致,因为LR属于广义上的线性回归。线性回归是基于高斯分布的样本建模,而LR则是基于Bernoulli分布。而不论是高斯分布,二项分布,还是Poisson分布,都是指数族分布,均属于线性模型范畴,是general linear model。因此可以参照线性回归写出BGD以及SGD的公式。

事件发生的几率,被定义为事件发生的概率与不发生概率的比值。如果对于sigmoid函数求对数几率,则会发现其对数几率为线性模型:
log ⁡ p 1 − p = log ⁡ h θ ( x ) 1 − h θ ( x ) = log ⁡ ( 1 1 + e − θ T x e − θ T x 1 + e − θ T x ) = θ T x \log{\frac{p}{1-p}}=\log{\frac{h_\theta (x)}{1-h_\theta (x)}}=\log{(\frac{\frac{1}{1+e^{-\theta ^T x}}}{\frac{e^{-\theta ^T x}}{1+e^{-\theta ^T x}}})}=\theta ^T x log1pp=log1hθ(x)hθ(x)=log(1+eθTxeθTx1+eθTx1)=θTx

因此LR被认为是对数线性模型。反过来看,实际上LR模型的建立,就是假设模型满足对数线性的情况下,对 p p p求解得到的表达式。

如果对 y y y的类别用1与-1表示,此时似然函数为:
L ( θ ) = ∏ i = 1 m [ ( p ( i ) ) y ( i ) + 1 2 ( 1 − ( p ( i ) ) ) − y ( i ) − 1 2 ] L(\theta)=\prod_{i=1}^{m}[(p^{(i)})^{\frac{y^{(i)}+1}{2}}(1-(p^{(i)}))^{-\frac{y^{(i)}-1}{2}}] L(θ)=i=1m[(p(i))2y(i)+1(1(p(i)))2y(i)1]

对数似然为:
l ( θ ) = ∑ i = 1 m ln ⁡ [ ( p ( i ) ) y ( i ) + 1 2 ( 1 − ( p ( i ) ) ) − y ( i ) − 1 2 ] l(\theta)=\sum^m_{i=1}\ln[(p^{(i)})^{\frac{y^{(i)}+1}{2}}(1-(p^{(i)}))^{-\frac{y^{(i)}-1}{2}}] l(θ)=i=1mln[(p(i))2y(i)+1(1(p(i)))2y(i)1]
若表示为 p ( i ) = 1 1 + e − f i p^{(i)}=\frac{1}{1+e^{-f_i}} p(i)=1+efi1,则有:
l ( θ ) = ∑ i = 1 m ln ⁡ [ ( 1 1 + e − f i ) y ( i ) + 1 2 ( 1 1 + e f i ) − y ( i ) − 1 2 ] l(\theta)=\sum^m_{i=1}\ln[(\frac{1}{1+e^{-f_i}})^{\frac{y^{(i)}+1}{2}}(\frac{1}{1+e^{f_i}})^{-\frac{y^{(i)}-1}{2}}] l(θ)=i=1mln[(1+efi1)2y(i)+1(1+efi1)2y(i)1]
对似然求最大即是对其负值求最小。因此loss function可以被表示为:
l o s s ( y ( i ) , y ^ ( i ) ) = − ln ⁡ ( θ ) = ∑ i = 1 m ln ⁡ ( 1 + e − y ( i ) f i ) loss(y^{(i)}, \hat y^{(i)})=-\ln(\theta)=\sum^m_{i=1}\ln(1+e^{-y^{(i)}f_i}) loss(y(i),y^(i))=ln(θ)=i=1mln(1+ey(i)fi)
此时 f i = ln ⁡ p ( i ) 1 − p ( i ) = θ T x ( i ) f_i=\ln\frac{p^{(i)}}{1-p^{(i)}}=\theta^Tx^{(i)} fi=ln1p(i)p(i)=θTx(i),正是之前对数几率的公式。

使用softmax进行多分类

使用LR处理多分类问题时,可以选择做多次二分类,也可以选择直接使用softmax进行多分类。对于 K K K分类问题,假设第 k k k类的参数为 θ k \theta_k θk,此时有维度为 k ∗ n k*n kn的二维矩阵,则事件 k k k发生概率为:
P ( c = k ∣ x ; θ ) = h θ ( x ) = e θ k T x ∑ i = 1 K e θ i T x ,   k = 1 , 2 , . . . , K P(c=k|x;\theta)=h_\theta(x)=\frac{e^{\theta^T_kx}}{\sum^K_{i=1}e^{\theta^T_ix}}, \ k=1,2,...,K P(c=kx;θ)=hθ(x)=i=1KeθiTxeθkTx, k=1,2,...,K
公式中,第k类的指数化结果与所有类指数化结果的比值即为分类为第 k k k类的概率值。同理可求其似然函数:
L ( θ ) = ∏ i = 1 m ∏ k = 1 K p ( c = k ∣ x ; θ ) = ∏ i = 1 m ∏ k = 1 K { e θ k T x ( i ) ∑ l = 1 K e θ l T x ( i ) } y k ( i ) L(\theta)=\prod^m_{i=1}\prod^K_{k=1}p(c=k|x;\theta)=\prod^m_{i=1}\prod^K_{k=1}\{\frac{e^{\theta^T_kx^{(i)}}}{\sum^K_{l=1}e^{\theta^T_lx^{(i)}}}\}y_k^{(i)} L(θ)=i=1mk=1Kp(c=kx;θ)=i=1mk=1K{l=1KeθlTx(i)eθkTx(i)}yk(i)
对数似然:
J m ( θ ) = ∑ i = 1 m ∑ k = 1 K y k ( i ) ( θ k T x ( i ) − ln ⁡ ∑ l = 1 K e θ l T x ( i ) ) J_m(\theta)=\sum^m_{i=1}\sum^K_{k=1}y_k^{(i)}(\theta_k^Tx^{(i)}-\ln\sum^K_{l=1}e^{\theta_l^Tx^{(i)}}) Jm(θ)=i=1mk=1Kyk(i)(θkTx(i)lnl=1KeθlTx(i))
J ( θ ) = ∑ k = 1 K y k ( θ k T x − ln ⁡ ∑ l = 1 K e θ l T x ) J(\theta)=\sum^K_{k=1}y_k(\theta_k^Tx-\ln\sum^K_{l=1}e^{\theta_l^Tx}) J(θ)=k=1Kyk(θkTxlnl=1KeθlTx)
θ \theta θ求偏导:
∂ J ( θ ) ∂ θ k = ( y k − p ( y k ∣ x ; θ ) ) x \frac{\partial J(\theta)}{\partial \theta_k}=(y_k-p(y_k|x;\theta))x θkJ(θ)=(ykp(ykx;θ))x

线性模型的记忆性优势

作为线性模型,LR可以更好的捕捉特征之间的关联关系,从而体现出良好的记忆性。在很多场景下,记忆性强的模型可以通过很强的特征组合进行推荐。关于记忆性和泛化性的详细讨论,可以阅读Google Play的旷世巨著《Wide & Deep Learning for Recommender Systems》,里面对记忆性和泛化性等内容做了很好的总结。下面简单来说一下这个性质。

记忆性

记忆性指的是模型通过已知数据中的某些特征的组合或者商品的共现频率总结出来的非常强的规则,最典型的模型就是协同过滤。

泛化性

泛化性指的是模型通过已知数据的学习,应对未知的组合共现情况的能力,最典型的模型就是矩阵分解。

LR在Wide&Deep中的作用

Wide&Deep是Google Play用来做App推荐的排序模型,其中Wide部分就是最简单的用户已下载App与目标未下载App的交叉特征。在Deep部分的神经网络生成了最终的稠密特征之后,Wide部分的稀疏特征与Deep的稠密特征拼接共同送入Sigmoid函数中。因此你可以认为Wide部分就是一个交叉项LR。

通过Spark并行运算LR

使用Spark内置的LogisticRegression模型可以完成二分类以及多分类任务:

import org.apache.spark.ml.classification.LogisticRegression

// Load training data
val training = spark.read.format("libsvm").load("data/mllib/sample_libsvm_data.txt")

val lr = new LogisticRegression()
  .setMaxIter(10)
  .setRegParam(0.3)
  .setElasticNetParam(0.8)

// Fit the model
val lrModel = lr.fit(training)

// Print the coefficients and intercept for logistic regression
println(s"Coefficients: ${lrModel.coefficients} Intercept: ${lrModel.intercept}")

// We can also use the multinomial family for binary classification
val mlr = new LogisticRegression()
  .setMaxIter(10)
  .setRegParam(0.3)
  .setElasticNetParam(0.8)
  .setFamily("multinomial")

val mlrModel = mlr.fit(training)

// Print the coefficients and intercepts for logistic regression with multinomial family
println(s"Multinomial coefficients: ${mlrModel.coefficientMatrix}")
println(s"Multinomial intercepts: ${mlrModel.interceptVector}")
;