用户下一个观看视频预测_baseline_CF

第三届“马栏山杯”国际音视频算法大赛

1. 赛题介绍

设法提高用户观看体验,是芒果TV平台的核心技术挑战之一,我们不断为此而努力!及时发现用户的兴趣和调整内容展示对于实现这一目标非常重要,在给定用户观影历史和上下文的行为的条件下,进行序列预测是一项非常重要且困难的推荐任务,本赛题将以此为背景,希望选手在真实样本数据集下建立出最优的序列预测模型。

2. 赛题任务

根据大赛组织方提供的用户在芒果TV产生的行为,视频特征,标签特征等数据,构建模型,预测用户在芒果TV下一个时刻观看的视频。

3. baseline_CF

import os
import pandas as pd
import time
from datetime import datetime
from tqdm import tqdmfrom collections import defaultdict
import math,pickle
import numpy as npdata_dir = '/Desktop/比赛/2022用户下一个观看视频预测'
seq = pd.read_csv(os.path.join(data_dir, 'dataset/main_vv_seq_train.csv'))candidates_items = pd.read_csv(os.path.join(data_dir, 'dataset/candidate_items_A.csv'))
candidates_set = set(candidates_items.vid)
def get_sim_item(df, user_col, item_col, use_iif=False):  user_item_ = df.groupby(user_col)[item_col].agg(set).reset_index()  user_item_dict = dict(zip(user_item_[user_col], user_item_[item_col]))  item_user_ = df.groupby(item_col)[user_col].agg(set).reset_index()  item_user_dict = dict(zip(item_user_[item_col], item_user_[user_col]))   sim_item_corr = {}for item, users in tqdm(item_user_dict.items()):sim_item_corr.setdefault(item, {}) for u in users:tmp_len = len(user_item_dict[u])for relate_item in user_item_dict[u]:sim_item_corr[item].setdefault(relate_item, 0)sim_item_corr[item][relate_item] += 1/ (math.log(len(users)+1) * math.log(tmp_len+1))return sim_item_corr  sim_item_corr = get_sim_item(train_sessions, 'did','vid',use_iif=True)
def recommend(sim_item_corr, popular_items, top_k, session_item_list, item_num=100):  rank = {}  for i in session_item_list:  if i not in sim_item_corr.keys():continuefor j, wij in sorted(sim_item_corr[i].items(), key=lambda d: d[1], reverse=True)[0:item_num]:  if j not in candidates_set:continueif j not in session_item_list:  rank.setdefault(j, 0)  rank[j] += wijif len(rank) > 0:rank = sorted(rank.items(), key=lambda d: d[1], reverse=True)[:top_k]rank = np.array(rank)# item_list = list(rank[:,0].astype('int32'))item_list = list(rank[:,0])score_list = rank[:,1]else:item_list = []score_list = []return item_list, score_list
top_k = 6
train_session_dict = seq.groupby('did')['vid'].agg(list).to_dict()
session_id_list = []
item_id_list = []
rank_list = []
for session_id,session_item_list in tqdm(train_session_dict.items()):item_list, score_list = recommend(sim_item_corr,popular_items,top_k,session_item_list)session_id_list += [session_id for _ in range(len(item_list))]item_id_list += list(item_list)rank_list += [x for x in range(1,len(item_list)+1)]
res_df = pd.DataFrame()
res_df['did'] = session_id_list
res_df['vid'] = item_id_list
res_df['rank'] = rank_listres_df.to_csv(data_dir + '/results/baseline_CF_0627.csv',index=False)

线上得分0.1672。这个比赛数据集相对于recsys2022那个来说,可操作空间大一些。

4. YoutubeDNN召回

4.1 数据处理

def gen_data_set(data, negsample=5):item_ids = data['vid'].unique()train_set = []test_set = []for reviewerID, hist in tqdm(data.groupby('did')):pos_list = hist['vid'].tolist()if negsample > 0:candidate_set = list(set(item_ids) - set(pos_list))   neg_list = np.random.choice(candidate_set,size=len(pos_list)*negsample,replace=True)  # 对于每个正样本,选择n个负样本if len(pos_list) == 1:train_set.append((reviewerID, [pos_list[0]], pos_list[0],1,len(pos_list)))test_set.append((reviewerID, [pos_list[0]], pos_list[0],1,len(pos_list)))# 滑窗构造正负样本for i in range(1, len(pos_list)):hist = pos_list[:i]if i != len(pos_list) - 1:train_set.append((reviewerID, hist[::-1], pos_list[i], 1, len(hist[::-1])))  # 正样本 [user_id, his_item, pos_item, label, len(his_item)]for negi in range(negsample):train_set.append((reviewerID, hist[::-1], neg_list[i*negsample+negi], 0,len(hist[::-1]))) # 负样本 [user_id, his_item, neg_item, label, len(his_item)]else:# 将最长的那一个序列长度作为测试数据test_set.append((reviewerID, hist[::-1], pos_list[i],1,len(hist[::-1])))random.shuffle(train_set)random.shuffle(test_set)return train_set, test_set# 将输入的数据进行padding,使得序列特征的长度都一致
def gen_model_input(train_set,user_profile,seq_max_len):train_uid = np.array([line[0] for line in train_set])train_seq = [line[1] for line in train_set]train_iid = np.array([line[2] for line in train_set])train_label = np.array([line[3] for line in train_set])train_hist_len = np.array([line[4] for line in train_set])train_seq_pad = pad_sequences(train_seq, maxlen=seq_max_len, padding='post', truncating='post', value=0)train_model_input = {"did": train_uid, "vid": train_iid, "hist_article_id": train_seq_pad,"hist_len": train_hist_len}return train_model_input, train_label
def youtubednn_u2i_dict(data, topk=7):    sparse_features = ["vid", "did"]SEQ_LEN = 30 # 用户点击序列的长度,短的填充,长的截断user_profile_ = data[["did"]].drop_duplicates('did')item_profile_ = data[["vid"]].drop_duplicates('vid')  # 类别编码features = ["vid", "did"]feature_max_idx = {}for feature in features:lbe = LabelEncoder()data[feature] = lbe.fit_transform(data[feature])feature_max_idx[feature] = data[feature].max() + 1# 提取did和vid的画像,具体选择哪些特征还需要进一步的分析和考虑user_profile = data[["did"]].drop_duplicates('did')item_profile = data[["vid"]].drop_duplicates('vid')  user_index_2_rawid = dict(zip(user_profile['did'], user_profile_['did']))item_index_2_rawid = dict(zip(item_profile['vid'], item_profile_['vid']))# 划分训练和测试集# 由于深度学习需要的数据量通常都是非常大的,所以为了保证召回的效果,往往会通过滑窗的形式扩充训练样本train_set, test_set = gen_data_set(data, 0)# 整理输入数据,具体的操作可以看上面的函数train_model_input, train_label = gen_model_input(train_set, user_profile, SEQ_LEN)test_model_input, test_label = gen_model_input(test_set, user_profile, SEQ_LEN)# 确定Embedding的维度embedding_dim = 32# 将数据整理成模型可以直接输入的形式user_feature_columns = [SparseFeat('did', feature_max_idx['did'], embedding_dim),VarLenSparseFeat(SparseFeat('hist_article_id', feature_max_idx['vid'], embedding_dim,embedding_name="vid"), SEQ_LEN, 'mean', 'hist_len'),]item_feature_columns = [SparseFeat('vid', feature_max_idx['vid'], embedding_dim)]from collections import Countertrain_counter = Counter(train_model_input['vid'])item_count = [train_counter.get(i, 0) for i in range(item_feature_columns[0].vocabulary_size)]sampler_config = NegativeSampler('frequency', num_sampled=5, item_name='vid', item_count=item_count)import tensorflow as tfif tf.__version__ >= '2.0.0':tf.compat.v1.disable_eager_execution()else:K.set_learning_phase(True)# 模型的定义print("staring!")model = YoutubeDNN(user_feature_columns, item_feature_columns, user_dnn_hidden_units=(256, 64, embedding_dim),sampler_config=sampler_config)# 模型编译model.compile(optimizer="adam", loss=sampledsoftmaxloss)  history = model.fit(train_model_input, train_label, batch_size=256, epochs=10, verbose=1, validation_split=0.0)test_user_model_input = test_model_inputall_item_model_input = {"vid": item_profile['vid'].values}user_embedding_model = Model(inputs=model.user_input, outputs=model.user_embedding)item_embedding_model = Model(inputs=model.item_input, outputs=model.item_embedding)user_embs = user_embedding_model.predict(test_user_model_input, batch_size=2 ** 12)item_embs = item_embedding_model.predict(all_item_model_input, batch_size=2 ** 12)# embedding保存之前归一化一下user_embs = user_embs / np.linalg.norm(user_embs, axis=1, keepdims=True)item_embs = item_embs / np.linalg.norm(item_embs, axis=1, keepdims=True)# 将Embedding转换成字典的形式方便查询raw_user_id_emb_dict = {user_index_2_rawid[k]: \v for k, v in zip(user_profile['did'], user_embs)}raw_item_id_emb_dict = {item_index_2_rawid[k]: \v for k, v in zip(item_profile['vid'], item_embs)}# 将Embedding保存到本地pickle.dump(raw_user_id_emb_dict, open('./temp_data/user_youtube_emb.pkl', 'wb'))pickle.dump(raw_item_id_emb_dict, open('./temp_data/item_youtube_emb.pkl', 'wb'))# faiss紧邻搜索,通过user_embedding 搜索与其相似性最高的topk个vidindex = faiss.IndexFlatIP(embedding_dim)index.add(item_embs) # 将vid向量构建索引sim, idx = index.search(np.ascontiguousarray(user_embs), topk) # 通过did去查询最相似的topk个viduser_recall_items_dict = collections.defaultdict(dict)for target_idx, sim_value_list, rele_idx_list in tqdm(zip(test_user_model_input['user_id'], sim, idx)):target_raw_id = user_index_2_rawid[target_idx]# 从1开始是为了去掉\id本身, 所以最终获得的相似商品只有topk-1for rele_idx, sim_value in zip(rele_idx_list[1:], sim_value_list[1:]): rele_raw_id = item_index_2_rawid[rele_idx]user_recall_items_dict[target_raw_id][rele_raw_id] = user_recall_items_dict.get(target_raw_id, {})\.get(rele_raw_id, 0) + sim_valueuser_recall_items_dict = {k: sorted(v.items(), key=lambda x: x[1], reverse=True) for k, v in user_recall_items_dict.items()}return user_recall_items_dict
user_recall_items_dict = youtubednn_u2i_dict(data, topk=20)

后续只要把字典读出来,转化成dataframe即可,不过我提交单独youtubeDNN的召回结果,咋是0分呢!有大佬能讲解一下吗?

2022芒果TV算法赛_用户下一个观看视频预测_baseline_CF召回YoutubeDNN相关推荐

  1. 深入理解操作系统(12)第四章:处理器体系结构(4)Y86-64的流水线实现(包括:PIPE-处理器/预测下一个PC/分支预测/流水线冒险/暂停,转发避免冒险/PPE硬件结构及实现/CPI)

    深入理解操作系统(12)第四章:处理器体系结构(4)Y86-64的流水线实现(包括:PIPE-处理器/预测下一个PC/分支预测/流水线冒险/暂停,转发避免冒险/PPE硬件结构及实现/CPI) 1. Y ...

  2. nasa数据库cm1数据集_获取下一个地理项目的NASA数据

    nasa数据库cm1数据集 NASA provides an extensive library of data points that they've captured over the years ...

  3. web密码尝试工具_尝试下一个Web项目的10种工具

    web密码尝试工具 接下来是一些工具的组合,您作为开发人员或设计人员可以尝试下一个项目. 该列表绝不是详尽无遗的,也不是任何事物的"前十名",而只是对那些寻求新事物的人的建议. 我 ...

  4. 供销大集长期持有_谁是下一个供销大集?(附股)

    昨天我们在文章分析了芯片这波行情的几个细节,觉得以芯片股的热点状态还是很健康的,以芯片为首的自主可控还有得玩. 今天,这个方向又有了新的变化,结合这些变化,再说说我们的跟踪思路. 昨天芯片股出现了高低 ...

  5. html5猜颜色游戏,好看漂亮的html5网页特效学习笔记(3)_猜猜下一个颜色是什么?...

    效果: 根据给出的两个连续颜色,玩家需要猜出下一个是什么颜色 随机关卡 使用vw,vh,vmin,vmax来屏幕自适应 很难玩 html+css+javascript,但js很短并不难,上手难度:简单 ...

  6. 响铃:视频彩铃,会是下一个短视频生态的入口吗?

    文|曾响铃 来源|科技向令说(xiangling0815) 刚刚过去的2019年春节照例是互联网大佬们营销攻势最猛烈的时候,春晚上百度四轮红包互动.抖音短视频互动十分惹眼,各平台在春节期间的红包雨或其 ...

  7. 使用redis实现缓存_用下一个js实现一个简单的redis缓存

    使用redis实现缓存 For most websites, the changing pieces don't actually vary that often. That immutability ...

  8. 安全大讲堂 | 2022产业趋势洞察:网络安全的下一个十年

    随着产业数字化发展进入深水区,网络的边界变得难以界定,数据分析如何应用于网络安全?随着云原生应用普及并开始承载企业核心生产系统,企业如何建构自身云原生安全防护能力?网络安全行业的机遇与挑战潜藏何处?未 ...

  9. python皮同_Python OpenCV 图像的双线性插值算法,全网最细致的算法说明_橡皮擦,一个逗趣的互联网高级网虫-CSDN博客...

    原文作者:梦想橡皮擦 原文标题:Python OpenCV 图像的双线性插值算法,全网最细致的算法说明 发布时间:2021-02-17 20:55:32 Python OpenCV 365 天学习计划 ...

  10. mysql udate 充值_分享下一个mysql的充值记录系统

    总共分为几个步骤" 1.链接mysql 2.所有用户到处到listview 3.查询(if(#r)判断找没找到而不是if(!r)) 4.就是充值那 5.充值记录调用进程process 完整代 ...

最新文章

  1. Nginx 正向代理与反向代理区别
  2. 拾牙的2021年秋招总结(大概会有帮助?)
  3. (王道408考研数据结构)第八章排序-第四节2:快速排序
  4. 如何安装Linux操作系统
  5. jsp是在html里面嵌入哪种代码?_再说嵌入式入门
  6. python降噪突出人声_KlipC带您探寻——华为全新智慧动态降噪耳机
  7. (转)开源的大文件上传组件NeatUpload
  8. JAVA--scjp证书。
  9. 基于VM10+Win7安装Mac OSX10.11 El Capitan
  10. vue项目之页面底部出现白边及空白区域错误记录
  11. UDP进程terminated
  12. IP协议(IP协议报头、MTU、网段划分、NAT技术、路由的工作过程)
  13. 浙江众源自控系统有限公司亮相2022生物发酵展(济南)7月14日与您相约
  14. go语言-channel使用(二十一)
  15. 【Unity】动作游戏开发实战详细分析-26-组合攻击
  16. 华为交换机配置consol密码及vty密码
  17. 枚举算法3——五猴分桃
  18. PowerPoint输出图片分辨率设置
  19. elasticsearch xpack license过期
  20. view设置圆角 android,Android 设置圆角View

热门文章

  1. python mysql插入数据报错:TypeError: %d format: a number is required, not str
  2. 微机——微型计算机系统组成及工作原理
  3. c语言中sys是什么文件夹,windows系统中C盘的pagefile.sys是什么文件
  4. 【英语学习工具】程序员学习英语硬背硬记太难了, 在这里推荐 LeHoCat 提供免费的,看视频学英语的工具,制作英语教学课件的工具,帮助自学英语
  5. YY0709|听觉报警信号要求及测试方法
  6. 2007年“网络十大炒女”排行榜
  7. DSPE;CAS:1069-79-0 ;二硬脂酰基磷脂酰乙醇胺;功能化磷脂
  8. 笔耕不辍,无问西东——2018年终小结
  9. 手机如何将PDF文件拆分?分享两种手机拆分文件方法
  10. 最短路径算法----Floyd-warshall(十字交叉算法证明)