【人工智能】多目标融合算法(二):底部共享多任务模型(Shared-Bottom Multi-task Model)

【人工智能】多目标融合算法(二):底部共享多任务模型(Shared-Bottom Multi-task Model)

 

目录

一、引言

1.1 往期回顾

1.2 本期概要

二、Shared-Bottom Multi-task Model(SBMM)

2.1 技术原理

2.2 技术优缺点

2.3 业务代码实践

三、总结


一、引言

在朴素的深度学习ctr预估模型中(如DNN),通常以一个行为为预估目标,比如通过ctr预估点击率。但实际推荐系统业务场景中,更多是多种目标融合的结果,比如视频推荐,会存在视频点击率、视频完整播放率、视频播放时长等多个目标,而多种目标如何更好的融合,在工业界与学术界均有较多内容产出,由于该环节对实际业务影响最为直接,特开此专栏对推荐系统深度学习多目标问题进行讲述。

1.1 往期回顾

上一篇文章主要介绍了推荐系统多目标算法中的“样本Loss加权”,该方法在训练时Loss乘以样本权重实现对多种目标的加权,通过引导Loss梯度的学习方向,让模型参数朝着你设定的权重方向去学习。

1.2 本期概要

今天进一步深化,主要介绍Shared-Bottom Multi-task Model算法,该算法中文可译为“底部共享多任务模型”,该算法设定多个任务,每个任务设定多个目标,通过“Loss计算时调整每个任务的权重”,亦或是“每个塔单元内,多目标Loss计算时调整每个目标的权重”进行多任务多目标的调整。

二、Shared-Bottom Multi-task Model(SBMM)

2.1 技术原理

Shared-Bottom Multi-task Model(SBMM)全称为底层共享多任务模型,主要由底层共享网络、多任务塔、多目标输出构成。核心原理:通过构造多任务多目标样本数据,在Loss计算环节,将各任务Loss求和(或加权求和),对Loss求导(求梯度)后,逐步后向传播迭代。

底部网络:Shared-Bottom 网络通常位于底部,可以为一个DNN网络,或者emb+pooling+mlp的方式对input输入的稀疏(sparse)特征进行稠密(dense)化。多个任务塔:底部网络上层接N个任务塔(Tower),每个塔根据需要可以定义为简单或复杂的多层感知器(mlp)网络。每个塔可以对应特定的场景,比如一二级页面场景。多个目标:每个任务塔(Tower)可以输出多个学习目标,每个学习目标还可以像上一篇文章一样进行样本Loss加权。每个目标可以对应一种特定的指标行为,比如点击、时长、下单等。

2.2 技术优缺点

相比于上一篇文章提到的样本Loss加权融合法,以及后续文章将会介绍的MoE、MMoE方法,有如下优缺点:

优点:可以对多级场景任务进行建模,使得ctcvr等点击后转化问题可以被深度学习浅层参数共享,互相补充学习,任务相关性越高,模型的loss可以降低到更低

缺点: 跷跷板问题:任务没有好的相关性时,这种Hard parameter sharing会损害效果

2.3 业务代码实践

我们以小红书推荐场景为例,用户在一级发现页场景中停留并点击了“误杀3”中的一个视频笔记,在二级场景视频播放页中观看并点赞了视频。

跨场景多目标建模:我们定义一个SBMM算法结构,底层是一个3层的MLP(64,32,16),MLP出来后接一级场景Tower和二级场景Tower,一级场景任务中分别定义视频一级页“是否停留”、“停留时长”、“是否点击”,二级场景任务中分别定义“点击后播放时长”,“播放后是否点赞”

伪代码:

导入 pytorch 库 定义 SharedBottomMultiTaskModel 类 继承自 nn.Module: 定义 __init__ 方法 参数 (self, 输入维度, 隐藏层1大小, 隐藏层2大小, 隐藏层3大小, 输出任务1维度, 输出任务2维度): 初始化共享底部的三层全连接层 初始化任务1的三层全连接层 初始化任务2的三层全连接层 定义 forward 方法 参数 (self, 输入数据): 计算输入数据通过共享底部后的输出 从共享底部输出分别计算任务1和任务2的结果 返回任务1和任务2的结果 生成虚拟样本数据: 创建训练集和测试集 实例化模型对象 定义损失函数和优化器 训练循环: 前向传播: 获取预测值 计算每个任务的损失 反向传播和优化

PyTorch版本:

算法逻辑导入必要的库。定义一个类来表示共享底部和特定任务头部的模型结构。在初始化方法中定义共享底部和两个独立的任务头部网络层。实现前向传播函数,处理输入数据通过共享底部后分发到不同的任务头部。生成虚拟样本数据。定义损失函数和优化器。编写训练循环。进行模型预测。
import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader, TensorDataset class SharedBottomMultiTaskModel(nn.Module): def __init__(self, input_dim, hidden1_dim, hidden2_dim, hidden3_dim, output_task1_dim, output_task2_dim): super(SharedBottomMultiTaskModel, self).__init__() # 定义共享底部的三层全连接层 self.shared_bottom = nn.Sequential( nn.Linear(input_dim, hidden1_dim), nn.ReLU(), nn.Linear(hidden1_dim, hidden2_dim), nn.ReLU(), nn.Linear(hidden2_dim, hidden3_dim), nn.ReLU() ) # 定义任务1的三层全连接层 self.task1_head = nn.Sequential( nn.Linear(hidden3_dim, hidden2_dim), nn.ReLU(), nn.Linear(hidden2_dim, output_task1_dim) ) # 定义任务2的三层全连接层 self.task2_head = nn.Sequential( nn.Linear(hidden3_dim, hidden2_dim), nn.ReLU(), nn.Linear(hidden2_dim, output_task2_dim) ) def forward(self, x): # 计算输入数据通过共享底部后的输出 shared_output = self.shared_bottom(x) # 从共享底部输出分别计算任务1和任务2的结果 task1_output = self.task1_head(shared_output) task2_output = self.task2_head(shared_output) return task1_output, task2_output # 构造虚拟样本数据 torch.manual_seed(42) # 设置随机种子以保证结果可重复 input_dim = 10 task1_dim = 3 task2_dim = 2 num_samples = 1000 X_train = torch.randn(num_samples, input_dim) y_train_task1 = torch.randn(num_samples, task1_dim) # 假设任务1的输出维度为task1_dim y_train_task2 = torch.randn(num_samples, task2_dim) # 假设任务2的输出维度为task2_dim # 创建数据加载器 train_dataset = TensorDataset(X_train, y_train_task1, y_train_task2) train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True) # 实例化模型对象 model = SharedBottomMultiTaskModel(input_dim, 64, 32, 16, task1_dim, task2_dim) # 定义损失函数和优化器 criterion_task1 = nn.MSELoss() criterion_task2 = nn.MSELoss() optimizer = optim.Adam(model.parameters(), lr=0.001) # 训练循环 num_epochs = 10 for epoch in range(num_epochs): model.train() running_loss = 0.0 for batch_idx, (X_batch, y_task1_batch, y_task2_batch) in enumerate(train_loader): # 前向传播: 获取预测值 outputs_task1, outputs_task2 = model(X_batch) # 计算每个任务的损失 loss_task1 = criterion_task1(outputs_task1, y_task1_batch) loss_task2 = criterion_task2(outputs_task2, y_task2_batch) #print(f'loss_task1:{loss_task1},loss_task2:{loss_task2}') total_loss = loss_task1 + loss_task2 # 反向传播和优化 optimizer.zero_grad() total_loss.backward() optimizer.step() running_loss += total_loss.item() print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {running_loss/len(train_loader):.4f}') # 模型预测 model.eval() with torch.no_grad(): test_input = torch.randn(1, input_dim) # 构造一个测试样本 pred_task1, pred_task2 = model(test_input) print(f'任务1预测结果: {pred_task1}') print(f'任务2预测结果: {pred_task2}')

三、总结

本文从技术原理、技术优缺点方面对推荐系统深度学习多任务多目标“Shared-Bottom Multi-task Model”算法进行讲解,该模型使用深度学习模型对多个任务场景多个目标的业务问题进行建模,使得用户在多个场景连续性行为可以被学习,在现实推荐系统业务中是比较基础的方法,后面本专栏还会陆续介绍MoE、MMoE等多任务多目标算法,期待您的关注和支持。

如果您还有时间,欢迎阅读本专栏的其他文章:

【深度学习】多目标融合算法(一):样本Loss加权(Sample Loss Reweight)

【深度学习】多目标融合算法(二):底部共享多任务模型(Shared-Bottom Multi-task Model) 

Read more

脉脉平台深度测评:AI创作者不可错过的xAMA活动

脉脉平台深度测评:AI创作者不可错过的xAMA活动

🔥个人主页:Cx330🌸 ❄️个人专栏:《C语言》《LeetCode刷题集》《数据结构-初阶》《C++知识分享》 《优选算法指南-必刷经典100题》《Linux操作系统》:从入门到入魔 《Git深度解析》:版本管理实战全解 🌟心向往之行必能至 🎥Cx330🌸的简介: 前言 : 在 AI 创作与职场社交深度融合的当下,脉脉凭借 1.2 亿 + 中高端职场用户基数,已从单纯的人脉平台升级为 “创作者成长沃土”。本文实测脉脉核心功能,并重点拆解其王牌活动 —— 创作者 xAMA,为技术人提供 “找资源 + 学创作 + 拓人脉” 的实战指南。 目录 前言 : 一、脉脉平台核心价值测评 1.1 定位:实名制职场生态的独特优势 1.2 核心功能实测(附实用度评级) 1.3

飞算JavaAI开发在线图书借阅平台全记录:从0到1的实践指南

飞算JavaAI开发在线图书借阅平台全记录:从0到1的实践指南

免责声明:此文章的所有内容皆是本人实验测评,并非广告推广,并非抄袭。如有侵权,请联系,谢谢! 目录 一、需求分析与规划 1.1、功能需求 1.2、核心模块 1.3、技术选型 二、飞算JavaAI开发实录 三、优化与调试心得 3.1、SQL性能优化:精准打击,提升查询效率 3.2、并发控制:乐观锁机制,解决超卖难题 3.3、缓存策略调整:从本地到分布式,应对高并发挑战 四、成果展示与总结 工程结构图 核心API列表 核心代码的实现: 飞算JavaAI优势总结 待改进方向 开发体会 一、需求分析与规划 我们可以直接在飞算Java AI里面自带的智能会话功能,

CLI-Anything:一条命令把任意软件变成 AI Agent 原生工具,到底怎么做到的?

CLI-Anything:一条命令把任意软件变成 AI Agent 原生工具,到底怎么做到的?

快速摘要 CLI-Anything 是香港大学数据科学实验室(HKUDS)开源的一个项目,核心做的事情只有一件:把那些只有图形界面的专业软件(GIMP、Blender、LibreOffice、OBS 等),自动生成一套完整的命令行接口(CLI),让 AI Agent 能像操作终端命令一样直接调用这些软件的全部功能。 它以 Claude Code 插件的形式分发,整个过程分为 7 个阶段全自动完成,已在 9 款专业软件上通过了超过 1400 项测试。如果你正在做 AI Agent 相关的开发工作,或者对"让 AI 操控真实软件"这个方向感兴趣,往下看有更详细的原理拆解和上手教程。 这个项目到底在解决什么问题? 做过 AI Agent 开发的朋友应该都有体会:目前的 Agent 在&

OpenClaw(小龙虾)B 端企业级应用实战:CentOS 7 快速部署指南,拥有你的第一个 AI 运维员工

大家好,我是独孤风。 春节期间,OpenClaw(小龙虾)彻底火了,人人都在谈论如何“养一只自己的小龙虾”。 过去一年,我们见识了太多能言善辩的大模型,但它们大多停留在“动嘴”阶段。你问它怎么重启服务器,它给你列出 1234 步骤,最后还得你自己去敲键盘。而 OpenClaw 的爆火,是因为它彻底解决了 “执行” 的问题。 它不是一个只会聊天的对话框,而是一个住在你服务器里、拥有操作权限、能 7x24 小时不间断工作的 “数字员工”。  但是,目前的大部分应用还是停留在助手阶段,帮助我们做一些简单的事务性的工作。在 B 端企业级场景下,应用几乎是没有的。那么OpenClaw能不能在B端应用呢?它的出现能否直接改写了运维与开发的成本结构呢?这篇文章我们就来实战一下,实现一个最基本的OpenClaw小龙虾AI运维员工。 正文共:6013字 25图 预计阅读时间:16分钟 文末联系作者,加入AI学习交流群 一、