实验和完整代码
完整代码实现和jupyter运行:github.com/Myolive-Lin…
引言
点击通过率(CTR) 预测是推荐系统行业的一个核心问题
。Gai et al. (2017)
提到:为了提高CTR预测的准确性,越来越多的数据被涉及,使得CTR预测成为一个大规模学习问题,具有大量的样本和高维特征。传统的解决方案是应用线性逻辑回归(LR)模型,并以并行方式训练。然而,CTR预测问题是一个高度非线性问题,用户点击生成涉及许多复杂因素,如广告质量、上下文信息、用户兴趣以及这些因素之间的复杂交互。为了帮助LR模型捕捉非线性,探索了特征工程技术,但这既耗时又耗人力。另一个方向是使用设计良好的模型来捕捉非线性。Facebook使用了一种混合模型,将决策树与逻辑回归相结合。然而,基于树的方法不适合非常稀疏和高维的数据。Rendle引入了因子分解机(FM),使用二阶函数(或使用其他给定数量阶函数)涉及特征之间的交互。然而,FM不能拟合数据中所有一般非线性模式(如其他高阶模式)
2 LS-PLM模型
注意理论方法由Gai et al. (2017)
等人提出,感兴趣可以去查找一下原文。
将大规模点击率预测视为数据集 的二元分类问题,其中 和 是高维且稀疏的。
2.1 Formulation
为了对非线性建模,我们采用分而治之的策略:
Parameters:
- : 的分区参数
- :的预测参数
Special Case (Softmax + Sigmoid):
当、、时:
相当于混合模型:
目标函数
损失函数:
Regularizations:
- 范数(特征选择):
- 范数(稀疏性):
Key Properties
- 由于 / 项导致的非凸和非平滑目标
- 显式稀疏控制:
- 特征选择(抑制不重要的特征)
- 模型可解释性
- 存储和预测的高效性
Notations
符号 | 描述 |
---|---|
分区数量 | |
配分函数(例如,softmax) | |
预测函数(例如 sigmoid) | |
正则化系数 |
2.1 LS-PLM模型优势
LS-PLM遵循分而治之的策略,即首先将特征空间划分为几个局部区域,然后在每个区域中拟合一个线性模型,结果是加权线性预测的组合。这两个步骤是同时以监督方式学习的,旨在最小化预测损失。LS-PLM在三个方面优于传统的LR模型:
- 非线性:只要有足够的划分区域,LS-PLM可以拟合任何复杂的非线性函数。
- 可扩展性:与LR模型类似,LS-PLM可以扩展到大量的样本和高维特征。我们设计了一个分布式系统,可以在数百台机器上并行训练模型。在我们的在线产品系统中,每天都会训练和部署数十个具有数千万参数的LS-PLM模型。
- 稀疏性:正如Brendan等人在2013年指出的,模型稀疏性是工业环境中在线服务的一个实际问题。
Gai et al. (2017)
展示了带有L1和L2,1正则化的LS-PLM可以实现良好的稀疏性,使模型的部署更加轻量级。模型服务过程仅需使用权重非零特征,因此稀疏模型也能使其在线推断的效率更高。
对于非线性可以从下图得知: 图 A 是演示数据集。这是一个二分类问题,红点属于正类,蓝点属于负类。图B所示使用LR模型的分类结果。图C显示了使用LS-PLM模型的分类结果。可以看出来明确LS-PLM可以捕获数据的非线性分布。
LS-PLM与深度学习模型对比
LS-PLM其实可以是看作三层的神经网络,其模型如下
2.3 torch实现
模型定义
class LS_PLM(nn.Module):
"""
基于LS-PLM的分类模型
"""
def __init__(self, num_features, num_classes):
super(LS_PLM, self).__init__()
# 聚类模型,采用softmax输出类别概率
self.num_classes = num_classes
self.cluster_fc = nn.Sequential(
nn.Linear(num_features, num_classes).float(),
nn.Softmax(dim=1)
)
self.lr_fc = nn.Sequential(
nn.Linear(num_features, self.num_classes, bias= True).float(),
nn.Sigmoid()
)
def forward(self, x):
"""
前向传播函数
:param x: 输入数据
:return: 模型输出
"""
softmax_output = self.cluster_fc(x)
lr_output = self.lr_fc(x)
output = torch.sum(softmax_output * lr_output, dim=1, keepdim= True) #与输入维度保持一致
return output
def get_regularization(self, l1=0., l21=0.):
"""
计算L1和L2,1正则项
:param l1: L1正则系数
:param l21: L2,1正则系数
:return: 正则损失项
"""
reg_loss = 0
for name, param in self.named_parameters():
if 'weight' in name:
# L2,1正则项 (按行计算L2范数后求和)
if l21 > 0:
row_norms = torch.norm(param, p=2, dim=1) # 计算每行的L2范数
reg_loss += l21 * torch.sum(row_norms) # 对行范数求和
# L1正则项
if l1 > 0:
reg_loss += l1 * torch.sum(torch.abs(param))
return reg_loss
模型参数
# 参数设置
epoch = 100
lr = 0.005
num_classes = 12
batch_size = 32
l1_lambda = 1e-4
l2_1lambda = 1e-5
# 模型构建
model = LS_PLM(X.shape[1], num_classes=num_classes)
optimizer = optim.Adam(model.parameters(), lr=lr)
criterion = nn.BCELoss(reduction='mean')
模型训练
# 模型训练
loss_history = []
validation_loss_history = []
Auc_history = []
validation_Auc_history = []
pbar = tqdm(range(epoch), desc='Training')
for i in pbar:
model.train()
# 前向传播
y_pred = model(X_train)
loss = criterion(y_pred.squeeze(), y_train)
#添加正则化
reg_loss = model.get_regularization(l1 = l1_lambda, l21 = l2_1lambda)
total_loss = loss + reg_loss
# 反向传播
optimizer.zero_grad()
total_loss.backward()
optimizer.step()
loss_history.append(total_loss.item())
Auc_history.append(roc_auc_score(y_train.detach().numpy(), (y_pred).detach().numpy()))
model.eval()
with torch.no_grad():
y_pred = model(X_validation)
validation_loss = criterion(y_pred.squeeze(), y_validation)
validaiton_reg_loss = model.get_regularization(l1_lambda,l2_1lambda)
total_validation_loss = validation_loss + validaiton_reg_loss
validation_loss_history.append(total_validation_loss.item())
validation_Auc_history.append(roc_auc_score(y_validation.detach().numpy(), (y_pred).detach().numpy()))
pbar.set_postfix({'validation_Loss': f'{total_validation_loss.item():.4f}',
'train_loss':f'{total_loss.item():.4f}'})
2.4模型评估
通过训练,我们观察到模型的训练损失和验证损失逐步减少,证明了模型在训练过程中逐渐收敛,并且能够有效地拟合训练数据。在训练后期,模型的auc值始终大于0.9,表明模型的预测效果较好
AUC(ROC曲线下的面积)
AUC是衡量二分类模型性能的重要指标。在本实验中,模型的训练集和验证集上的AUC值持续上升,并在最终达到了较高的值,证明LS-PLM能够有效地进行CTR预测。通过绘制ROC曲线,我们可以直观地看到模型在正负样本上的区分能力。
最终的ROC曲线如下所示:
预测结果可视化
模型的预测结果可视化表明,LS-PLM在识别点击广告的概率时,能够较为准确地估计用户行为。以下是部分预测结果与实际标签的对比:
预测 | 实际标签 |
---|---|
0.911821 | 1.0 |
0.639550 | 1.0 |
0.950604 | 1.0 |
0.292560 | 0.0 |
0.967143 | 1.0 |
... | ... |
0.047114 | 0.0 |
0.015566 | 0.0 |
0.946931 | 1.0 |
0.297911 | 0.0 |
0.035124 | 0.0 |
总结
- LS-PLM在CTR预测中表现良好:通过使用LS-PLM,我们能够有效地捕捉到数据中的非线性关系,进而提高CTR预测的准确性。
- 正则化和稀疏性控制:通过L1和L21正则化的应用,模型能够有效控制过拟合,并实现良好的稀疏性,使模型的部署更加轻量级。模型服务过程仅需使用权重非零特征,因此稀疏模型也能使其在线推断的效率更高,并提升泛化能力。
Reference
1、Gai, K., Zhu, X., Li, H., Liu, K., & Wang, Z. (2017). Learning piece-wise linear models from large scale data for ad click prediction. arXiv preprint arXiv:1704.05194.
2、王喆 《深度学习推荐系统》
3、经典推荐算法学习(四)| 阿里LS-PLM(MLR)模型原理解析