Dynamic Embedding
DynamicEmbedding 是特征零Hash冲突Id化的一种方式,它相比设置hash_bucket_size的方式能避免hash冲突,相比设置vocab_dict和vocab_list的方式能更灵活动态地进行id的准入和驱逐。DynamicEmbedding 常用于user id,item id,combo feature等超大id枚举数的特征配置中。DynamicEmbedding 相比 ZCH 能外接PS,支撑十亿百亿甚至更多的Id枚举数,Id准入和淘汰无需攒Batch,可以更加及时。
注:目前使用DynamicEmbedding还处于实验阶段,配置和接口都可能调整,暂只支持训练和评估,暂不包含在官方提供的镜像环境中,使用前需要额外安装如下whl包
注:同一个 FeatureGroup 中若存在多个配置了 DynamicEmbedding 的特征,底层 dynamicemb 会自动将这些表融合到同一份存储里(table fusion),共享 cache/admission counter,降低显存占用并减少内存碎片,无需额外配置。
# DEVICE 可选: cu126/cu129 (支持 Python 3.10/3.11/3.12)
pip install dynamicemb==0.1.0+20260519.e0c1fbb.${DEVICE} -f https://tzrec.oss-accelerate.aliyuncs.com/third_party/dynamicemb/${DEVICE}/repo.html
以id_feature的配置为例,DynamicEmbedding 只需在id_feature新增一个dynamicemb的配置字段
feature_configs {
id_feature {
feature_name: "cate"
expression: "item:cate"
embedding_dim: 32
dynamicemb {
max_capacity: 100000
initializer_args {
mode: "NORMAL"
std_dev: 0.05
}
score_strategy: "STEP"
frequency_admission_strategy {
threshold: 5
}
}
}
}
max_capacity: 最大的id数,Id数超过后会根据Id的驱逐策略进行淘汰
score_strategy: Id驱逐策略,默认为 STEP,目前支持 TIMESTAMP | STEP | LFU | NO_EVICTION
TIMESTAMP: 每个Id根据最近更新的时间戳,驱逐时间戳最小的Id
STEP: 每个Id根据最近更新的迭代步数,驱逐步数最早的Id
LFU: 每个Id根据出现的频次,驱逐频次小的Id
NO_EVICTION: 不驱逐,表容量到达
max_capacity后不再接收新Id,适合配合init_capacity_per_rank做可扩容的表
bucket_capacity: (可选)dynamicemb 哈希表 bucket 大小,默认为 128,增大可提升表的装填率但会增加每次查表的探测代价
initializer_args: 参数初始化设置,默认是 UNIFORM
mode: 初始化方式,可选 NORMAL | TRUNCATED_NORMAL | UNIFORM | CONSTANT
mean: NORMAL | TRUNCATED_NORMAL 初始化方式的均值,默认为 0
std_dev: NORMAL | TRUNCATED_NORMAL 初始化方式的标准差,默认为 sqrt(1 / embedding_dim)
lower: UNIFORM 初始化方式的均值的下界,默认为 - sqrt(1 / max_capacity)
upper: UNIFORM 初始化方式的均值的上界,默认为 sqrt(1 / max_capacity)
value: CONSTANT 初始化方式的值,默认为0
eval_initializer_args: (可选)评估时的初始化方式,默认是 CONSTANT,value=0
init_capacity_per_rank: (可选)初始的每个Rank上的id数,默认等于max_capacity
admission_strategy: (可选) 特征准入策略,默认不开启,目前只支持frequency_admission_strategy
frequency_admission_strategy: 基于频次的特征准入策略
threshold: 准入频次
initializer_args: (可选)未准入的ID的初始化方式,默认是 CONSTANT,value=0
counter_capacity: (可选)频次统计Counter的最大id数,默认与max_capacity相等
counter_bucket_capacity: (可选)频次统计Counter的每个bucket的最大id数,默认为1024
init_table: (可选)初始化表的路径,支持Odps/Parquet/Csv格式,表的第一列为id值,第二列为embedding值。
注意: init_table 参数不能再训练任务中直接生效,需要前置一个使用init_table构建初始化ckpt的任务,具体步骤如下
使用init_table构建初始化ckpt
python -m tzrec.tools.dynamicemb.create_dynamicemb_init_ckpt \ --pipeline_config_path {PATH_TO_CONFIG_WITH_DYNAMICEMB} \ --world_size $WORLD_SIZE*$NPROC_PER_NODE \ --save_dir {INIT_CKPT_PATH}
–pipeline_config_path: 训练配置文件
–world_size: 训练进程数,一般情况下为训练的torchrun命令中的 nnodes*nproc-per-node
–save_dir: 初始化模型保存目录
–reader_worker_num:(可选)读worker数目,默认为自动根据cpu核数设置
–separator: (可选) embedding数据类型如果为string的情况下的分隔符
使用初始化的ckpt训练模型
torchrun --master_addr=$MASTER_ADDR --master_port=$MASTER_PORT \ --nnodes=$WORLD_SIZE --nproc-per-node=$NPROC_PER_NODE --node_rank=$RANK \ -m tzrec.train_eval \ --pipeline_config_path {PATH_TO_CONFIG_WITH_DYNAMICEMB} \ --fine_tune_checkpoint {INIT_CKPT_PATH}/model.ckpt-0
从ZCH训练好的模型迁移
如果已有用 zch{} 训练好的模型,希望切换到 dynamicemb{} 继续训练,可以使用 tzrec.tools.dynamicemb.zch_to_dynamicemb_convert 将ZCH checkpoint 转换为 dynamicemb 格式的 checkpoint,下游训练任务直接通过 --fine_tune_checkpoint 热启动。
python -m tzrec.tools.dynamicemb.zch_to_dynamicemb_convert \
--source_checkpoint_path {ZCH_CKPT_PATH}/model.ckpt-N \
--source_pipeline_config_path {PATH_TO_CONFIG_WITH_ZCH} \
--target_pipeline_config_path {PATH_TO_CONFIG_WITH_DYNAMICEMB} \
--save_dir {CONVERTED_CKPT_PATH}
–source_checkpoint_path: ZCH 训练好的 checkpoint 目录(形如
.../model.ckpt-N/,需包含model/子目录的 DCP 分片)–source_pipeline_config_path: 原始训练所用的 pipeline 配置(特征上配置了
zch{})–target_pipeline_config_path: 切换后的 pipeline 配置(同名特征上将
zch{}替换为dynamicemb{},embedding_dim保持一致)–save_dir: 转换后 checkpoint 的输出目录,工具会写入
{save_dir}/model.ckpt-0/–world_size:(可选)转换后 dynamicemb 分片的 world_size,默认从 source checkpoint 的
.distcp文件名自动识别
迁移内容
Embedding: ZCH 表中已学到的 embedding 向量会迁移到 dynamicemb。
分数(Scores): 仅当目标
score_strategy为LFU或STEP时迁移;其它策略 dynamicemb 会自行初始化分数。非 ZCH 部分: 稠密层、非 ZCH embedding 及其对应 optimizer state 直接保留。
未迁移内容
ZCH embedding 的 optimizer state 不迁移,dynamicemb 加载后自行冷启动。
ZCH 本身的配置详见 ZCH。