AI比赛-推荐系统(一)-新闻推荐03:多路召回【用不同策略分别召回部分候选集,然后把候选集混在一起供后续排序模型使用】【①、YoutubeDNN双塔召回;②、基于物品召回;③、基于用户召回】【天池】

本文探讨了新闻推荐系统中的多路召回策略,包括基于双塔的YoutubeDNN召回、物品和用户协同过滤、物品embedding相似度召回等方法。通过对用户点击日志的处理和相似度矩阵计算,提升召回率和效率,为后续排序模型提供候选集。
摘要由CSDN通过智能技术生成

所谓的“多路召回”策略,就是指采用不同的策略、特征或简单模型,分别召回一部分候选集,然后把候选集混合在一起供后续排序模型使用,可以明显的看出,“多路召回策略”是在“计算速度”和“召回率”之间进行权衡的结果。其中,各种简单策略保证候选集的快速召回,从不同角度设计的策略保证召回率接近理想的状态,不至于损伤排序效果。如下图是多路召回的一个示意图,在多路召回中,每个策略之间毫不相关,所以一般可以写并发多线程同时进行,这样可以更加高效。

上图只是一个多路召回的例子,也就是说可以使用多种不同的策略来获取用户排序的候选商品集合,而具体使用哪些召回策略其实是与业务强相关的 ,针对不同的任务就会有对于该业务真实场景下需要考虑的召回规则。例如新闻推荐,召回规则可以是“热门新闻”、“作者召回”、“关键词召回”、“主题召回“、”协同过滤召回“等等。

导包

import pandas as pd  
import numpy as np
from tqdm import tqdm  
from collections import defaultdict  
import os, math, warnings, math, pickle
from tqdm import tqdm
import faiss
import collections
import random
from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import LabelEncoder
from datetime import datetime
from deepctr.feature_column import SparseFeat, VarLenSparseFeat
import tensorflow as tf
if tf.__version__ >= '2.0.0':
    tf.compat.v1.disable_eager_execution()
from tensorflow.python.keras import backend as K
K.set_learning_phase(True)
from tensorflow.python.keras.models import Model
from tensorflow.python.keras.preprocessing.sequence import pad_sequences    # pip install tensorflow==2.5.0
from deepmatch.models import *
from deepmatch.utils import sampledsoftmaxloss

warnings.filterwarnings('ignore')
# 设置整个开发环境的seed
def seed_everything(seed=1029):
    os.environ['PYTHONHASHSEED'] = str(seed)
    np.random.seed(seed)
seed_everything()
data_path = './data_raw/'
save_path = './temp_results/'

# 做召回评估的一个标志, 如果不进行评估就是直接使用全量数据进行召回
metric_recall = True
# 定义一个多路召回的字典,将各路召回的结果都保存在这个字典当中
user_multi_recall_dict =  {'itemcf_sim_itemcf_recall': {}, 'embedding_sim_item_recall': {}, 'usercf_u2u2i_recall' : {}, 'youtubednn_recall': {}, 'youtubednn_usercf_recall': {}, 'cold_start_recall': {}}   

一、读取数据

在一般的rs比赛中读取数据部分主要分为三种模式, 不同的模式对应的不同的数据集:

  1. debug模式: 这个的目的是帮助我们基于数据先搭建一个简易的baseline并跑通, 保证写的baseline代码没有什么问题。 由于推荐比赛的数据往往非常巨大, 如果一上来直接采用全部的数据进行分析,搭建baseline框架, 往往会带来时间和设备上的损耗, **所以这时候我们往往需要从海量数据的训练集中随机抽取一部分样本来进行调试(train_click_log_sample)**, 先跑通一个baseline。
  2. 线下验证模式: 这个的目的是帮助我们在线下基于已有的训练集数据, 来选择好合适的模型和一些超参数。 **所以我们这一块只需要加载整个训练集(train_click_log)**, 然后把整个训练集再分成训练集和验证集。 训练集是模型的训练数据, 验证集部分帮助我们调整模型的参数和其他的一些超参数。
  3. 线上模式: 我们用debug模式搭建起一个推荐系统比赛的baseline, 用线下验证模式选择好了模型和一些超参数, 这一部分就是真正的对于给定的测试集进行预测, 提交到线上, **所以这一块使用的训练数据集是全量的数据集(train_click_log+test_click_log)**

1、读取用户点击新闻日志数据

下面就分别对这三种不同的数据读取模式先建立不同的代导入函数, 方便后面针对不同的模式下导入数据。

# 从训练集中读取数据
def get_click_df(data_path, debug=True, sample_nums=10000, offline=True):
    # debug模式: 从训练集中划出一部分数据来调试代码
    if debug:
        """
            训练集中采样一部分数据调试
            data_path: 原数据的存储路径
            sample_nums: 采样数目(这里由于机器的内存限制,可以采样用户做)
        """
        all_click = pd.read_csv(data_path + 'train_click_log.csv')
        all_user_ids = all_click.user_id.unique()
        sample_user_ids = np.random.choice(all_user_ids, size=sample_nums, replace=False) 
        all_click = all_click[all_click['user_id'].isin(sample_user_ids)]
        all_click = all_click.drop_duplicates((['user_id', 'click_article_id', 'click_timestamp'])) # 去重
        
        return all_click
    else:
        # 读取点击数据,这里分成线上和线下,如果是为了获取线上提交结果应该将测试集中的点击数据合并到总的数据中
        # 如果是为了线下验证模型的有效性或者特征的有效性,可以只使用训练集,这里只是用训练集
        """
            data_path: 原数据的存储路径
            sample_nums: 采样数目(这里由于机器的内存限制,可以采样用户做)
        """
        if offline:
            all_click = pd.read_csv(data_path + 'train_click_log.csv')
        else:
            trn_click = pd.read_csv(data_path + 'train_click_log.csv')
            tst_click = pd.read_csv(data_path + 'testA_click_log.csv')
            all_click = trn_click.append(tst_click)
        all_click = all_click.drop_duplicates((['user_id', 'click_article_id', 'click_timestamp'])) # 去重

        return all_click
# 读取用户点击新闻日志数据
all_click_df = get_click_df(data_path=data_path, debug=False, offline=True)
all_click_df = all_click_df.sort_values('click_timestamp')
all_click_df
user_id click_article_id click_timestamp click_environment click_deviceGroup click_os click_country click_region click_referrer_type
3 199998 157770 1507029532200 4 1 17 1 25 5
45 199987 272143 1507029551778 4 1 17 1 24 5
52 199984 70594 1507029553199 4 3 2 1 5 7
32 199990 272143 1507029564434 4 1 17 1 7 5
0 199999 160417 1507029570190 4 1 17 1 13 1
... ... ... ... ... ... ... ... ... ...
705656 121158 224148 1509798422502 4 1 17 1 13 2
925954 70254 207672 1510093882860 4 1 17 1 20 2
925955 70254 96333 1510093912860 4 1 17 1 20 2
1091177 2465 203538 1510603424886 4 1 17 1 2 2
1091178 2465 145309 1510603454886 4 1 17 1 2 2

1112623 rows × 9 columns

2、对用户点击新闻日志数据的时间戳进行归一化,用于在关联规则的时候计算权重

# 对时间戳进行归一化,用于在关联规则的时候计算权重
max_min_scaler = lambda x : (x-np.min(x))/(np.max(x)-np.min(x))
all_click_df['click_timestamp'] = all_click_df[['click_timestamp']].apply(max_min_scaler)
all_click_df
user_id click_article_id click_timestamp click_environment click_deviceGroup click_os click_country click_region click_referrer_type
3 199998 157770 0.000000 4 1 17 1 25 5
45 199987 272143 0.000005 4 1 17 1 24 5
52 199984 70594 0.000006 4 3 2 1 5 7
32 199990 272143 0.000009 4 1 17 1 7 5
0 199999 160417 0.000011 4 1 17 1 13 1
... ... ... ... ... ... ... ... ... ...
705656 121158 224148 0.774748 4 1 17 1 13 2
925954 70254 207672 0.857419 4 1 17 1 20 2
925955 70254 96333 0.857428 4 1 17 1 20 2
1091177 2465 203538 0.999992 4 1 17 1 2 2
1091178 2465 145309 1.000000 4 1 17 1 2 2

1112623 rows × 9 columns

3、获取历史和最后一次点击

这个在评估召回结果, 特征工程和制作标签转成监督学习测试集的时候回用到

# 获取当前数据的历史点击和最后一次点击
def get_hist_and_last_click(all_click):
    all_click = all_click.sort_values(by=['user_id', 'click_timestamp'])
    click_last_df = all_click.groupby('user_id').tail(1)    # 最后一个点击
    # 如果用户只有一个点击,history为空了,会导致训练的时候这个用户不可见,此时默认泄露一下
    def history_func(user_df):
        if len(user_df) == 1:
            return user_df
        else:
            return user_df[:-1]
    click_history_df = all_click.groupby('user_id').apply(history_func).reset_index(drop=True)

    return click_history_df, click_last_df
# 使用召回评估函数验证当前召回方式的效果
# 这里是为了召回评估,所以提取最后一次点击作为召回评估,如果不需要做召回评估直接使用全量的训练集进行召回(线下验证模型)【如果不是召回评估,直接使用全量数据进行召回,不用将最后一次提取出来】
if metric_recall:
    trn_hist_click_df, trn_last_click_df = get_hist_and_last_click(all_click_df) # 这里是为了召回评估,所以提取最后一次点击  406431, 90000
else:
    trn_hist_click_df = all_click_df
trn_hist_click_df
user_id click_article_id click_timestamp click_environment click_deviceGroup click_os click_country click_region click_referrer_type
0 0 30760 0.330768 4 1 17 1 25 2
1 1 289197 0.330669 4 1 17 1 25 6
2 2 36162 0.330703 4 3 20 1 25 2
3 3 50644 0.330681 4 3 2 1 25 2
4 4 42567 0.330755 4 1 12 1 16 1
... ... ... ... ... ... ... ... ... ...
912618 199999 161191 0.177905 4 1 17 1 13 1
912619 199999 42223 0.177913 4
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值