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

目录

一、引言

二、样本Loss提权

2.1 技术原理

2.2 技术优缺点

2.3 代码实例

三、总结


一、引言

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

今天重点介绍“样本Loss提权”,该方法通过训练时Loss乘以样本权重实现对其它目标的加权,方法最为简单。

二、样本Loss提权

2.1 技术原理

所有目标使用一个模型,在标注正样本时,考虑多个目标。例如对于点击和播放,在标注正样本时,给予不同的权重,使它们综合体现在模型目标中。如下表,以视频业务为例,每行为一条训练样本,根据业务需要,把点击视频、视频完播、视频时长的权重分别设置为1、3、5。

该方法通过对不同正向行为给予不同权重,将多目标问题转化为单目标问题。本质是保证一个主目标的同时,将其它目标转化为样本权重,达到优化其它目标的效果。

2.2 技术优缺点

优点:

  • 模型简单:易于理解,仅在训练时通过Loss乘以样本权重实现对其它目标的加权
  • 成本较低:相比于训练多个目标模型再融合,单模型资源及维护成本更低

缺点: 

  • 优化周期长:每次调整样本加权系数,都需要重新训练模型至其收敛
  • 跷跷板问题:多个目标之间可能存在相关或互斥的问题,导致一个行为指标提升的同时,另一个指标下降。

2.3 代码实例

首先,我们需要定义一个DNN模型,并实现一个多目标样本损失函数loss加权算法。这个算法会为不同的目标分配不同的权重,以便在训练过程中优化每个目标的表现。 

TensorFlow版本:

代码步骤

  1. 导入库: 导入TensorFlow和其他必要的库。
  2. 数据准备: 假设我们有一个多目标的数据集,包含多个标签。
  3. 模型定义: 定义一个简单的DNN模型。
  4. 损失函数: 实现一个多目标的加权损失函数。
  5. 训练步骤: 编写训练循环,并使用自定义的损失函数来更新模型权重。
# Python

import tensorflow as tf
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Dense, Input
from tensorflow.keras.optimizers import Adam

# 假设我们有一个多目标的数据集,包含多个标签
# 数据准备部分在实际应用中可能更加复杂,这里简化处理
num_features = 10
num_targets = 3  # 假设有三个不同的预测目标
batch_size = 64
epochs = 10

# 定义一个简单的DNN模型
def create_model(input_shape, num_targets):
    inputs = Input(shape=(input_shape,))
    x = Dense(128, activation='relu')(inputs)
    x = Dense(64, activation='relu')(x)
    outputs = [Dense(1)(x) for _ in range(num_targets)]  # 每个目标一个输出
    model = Model(inputs=inputs, outputs=outputs)
    return model

model = create_model(input_shape=num_features, num_targets=num_targets)

# 自定义的多目标加权损失函数
def weighted_loss(weights):
    def loss(y_true_list, y_pred_list):
        total_loss = 0
        for weight, y_true, y_pred in zip(weights, y_true_list, y_pred_list):
            # 这里假设使用均方误差作为损失函数
            single_loss = tf.reduce_mean(tf.square(y_true - y_pred))
            total_loss += weight * single_loss
        return total_loss
    return loss

# 假设我们给每个目标分配的权重分别是0.5, 0.3, 0.2
loss_weights = [0.5, 0.3, 0.2]
model.compile(optimizer=Adam(), loss=weighted_loss(loss_weights))

# 生成一些虚拟数据以进行训练
import numpy as np

x_train = np.random.rand(1000, num_features)  # 随机生成特征
y_train_list = [np.random.rand(1000, 1) for _ in range(num_targets)]  # 每个目标的标签

# 训练模型
model.fit(x_train, y_train_list, batch_size=batch_size, epochs=epochs)

PyTorch版本:

代码结构

  1. 导入必要的库
  2. 定义多目标 DNN 模型
  3. 定义加权损失函数
  4. 生成虚拟数据并进行训练
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset

# 定义多目标 DNN 模型
class MultiTargetDNN(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim):
        super(MultiTargetDNN, self).__init__()
        self.fc1 = nn.Linear(input_dim, hidden_dim)
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(hidden_dim, output_dim)

    def forward(self, x):
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        return x

# 定义加权损失函数
def weighted_loss(weights):
    def loss(y_true_list, y_pred_list):
        total_loss = 0
        for weight, y_true, y_pred in zip(weights, y_true_list, y_pred_list):
            # 使用均方误差作为损失函数
            single_loss = nn.MSELoss()(y_true, y_pred)
            total_loss += weight * single_loss
        return total_loss
    return loss

# 生成虚拟数据
def generate_data(num_samples, input_dim, num_targets):
    x_train = torch.randn(num_samples, input_dim)
    y_train_list = [torch.randn(num_samples, 1) for _ in range(num_targets)]
    return x_train, y_train_list

# 主训练函数
def train_model(x_train, y_train_list, weights, num_epochs=10, batch_size=8):
    # 将数据转换为 DataLoader
    dataset = TensorDataset(*([x_train] + y_train_list))
    dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)

    # 初始化模型、损失函数和优化器
    input_dim = x_train.shape[1]
    hidden_dim = 64
    output_dim = len(y_train_list)
    model = MultiTargetDNN(input_dim, hidden_dim, output_dim)
    criterion = weighted_loss(weights)
    optimizer = optim.Adam(model.parameters(), lr=0.001)

    # 训练模型
    for epoch in range(num_epochs):
        total_loss = 0
        for batch in dataloader:
            x_batch = batch[0]
            y_true_list = batch[1:]

            # 前向传播
            optimizer.zero_grad()
            y_pred_list = model(x_batch).split(1, dim=1)
            loss_value = criterion(y_true_list, y_pred_list)

            # 反向传播和优化
            loss_value.backward()
            optimizer.step()

            total_loss += loss_value.item()

        print(f"Epoch {epoch + 1}: Loss = {total_loss / len(dataloader)}")

# 主函数
if __name__ == '__main__':
    # 设置参数
    num_samples = 64
    input_dim = 10
    num_targets = 3
    weights = [0.5, 0.3, 0.2]

    # 生成虚拟数据
    x_train, y_train_list = generate_data(num_samples, input_dim, num_targets)

    # 训练模型
    train_model(x_train, y_train_list, weights)

关键点解释:

  1. 多目标 DNN 模型:

    • MultiTargetDNN 类定义了一个简单的两层全连接网络,输入维度为 input_dim,隐藏层维度为 hidden_dim,输出维度为 output_dim(即目标数量)。
  2. 加权损失函数:

    • weighted_loss 函数接受权重列表,并返回一个损失计算函数。该函数通过循环遍历每个目标的预测值和真实值,计算均方误差并根据权重进行加权求和。
  3. 生成虚拟数据:

    • generate_data 函数生成随机输入数据 x_train 和多个目标的真实值 y_train_list
  4. 训练模型:

    • train_model 函数将数据加载到 DataLoader 中,并初始化模型、损失函数和优化器。
    • 在每个 epoch 中,遍历数据批次,进行前向传播、计算损失、反向传播和参数更新。

三、总结

本文从技术原理和技术优缺点方面对推荐系统深度学习多目标融合的“样本Loss加权”进行简要讲解,以达到对预期指标的强化,具有模型简单,成本较低的优点,但同时优化周期长、多个指标跷跷板问题也是该方法的缺点,业界针对该方法的缺点进行了一系列的升级,专栏中会逐步讲解,期待您的关注。

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

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

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

### 多损失函数权重分配方法 在机器学习模型中,当存在多个目标需要优化时,通常会引入多个损失函数。这些损失函数可能来自不同的任务或同任务的不同方面。为了平衡各个损失项的重要性,在训练过程中合理地为它们分配权重至关重要。 #### 加权求和方式 种常见的方式是对各单独定义好的损失函数采用加权求和的形式构建最终的整体损失函数: \[ L_{total} = w_1 \cdot L_1 + w_2 \cdot L_2 + ... + w_n \cdot L_n \] 这里 \(w_i\) 表示第 i 个特定损失对应的权重因子[^4]。通过调整不同部分的比重,可以让网络更侧重于某些类型的误差减少而非其他类型。 #### 动态调整策略 除了静态设定固定的权重外,还可以考虑动态改变这参数设置。例如基于当前阶段的学习进展状况自动调节;或是依据辅助任务的表现情况适时增减其影响力等高级技巧。这种方法能够使整个系统更加灵活高效地适应复杂场景下的需求变化[^3]。 #### 自动化搜索算法 近年来也有研究提出了利用自动化工具如贝叶斯优化、遗传算法乃至强化学习机制来寻找最优组合方案的可能性。这类方法试图在整个超参空间内探索最佳配置点,理论上可以获得更好的泛化性能[^2]。 ```python import torch.nn as nn class MultiTaskLoss(nn.Module): def __init__(self, task_num): super(MultiTaskLoss, self).__init__() self.weights = nn.Parameter(torch.ones(task_num)) def forward(self, losses): weighted_losses = [] for idx, loss in enumerate(losses): weight = self.weights[idx].exp() # Ensure positive weights via exponential function normalized_weighted_loss = (weight * loss).mean() weighted_losses.append(normalized_weighted_loss) total_loss = sum(weighted_losses) return total_loss ``` 此代码片段展示了如何实现个多任务损失模块 `MultiTaskLoss` ,它接受系列独立的任务损失并返回经过加权后的总损失值。注意这里的权重被设计成可学习参数,并通过指数运算确保始终是非负数[^1]。
评论 52
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值