腾讯2020广告受众基础属性预估大赛

摘要:

合集:AI案例-NLP-广告传媒
赛题:腾讯2020广告受众基础属性预估
数据集:腾讯广告用户在3个月的时间窗口内的广告点击历史记录
数据集价值:预估广告受众的基础属性
解决方案:广告历史曝光特征提取、词嵌入等建模技术
竞赛出题方/数据发布方:腾讯

一、赛题描述

竞赛主办方为参赛者提供一组用户在长度为 91 天(3 个月)的时间窗口内的广告点击历史记录作为训练数据集。每条记录中包含了日期 (从 1 到 91)、用户信息 (年龄,性别),被点击的广告的信息(素材 id、广告 id、产品 id、产品类目 id、广告主 id、广告主行业 id 等),以及该用户当天点击该广告的次数。测试数据集将会是另一组用户 的广告点击历史记录。提供给参赛者的测试数据集中不会包含这些用户的年龄和性别信息。 本赛题要求参赛者预测测试数据集中出现的用户的年龄和性别。

说明:以上章节引用竞赛主办方发布的赛题内容。

二、数据集内容

赛题中的训练数据包括用户基本属性信息、用户点击日志和广告相关信息。

训练集:
data\train_preliminary\ad.csv
data\train_preliminary\click_log.csv
data\train_preliminary\user.csv
data\train_semi_final\ad.csv
data\train_semi_final\click_log.csv
data\train_semi_final\user.csv

测试集:
data\test\ad.csv
data\test\click_log.csv

对于测试集合中的数据,包括广告信息和点击日志,需要我们去预测用户性别和年龄。

click_log.csv

  • time: 天粒度的时间,整数值,取值范围[1, 91]。
  • user_id: 从 1 到 N 随机编号生成的不重复的加密的用户 id,其中 N 为用户总数目(训练集和测试集)。
  • creative_id: 用户点击的广告素材的 id,采用类似于 user_id 的方式生成。
  • lick_times: 当天该用户点击该广告素材的次数。

user.csv

  • user_id:用户id
  • age: 分段表示的用户年龄,取值范围[1-10]。
  • gender:用户性别,取值范围[1,2]。

ad.csv

  • creative_id:广告素材id
  • ad_id: 该素材所归属的广告的 id,采用类似于 user_id 的方式生成。每个广告可能包含多个可展示的素材。
  • product_id: 该广告中所宣传的产品的 id,采用类似于 user_id 的方式生成。
  • product_category: 该广告中所宣传的产品的类别 id,采用类似于 user_id 的方式生成。
  • advertiser_id: 广告主的 id,采用类似于 user_id 的方式生成。
  • industry: 广告主所属行业的 id,采用类似于 user_id 的方式生成。

广告素材中的creative_id广告素材可能由文案、图片和视频组成,一个广告包含多个广告素材,因此广告素材生成的流程也需要加以了解。这也是影响广告投放的重要环节之一,首先结合用户画像和卖点提炼,然后确定使用场景,最后进行素材的筛选和加工。对数据和业务的基本认识可以帮助我们深入理解赛题,挖掘更多有用信息。

说明:以上章节引用竞赛主办方发布的数据集数据结构描述。

三、解决方案样例

以下为冠军选手的解决方案。

特征提取方案

用户的历史点击行为可以反映其属性特点,比如男性偏爱电子产品、游戏等,女性则更偏爱服饰、化妆品等,所以从点击序列中挖掘信息更为重要,其实也可以看着多值离散特征,对于重复的id问题,需要进一步尝试对比。那么如何挖掘序列信息呢,这里的方法就比较多了,下面逐个介绍。

统计特征

一般而言,以user_id维主键进行统计序列内的信息统计,如nunique/(number of unique)、mean、max、min、std/标准差(Standard Deviation)、count等等,对于nunique,用户点击素材id的类型个数,反映用户的兴趣范围。

一切问题都可以考虑根据目标变量进行有监督的构造特征。此题也不例外,目标变量为用户年龄核性别,那么我们就可以构造与目标有关的特征。然而这会存在一个问题,特别容易过拟合。有效的办法是采用交叉验证的方式,比如我们将将样本划分为5份,对于其中每一份数据,我们都用另外4份数据来构造。简单来说未知的数据在已知的数据里面取特征。

one-hot/top提取

直接展开,保留所有信息,300多万维,可以直接放弃了。或者提取点击最多的广告,然后再进行统计。

词频统计/TF-IDF

NLP中常用的做法,将用户点击序列中的creative_id或者ad_id集合看作一篇文档,将每个creative_id或者ad_id视为文档中的文字,然后使用tfidf。当然这也下来维度也非常高,可以通过参数调整来降低维度,比如sklearn中的TfidfVectorizer,可以使用max_df和min_df进行调整。

word2vec/deepwalk/fasttext等

把每个点击的creative_id或者ad_id当作一个词,把一个人91天内点击的creative_id或者ad_id列表当作一个句子,使用word2vec来构造creative_id或者ad_id嵌入表示。最后进行简单的统计操作得到用户的向量表示。除此之外还能够通过creative_id被user_id点击的序列来构造user_id向量表示。

  • 用户广告ID序列, sequence_text_user_id_ad_id
  • 用户创意ID序列, sequence_text_user_id_creative_id
  • 用户广告主ID序列, sequence_text_user_id_advertiser_id
  • 用户产品ID序列, sequence_text_user_id_product_id
  • 用户行业序列, sequence_text_user_id_industry
  • 用户产品类别序列, sequence_text_user_id_product_category
  • 用户时间序列, sequence_text_user_id_time
  • 用户点击次数序列, sequence_text_user_id_click_times

安装开发包

开发包版本信息

python                    3.10.16
pytorch                   2.5.1           py3.10_cuda12.1_cudnn9_0   pytorch
pytorch-cuda             12.1           pytorch
transformers             4.49.0         py310haa95532_0
gensim                   4.3.3
numpy                     1.26.4
numpy-base               1.26.4
pandas                   2.2.3
scikit-learn             1.6.1

运行

1. 数据预处理

合并所有原始数据文件,包括train_preliminary、train_semi_final、test目录下的点击记录CSV文件,并写入点击记录文件(click.pkl)。转换用户CSV数据成文件(train_user.pkl/test_user.pkl)。

python src/preprocess.py

输出:文件click.pkl、train_user.pkl、test_user.pkl

merge click files...
merge ad files...
merge user files...
merge all files...
preprocess done! saving data...

2. 特征提取

Python脚本extract_features.py主要用于从用户点击日志数据中提取多种特征,包括聚合特征、序列特征和K折统计特征,用于后续的机器学习模型训练。该脚本主要实现了四种类型的特征提取:

  • 聚合特征:对用户行为进行各种聚合统计
  • 序列特征:将用户的行为序列转化为文本形式
  • K折统计特征:使用交叉验证方式统计特征的年龄性别分布
  • K折序列特征:将K折统计结果转化为序列特征

核心函数分析:

输入:

click_log=pd.read_pickle('data/click.pkl')
train_df=pd.read_pickle('data/train_user.pkl')
test_df=pd.read_pickle('data/test_user.pkl')

get_agg_features() – 聚合特征提取

  • 输入:数据帧列表、特征列、聚合列、聚合操作类型、日志数据
  • 功能:对日志数据按指定列进行分组聚合操作(如count, mean, unique等)
  • 输出:返回新特征名称列表
  • 特点:支持多种聚合操作,处理缺失值,自动内存清理

sequence_text() – 序列特征提取

  • 输入:数据帧列表、ID列、序列值列、日志数据
  • 功能:将用户的行为序列转化为空格分隔的文本字符串
  • 输出:返回新特征名称列表
  • 特点:适用于将用户点击历史转化为可处理的文本形式

kfold() – K折统计特征

  • 输入:训练集、测试集、日志数据、关键特征列
  • 功能:使用5折交叉验证方式统计特征的年龄性别分布
  • 输出:直接在输入数据帧中添加新特征
  • 特点:避免数据泄露,适合分类问题中的统计特征

kfold_sequence() – K折序列特征

  • 输入:训练集、测试集、日志数据、关键特征列
  • 功能:将K折统计结果转化为序列特征并保存为Word2Vec格式
  • 输出:返回新特征名称列表
  • 特点:结合了统计特征和序列特征的优势

运行

python src/extract_features.py

输出:

(133878445, 23) (3000000, 3) (1000000, 3)
Extracting aggregate feature...
Extracting aggregate feature done!
List aggregate feature names:
['user_id__size', 'user_id_ad_id_unique', 'user_id_creative_id_unique', 'user_id_advertiser_id_unique', 'user_id_industry_unique', 'user_id_product_id_unique', 'user_id_time_unique', 'user_id_click_times_sum', 'user_id_click_times_mean', 'user_id_click_times_std']

Extracting sequence feature...
sequence_text_user_id_ad_id
sequence_text_user_id_creative_id
sequence_text_user_id_advertiser_id
sequence_text_user_id_product_id
sequence_text_user_id_industry
sequence_text_user_id_product_category
sequence_text_user_id_time
sequence_text_user_id_click_times
Extracting sequence feature done!
List sequence feature names:
['sequence_text_user_id_ad_id', 'sequence_text_user_id_creative_id', 'sequence_text_user_id_advertiser_id', 'sequence_text_user_id_product_id', 'sequence_text_user_id_industry', 'sequence_text_user_id_product_category', 'sequence_text_user_id_time', 'sequence_text_user_id_click_times']

3. 预训练 Word2Vector 与 BERT

这里提供两种方式获得预训练权重: 重新预训练或下载预训练好的权重

注: Word2Vector和BERT权重必须一致,即要么全部重新预训练,要么全部下载

4.1 预训练Word2Vector

源码src/w2v.py进行word2vector预训练。该脚本实现了以下核心功能:

  1. 从预处理好的用户行为序列数据中训练Word2Vec模型
  2. 将训练好的Word2Vec模型保存为pickle文件
  3. 支持多种用户行为序列的向量化(广告ID、创意ID、广告主ID等)

w2v() 函数

  • 输入参数:
    • dfs: 包含序列特征的数据帧列表(通常是训练集和测试集)
    • f: 要处理的序列特征列名
    • L: 输出的向量维度(默认为128)
  • 处理流程:
    1. 从所有数据帧中收集指定列的句子(将空格分隔的序列拆分为单词列表)
    2. 使用Gensim的Word2Vec模型训练词向量
    3. 将训练好的模型保存到data目录下
  • 模型参数:
    • vector_size=128: 词向量维度
    • window=8: 上下文窗口大小
    • min_count=1: 最小词频阈值
    • sg=1: 使用skip-gram算法(1=skip-gram, 0=CBOW)
    • workers=32: 并行工作线程数
    • epochs=10: 训练迭代次数

主程序流程

  1. 数据加载:读取预处理好的训练集和测试集(train_user.pkl和test_user.pkl)
  2. Word2Vec训练:对8种不同的用户行为序列分别训练Word2Vec模型:
    • 用户广告ID序列
    • 用户创意ID序列
    • 用户广告主ID序列
    • 用户产品ID序列
    • 用户行业序列
    • 用户产品类别序列
    • 用户时间序列
    • 用户点击次数序列
  3. 模型保存:每个模型保存为”.{维度}d”格式的pickle文件

关键代码:

if __name__ == "__main__":
  train_df=pd.read_pickle('data/train_user.pkl')
  test_df=pd.read_pickle('data/test_user.pkl')
  #训练word2vector,维度为128
  w2v([train_df,test_df],'sequence_text_user_id_ad_id',L=128)
  w2v([train_df,test_df],'sequence_text_user_id_creative_id',L=128)
  w2v([train_df,test_df],'sequence_text_user_id_advertiser_id',L=128)
  w2v([train_df,test_df],'sequence_text_user_id_product_id',L=128)
  w2v([train_df,test_df],'sequence_text_user_id_industry',L=128)
  w2v([train_df,test_df],'sequence_text_user_id_product_category',L=128)
  w2v([train_df,test_df],'sequence_text_user_id_time',L=128)
  w2v([train_df,test_df],'sequence_text_user_id_click_times',L=128)
python src/w2v.py

4.2预训练BERT

预训练BERT (如果GPU是v100,可以安装apex并在参数上加–fp16进行加速)

cd BERT
mkdir saved_models
python run.py \
   --output_dir saved_models \
   --model_type roberta \
   --config_name roberta-base \
   --mlm \
   --block_size 128 \
   --per_gpu_train_batch_size 64 \
   --per_gpu_eval_batch_size 64 \
   --gradient_accumulation_steps 1 \
   --learning_rate 5e-5 \
   --weight_decay 0.01 \
   --adam_epsilon 1e-6 \
   --max_grad_norm 1.0 \
   --max_steps 100000 \
   --mlm_probability 0.2 \
   --warmup_steps 10000 \
   --logging_steps 50 \
   --save_steps 10000 \
   --evaluate_during_training \
   --save_total_limit 500 \
   --seed 123456 \
   --tensorboard_dir saved_models/tensorboard_logs    
rm -r saved_models/bert-base    
cp -r saved_models/checkpoint-last saved_models/bert-base
rm saved_models/bert-base/optimizer.pt
cp saved_models/vocab.pkl saved_models/bert-base/vocab.pkl
cd ..

5. 训练模型

mkdir saved_models
mkdir saved_models/log
for((i=0;i<5;i++));  
do  
python run.py \
     --kfold=5 \
     --index=$i \
     --train_batch_size=256 \
     --eval_steps=5000 \
     --max_len_text=128 \
     --epoch=5 \
     --lr=1e-4 \
     --output_path=saved_models \
     --pretrained_model_path=BERT/bert-base \
     --eval_batch_size=512 2>&1 | tee saved_models/log/$i.txt
done  

合并结果,结果为submission.csv

python src/merge_submission.py

源码开源协议

作者:SYSU-MSRA/中山大学-微软亚洲研究院联合实验室 Daya Guo

GPL-3.0 license

四、获取案例套装

需要登录后才允许下载文件包。登录 需要登录后才允许下载文件包。登录

发表评论