Torch-Rechub学习分享

推荐系统开源学习 TASK 01 :

1. 推荐系统整理:

1.1 推荐系统概述:

随着移动互联网的飞速发展,人们已经处于一个信息过载的时代。在这个时代中,信息的生产者很难将信息呈现在对它们感兴趣的信息消费者面前,而对于信息消费者也很难从海量的信息中找到自己感兴趣的信息。推荐系统就是一个将信息生产者和信息消费者连接起来的桥梁。平台往往会作为推荐系统的载体,实现信息生产者和消费者之间信息的匹配。上述提到的平台方、信息生产者和消费者可以分别用平台方(如:腾讯视频、淘宝、网易云音乐等)、物品(如:视频、商品、音乐等)和用户和来指代。

1.2 推荐系统架构:

推荐系统架构,首先从数据驱动角度,对于数据,最简单的方法是存下来,留作后续离线处理,离线层就是我们用来管理离线作业的部分架构。在线层能更快地响应最近的事件和用户交互,但必须实时完成。这会限制使用算法的复杂性和处理的数据量。离线计算对于数据数量和算法复杂度限制更少,因为它以批量方式完成,没有很强的时间要求。不过,由于没有及时加入最新的数据,所以很容易过时。个性化架构的关键问题,就是如何以无缝方式结合、管理在线和离线计算过程。近线层介于两种方法之间,可以执行类似于在线计算的方法,但又不必以实时方式完成。这种设计思想最经典的就是Netflix在2013年提出的架构,整个架构分为

1. 离线层:不用实时数据,不提供实时响应; 2. 近线层:使用实时数据,不保证实时响应; 3. 在线层:使用实时数据,保证实时在线服务

1.3 推荐系统算法架构:

在入门学习推荐系统的时候,更加关注的是哪个模型AUC更高、topK效果好,从基本的协同过滤到点击率预估算法,从深度学习到强化学习,学术界都始终走在最前列。一个推荐算法从出现到在业界得到广泛应用是一个长期的过程,因为在实际的生产系统中,首先需要保证的是稳定、实时地向用户提供推荐服务,在这个前提下才能追求推荐系统的效果。算法架构的设计思想就是在实际的工业场景中,不管是用户维度、物品维度还是用户和物品的交互维度,数据都是极其丰富的,学术界对算法的使用方法不能照搬到工业界。一个通用的算法架构,设计思想就是对数据层层建模,层层筛选,帮助用户从海量数据中找出其真正感兴趣的部分。如下图所示,通用的推荐系统包含四个模块:召回,粗排,精排,重排


通用推荐系统流程和模块

2. Torch-RecHub学习整理:

2.1 Torch-RecHub概述

Torch-RecHub 是由Datawhale完成的一个轻量级的pytorch推荐模型框架,核心定位是是一个易用易拓展,聚焦复现业界实用的推荐模型,以及泛生态化的推荐场景。Torch-RecHub包含以下特性:(整体框架设计如图2所示)

(1)scikit-learn风格易用的API(fit、predict),即插即用;

(2)模型训练与模型定义解耦,易拓展,可针对不同类型的模型设置不同的训练机制

(3)接受pandas的DataFrame、Dict数据输入,上手成本低

(4)高度模块化,支持常见Layer,容易调用组装成新模型,包含LR、MLP、FM、FFM、CIN、target-attention、self-attention、transformer

Torch-RecHub代码系统架构

2.2 Torch-RecHub 安装总结

pip install torch-rechub

首先直接下载datawhalechina/torch-rechub: A Lighting Pytorch Framework for Recommendation Models, Easy-to-use and Easy-to-extend. (github.com)中的代码,并在Anaconda创建的torchrec虚拟环境中(建议单独设置一个虚拟环境,不同的库可能会破坏原有环境)安装 pytorch-gpu 和 torch-rechub。
需要注意的是:
torch-rechub中的召回match.py依赖于一个向量检索的工具包annoy,Annoy是高维空间求近似最近邻的一个开源库。在linux中的命令在Windows系统中运行,并不能成功安装,因为缺少C/C++编译环境。
解决方案:
在Python万能包库:Unofficial Windows Binaries for Python Extension Packages中搜索annoy
下载后,终端输入:

pip install 文件的绝对路径

2.3 运行简单精排CTR案例

安装完Torch-RecHub后,以example中的 run_criteo.py为案例,了解 torch-rechub 如何利用pytorch框架实现CTR预测。本案例中采用的模型是 Wide&Deep。Wide&Deep模型是围绕记忆性和泛化性进行讨论的,模型能够从历史数据中学习到高频共现的特征组合的能力,称为是模型的Memorization。能够利用特征之间的传递性去探索历史数据中从未出现过的特征组合,称为是模型的Generalization。Wide&Deep兼顾Memorization与Generalization并在Google Play store的场景中成功落地。具体的算法架构如下图所示:

Wide&Deep模型架构

首先简单了解criteo数据集:
如下图所示,criteo数据集是非常经典的点击率预估比赛,包含13个连续型特征,26个类别型(离散)特征和标签label(表明是否点击该广告),torch-rechub中只是简单的sample,并不是完整的数据集。
Dataframe格式的criteo数据集

通过编写get_criteo_data_dict函数,取出数据集路径中的原始数据,对特征进行缺失值处理,对连续性特征进行最小最大归一化处理同时转化为离散特征,对类别特征进行编码。
最终输出连续特征和类别特征的字符串列表和处理后的数据集和标签

def get_criteo_data_dict(data_path):
    if data_path.endswith(".gz"):  #if the raw_data is gz file:
        data = pd.read_csv(data_path, compression="gzip")
    else:
        data = pd.read_csv(data_path)
    print("data load finished")
    dense_features = [f for f in data.columns.tolist() if f[0] == "I"]
    sparse_features = [f for f in data.columns.tolist() if f[0] == "C"]

    data[sparse_features] = data[sparse_features].fillna('-996',)
    data[dense_features] = data[dense_features].fillna(0,)

    for feat in tqdm(dense_features):  #discretize dense feature and as new sparse feature
        sparse_features.append(feat + "_cat")
        data[feat + "_cat"] = data[feat].apply(lambda x: convert_numeric_feature(x))

    sca = MinMaxScaler()  #scaler dense feature
    data[dense_features] = sca.fit_transform(data[dense_features])

    for feat in tqdm(sparse_features):  #encode sparse feature
        lbe = LabelEncoder()
        data[feat] = lbe.fit_transform(data[feat])

    dense_feas = [DenseFeature(feature_name) for feature_name in dense_features]
    sparse_feas = [SparseFeature(feature_name, vocab_size=data[feature_name].nunique(), embed_dim=16) for feature_name in sparse_features]
    y = data["label"]
    del data["label"]
    x = data
    return dense_feas, sparse_feas, x, y

对数据集进行处理后,将模型需要的参数和数据集输入到主函数中,调用torch-rechub中封装好的DataGenerator类的generate_dataloader函数,以[0.7,0.1,0.2]的比例生成训练集,验证集和测试集,可以看到,主函数中可以调用三种推荐系统中的基础模型:Wide&Deep,DeepFM以及DCN。
之后调用封装好的CTRTrainer类,用fit函数对训练集和验证集进行训练,用evaluate函数测试模型在测试集上的效果。

def main(dataset_path, model_name, epoch, learning_rate, batch_size, weight_decay, device, save_dir, seed):
    torch.manual_seed(seed)
    dense_feas, sparse_feas, x, y = get_criteo_data_dict(dataset_path)
    dg = DataGenerator(x, y)
    train_dataloader, val_dataloader, test_dataloader = dg.generate_dataloader(split_ratio=[0.7, 0.1], batch_size=batch_size)
    if model_name == "widedeep":
        model = WideDeep(wide_features=dense_feas, deep_features=sparse_feas, mlp_params={"dims": [256, 128], "dropout": 0.2, "activation": "relu"})
    elif model_name == "deepfm":
        model = DeepFM(deep_features=dense_feas, fm_features=sparse_feas, mlp_params={"dims": [256, 128], "dropout": 0.2, "activation": "relu"})
    elif model_name == "dcn":
        model = DCN(features=dense_feas + sparse_feas, n_cross_layers=3, mlp_params={"dims": [256, 128]})
    ctr_trainer = CTRTrainer(model, optimizer_params={"lr": learning_rate, "weight_decay": weight_decay}, n_epoch=epoch, earlystop_patience=10, device=device, model_path=save_dir)
    #scheduler_fn=torch.optim.lr_scheduler.StepLR,scheduler_params={"step_size": 2,"gamma": 0.8},
    ctr_trainer.fit(train_dataloader, val_dataloader)
    auc = ctr_trainer.evaluate(ctr_trainer.model, test_dataloader)
    print(f'test auc: {auc}')

模型的主要参数通过argparse 传入函数,argparse 是python自带的命令行参数解析包,可以用来方便地读取命令行参数。

if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument('--dataset_path', default="./data/criteo/criteo_sample.csv")
    parser.add_argument('--model_name', default='widedeep')
    parser.add_argument('--epoch', type=int, default=2)  #100
    parser.add_argument('--learning_rate', type=float, default=1e-3)
    parser.add_argument('--batch_size', type=int, default=2048)  #4096
    parser.add_argument('--weight_decay', type=float, default=1e-3)
    parser.add_argument('--device', default='cuda:0')  #cuda:0
    parser.add_argument('--save_dir', default='./')
    parser.add_argument('--seed', type=int, default=2022)

    args = parser.parse_args()
    main(args.dataset_path, args.model_name, args.epoch, args.learning_rate, args.batch_size, args.weight_decay, args.device, args.save_dir, args.seed)

最终训练模型的结果如下图所示,本案例仅做展示,因此epoch设置为2:

两个epoch训练得到的模型预测精度auc

参考资料:
RecHub Wiki (wolai.com)
(30条消息) argparse基本用法_骑着蜗牛向前跑的博客-CSDN博客_argparse
datawhalechina/fun-rec: 推荐系统入门教程,在线阅读地址:https://datawhalechina.github.io/fun-rec/
(30条消息) Python——annoy的安装&如何安装包_GeekZW的博客-CSDN博客_annoy python

你可能感兴趣的:(Torch-Rechub学习分享)