推荐系统中的偏差问题

背景:1.在实际电商或者视频推荐场景中,流行度偏差是肯定存在的,所以所获得的数据集是具有流行度偏差的数据集。2.推荐系统的链路中包括了多个召回模型。3.如果所采用的召回模型不是无偏的话,例如双塔模型,就会被流行度偏差所影响,导致用户表征很相似,召回的内容大都是热门商品或视频,没有个性化。

问题:1.在工业界似乎并不是都采用的去偏的召回模型,那么如果采用的不是去偏的召回模型,工业界通常如何解决这个问题呢?(业界常用的有效的技术)

2.粗排和精排模型也是使用这个数据集,那么也会导致流行度偏差,这个采取什么策略解决呢?

注: 没实际解决过的就不要回答了,国外的chatgpt,国内的大语言模型我都试过了

引用 皆我百晓生 小程序回复内容作答:
解决推荐系统中的偏差问题可以采取以下策略:

  1. 采用去偏的召回模型:为了解决流行度偏差问题,可以采用一些去偏的召回模型,如PersonalRank算法、ItemCF算法等,这些算法可以通过一些调整来减弱或消除流行度偏差影响。

  2. 引入多样性推荐:为了避免推荐系统只关注热门商品或视频,可以引入多样性推荐策略,例如基于内容的推荐、基于用户兴趣的个性化推荐等。这些策略可以通过考虑用户的多样兴趣来提供更加个性化的推荐结果,减少流行度偏差带来的影响。

  3. 使用排序模型优化:在粗排和精排模型中,可以引入一些排序算法,如LambdaFM、RankNet等,通过优化排序模型来减少流行度偏差的影响。这些排序模型可以通过考虑用户的历史行为和兴趣,精确预测用户的喜好,从而提供更有针对性的推荐结果。

  4. 加入用户反馈机制:为了更好地解决流行度偏差问题,可以通过加入用户反馈机制来提高推荐准确度。例如,引入用户对推荐结果的评价、点击、购买等反馈信息,通过分析这些信息,可以对推荐算法进行优化,减少流行度偏差的影响。

  5. 评估和监控推荐结果:为了不断改进推荐算法,需要对推荐结果进行评估和监控,包括点击率、转化率等指标的监测。通过对推荐结果进行评估和监控,可以及时发现问题并进行调整,从而提高推荐系统的准确度和个性化程度,减少流行度偏差问题的影响。

【以下回答由 GPT 生成】

问题一解答:

在工业界,即使召回模型存在流行度偏差问题,也可以通过以下技术来解决:

  1. 多样性召回模型: 使用多个召回模型,每个模型使用不同的策略进行召回,以达到不同的个性化效果。这样可以一定程度上减少流行度偏差的影响,并提供更多样的推荐结果给用户。

  2. 随机负采样: 在生成训练样本时,除了使用正样本(用户真实点击或观看的物品),还可以引入随机负采样来生成负样本。负样本可以是用户未点击或未观看的物品,这样可以减轻流行度偏差的影响,提高模型的泛化能力。

  3. 时间衰减: 可以对不同时间段的物品赋予不同的权重。例如,对于较旧的物品,可以降低其权重,使其在召回过程中的影响力减小,进而减轻流行度偏差的问题。

  4. 基于用户和物品的特征加权: 可以根据用户和物品的一些特征,对召回结果进行加权。例如,可以根据用户的兴趣偏好和物品的属性,给召回结果赋予不同的分数或权重,以减少流行度偏差的影响。

Example code for time decay:

# 召回结果列表
rec_results = ['item1', 'item2', 'item3', 'item4']

# 每个物品对应的发布时间
item_publish_time = {'item1': '2021-01-01', 'item2': '2021-02-01', 'item3': '2021-02-15', 'item4': '2021-03-01'}

# 当前时间
current_time = '2021-04-01'

# 时间衰减函数
def time_decay(weight, publish_time, current_time):
    time_diff = (datetime.strptime(current_time, '%Y-%m-%d') - datetime.strptime(publish_time, '%Y-%m-%d')).days
    decay_factor = math.exp(-0.1 * time_diff)  # 可根据需求调整衰减因子
    return weight * decay_factor

# 根据时间衰减对召回结果进行加权
weighted_results = [time_decay(1, item_publish_time[item], current_time) for item in rec_results]

以上是一些解决流行度偏差问题的常用技术,当然还有其他方法,具体的选择可以根据实际情况和需求来确定。

问题二解答:

在粗排和精排模型中,同样可以采取一些策略来解决流行度偏差问题:

  1. 多样性特征引入: 在粗排模型中,可以引入一些多样性特征,例如所属类别、标签等,以增加个性化程度,减少流行度偏差的影响,从而在结果中呈现更多样的物品。

  2. 多尺度召回: 在粗排模型中可以使用多个召回模型,每个模型使用不同的召回策略,例如基于流行度、基于个性化兴趣等,通过综合多个召回结果来解决流行度偏差问题。

  3. 在线学习和A/B测试: 可以通过在线学习和A/B测试的方式,不断优化粗排和精排模型,评估不同策略对用户的推荐效果,并选择最佳的策略来解决流行度偏差问题。

  4. 反馈机制: 可以引入用户反馈信息,比如用户的点击、收藏、购买等行为作为重要特征,来影响粗排和精排模型的推荐结果。这样可以更好地反映用户的个性化需求,减轻流行度偏差的影响。

以上是一些常用的策略来解决粗排和精排模型中的流行度偏差问题,具体的选择和实施可以根据具体场景和需求来确定。



【相关推荐】



如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

对于召回模型:在推荐列表中过滤掉最热门的物品,以便为用户提供更多多样性的推荐。这可以通过设置一个流行度阈值或应用类似于“长尾”策略来实现。考虑用户的兴趣特点,为用户生成个性化的推荐列表,并根据用户对物品的历史交互情况来调整物品的权重。
对于粗排和精排模型:在粗排之后,使用一个重新排序策略来调整推荐列表的顺序,以更好地适应用户的兴趣。这个策略可以考虑用户历史行为、物品的流行度、物品的特征等。将粗排和精排模型结合起来,以确保用户在推荐列表中获得多样性的内容。粗排可以提供一些热门物品,而精排可以提供个性化的推荐。


Example code for time decay:
# 召回结果列表
rec_results = ['item1', 'item2', 'item3', 'item4']
# 每个物品对应的发布时间
item_publish_time = {'item1': '2021-01-01', 'item2': '2021-02-01', 'item3': '2021-02-15', 'item4': '2021-03-01'}
# 当前时间
current_time = '2021-04-01'
# 时间衰减函数
def time_decay(weight, publish_time, current_time):
    time_diff = (datetime.strptime(current_time, '%Y-%m-%d') - datetime.strptime(publish_time, '%Y-%m-%d')).days
    decay_factor = math.exp(-0.1 * time_diff)  # 可根据需求调整衰减因子
    return weight * decay_factor
# 根据时间衰减对召回结果进行加权
weighted_results = [time_decay(1, item_publish_time[item], current_time) for item in rec_results]


提供参考实例,建议和该博主私信沟通,至少是有目标的沟通,链接:https://blog.csdn.net/beilizhang/article/details/106323514

该回答通过自己思考并引用文心一言进行回答,如有帮助,还望采纳:
对于问题1:

在工业界中,如果采用的召回模型不是去偏的,通常会使用以下方法来解决这个问题:

混合召回策略:一种常用的方式是结合多种不同类型的召回模型,包括一些无偏的模型,如BERT等,以及一些有偏的模型,如双塔模型等。通过这种方式,可以在召回结果中平衡不同类型的信息,减少流行度偏差的影响。
个性化召回:在召回阶段引入用户个性化信息,如用户历史行为、偏好等,可以使得召回结果更加个性化,减少热门商品或视频的干扰。
重排序:在召回阶段获得的结果中,根据流行度或者其他因素(如用户历史行为、实时反馈等)对结果进行重排序,使得个性化、不热门的商品或视频有机会被推荐出去。
调整模型训练:针对数据集的流行度偏差,可以调整模型的训练方式。例如,可以在训练时增加对个性化、非热门商品的奖励,减少对热门商品的奖励,从而降低流行度偏差的影响。
对于问题2:

对于粗排和精排模型中使用同样的数据集导致流行度偏差的问题,可以采取以下策略来解决:

数据集扩展:通过引入更多的数据,来平衡流行度偏差。这可以是更广泛的数据源,或者是使用一些合成数据的方法来生成更多的非热门商品或视频的数据。
使用负采样:在训练过程中,对于流行的商品或视频,可以选择一些不相关的负样本进行训练,这样可以增加模型的多样性和泛化能力。
调整模型结构:对于粗排和精排模型,可以尝试不同的模型结构来适应流行度偏差。例如,可以在模型中引入一些能够捕捉到商品或视频的流行程度的模块。
后处理:在模型预测之后,可以通过一些后处理步骤来调整预测结果。例如,可以计算每个商品或视频的预测分数与商品流行度的差异,然后将这个差异加到预测分数上,以此来减少流行度偏差的影响。

该回答引用ChatGPT,希望对题主有所帮助


针对问题1,工业界通常采用的方法是通过流行度惩罚(Popularity Bias Correction)的方式进行解决。也就是在召回结果中,对热门商品或视频进行一定的惩罚,使得推荐结果更加多样化和个性化。具体实现方式可以是对推荐结果进行加权,根据商品或视频的流行度进行惩罚,或者在计算相似度的时候对流行度进行调整。此外,还可以采用一些行为序列建模的方法,利用用户历史行为信息,对用户的兴趣进行建模。

针对问题2,粗排和精排模型也可以采用流行度惩罚或者多样性惩罚的方式进行解决。粗排阶段可以采用一些基于物品流行度或者基于用户历史行为的模型进行排序,对热门商品或视频进行惩罚。精排阶段可以利用深度学习模型,对推荐结果进行加权或者调整,使得推荐结果更加多样化和个性化。此外,还可以采用一些序列建模的方法,结合用户历史行为信息和时间信息,对用户兴趣进行建模。

结合GPT给出回答如下请题主参考
在推荐系统中,流行度偏差是指对于热门物品的推荐程度更高,而对于不那么流行的物品则推荐程度更低的现象。这种偏差可能会导致推荐系统对于某些用户的推荐不够准确,从而降低用户体验。为了解决这个问题,可以采用一些方法来减少或消除流行度偏差。

一、概述

  1. 流行度偏差的定义和影响

流行度偏差是指对于热门物品的推荐程度更高,而对于不那么流行的物品则推荐程度更低的现象。这种偏差可能会导致推荐系统对于某些用户的推荐不够准确,从而降低用户体验。例如,如果一个音乐推荐系统只推荐最流行的几首歌曲给用户,那么用户就无法发现一些非常优秀但不那么流行的曲目。

  1. 解决流行度偏差的方法

为了解决流行度偏差问题,可以采用一些方法来减少或消除偏差。以下是一些具体的解决方法:

(1)基于物品相似度的推荐方法:通过计算物品之间的相似度来为用户推荐物品,这样偏好相似的物品之间就会互相引导,减少流行度偏差。例如,用户可能喜欢一些即使不那么流行但是和TA的兴趣相关的物品。

(2)基于用户兴趣相似度的推荐方法:通过计算用户之间的兴趣相似度来为用户推荐物品,这样有相似兴趣的用户之间就会互相引导,减少流行度偏差。

(3)基于热度的推荐方法:为了减少流行度偏差,可以采用基于热度的推荐策略,尽量向用户推荐一些与当前热门物品不同的物品,增加系统的多样性。

二、基于召回模型的解决方案

推荐系统中的链路中包括了多个召回模型。如果所采用的召回模型不是无偏的话,例如双塔模型,那么可能会导致流行度偏差的问题。为了解决这个问题,可以采用一些方法来减少或消除流行度偏差。

  1. 偏置和归一化:

在计算推荐结果时,可以通过减去一个物品的平均得分来消除偏置。另外,对于每个用户,可以将他所评分的物品得分归一化,这样可以将评分不均匀的用户对推荐的影响减小。

  1. 均衡采样:

为了消除流行度偏差,可以采用均衡采样的方法,即对于流行度比较高的物品,进行一定的降采样,使得流行度高的物品和流行度低的物品参与到训练中的样本数量相近。

  1. 相似性权重:

在计算相似性时,可以给不同物品赋予不同的权重,对于流行度比较高的物品给予较小的权重,对于流行度比较低的物品给予较大的权重,这样可以减少流行度偏差的影响。

下面给出一个基于双塔模型的推荐系统的代码示例。

import torch
from torch import nn
from torch.utils.data import DataLoader, Dataset
import numpy as np
import random

# 设置随机数种子
torch.manual_seed(1)
np.random.seed(1)
random.seed(1)

# 定义数据集
class RecDataset(Dataset):
    def __init__(self, user_dim, item_dim, data):
        self.user_dim = user_dim
        self.item_dim = item_dim
        self.data = data

    def __len__(self):
        return len(self.data)

    def __getitem__(self, index):
        user, item, score = self.data[index]
        user_vec = nn.functional.one_hot(torch.tensor(user), num_classes=self.user_dim)
        item_vec = nn.functional.one_hot(torch.tensor(item), num_classes=self.item_dim)
        score = torch.tensor(score).float()
        return user_vec, item_vec, score

# 定义双塔模型
class DualTower(nn.Module):
    def __init__(self, user_dim, item_dim, hidden_dim):
        super().__init__()
        self.user_emb = nn.Linear(user_dim, hidden_dim)
        self.item_emb = nn.Linear(item_dim, hidden_dim)
        self.score_pred = nn.Linear(hidden_dim, 1)

    def forward(self, user_vec, item_vec):
        user_emb = self.user_emb(user_vec.float())
        item_emb = self.item_emb(item_vec.float())
        x = user_emb * item_emb
        x = self.score_pred(x)
        return x.squeeze()

# 定义训练函数
def train(model, optimizer, data_loader, device):
    model.train()
    train_loss = 0.
    for i, (user_vec, item_vec, score) in enumerate(data_loader):
        optimizer.zero_grad()
        user_vec = user_vec.to(device)
        item_vec = item_vec.to(device)
        score = score.to(device)
        pred_score = model(user_vec, item_vec)
        loss = nn.MSELoss()(pred_score, score)
        loss.backward()
        optimizer.step()
        train_loss += loss.item()
    return train_loss / len(data_loader)

# 定义测试函数
def test(model, data_loader, device):
    model.eval()
    test_loss = 0.
    with torch.no_grad():
        for i, (user_vec, item_vec, score) in enumerate(data_loader):
            user_vec = user_vec.to(device)
            item_vec = item_vec.to(device)
            score = score.to(device)
            pred_score = model(user_vec, item_vec)
            loss = nn.MSELoss()(pred_score, score)
            test_loss += loss.item()
    return test_loss / len(data_loader)

# 加载数据
data = np.loadtxt('data.txt', dtype=int)
user_dim = np.amax(data[:, 0]) + 1
item_dim = np.amax(data[:, 1]) + 1
train_data = data[:int(0.8 * len(data))]
test_data = data[int(0.8 * len(data)):]
train_dataset = RecDataset(user_dim, item_dim, train_data)
test_dataset = RecDataset(user_dim, item_dim, test_data)
train_loader = DataLoader(train_dataset, batch_size=64)
test_loader = DataLoader(test_dataset, batch_size=64)

# 初始化模型和优化器
model = DualTower(user_dim, item_dim, 32)
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)

# 设置设备
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)

# 训练模型
for epoch in range(10):
    train_loss = train(model, optimizer, train_loader, device)
    test_loss = test(model, test_loader, device)
    print(f'Epoch {epoch+1}, train_loss: {train_loss:.4f}, test_loss: {test_loss:.4f}')

在上面的代码中,我们定义了一个名为 DualTower 的双塔模型,并且利用 RecDataset 来加载数据,然后使用 traintest 函数训练和评估模型。在训练模型时,我们可以根据上面提到的一些方法来解决流行度偏差问题,例如在计算相似性时给不同物品赋予不同的权重,或者在采样数据时进行均衡采样。

AI系统中的偏差与偏见
可以参考下


推荐系统中的偏差问题 - 知乎 写作背景写本文主要是因为最近要做ctr模型,建模涉及到样本构建的问题,光在样本构建中就要做许多工作,样本的好坏很大程度上能决定最终模型有多大程度接近特征决定的天花板。 在电商的点击率模型中,正样本与负样… https://zhuanlan.zhihu.com/p/470852961