1.数据读取和预处理
1.1源文件
文章相关
- articles.csv:文章ID、类型ID、创建时间戳、单词数
- articles_emb.csv:文章ID、emb_0到249
用户日志相关
- train_click_log.csv:用户点击日志训练集。包含用户ID、点击文章ID、点击时间、点击环境、点击设备、操作系统、点击次数、地区、点击时文章来源
- testA_click_log.csv:用户点击日志测试集。同上
1.2读取文件
1.2.1读取所有用户点击数据
将train_click_log.csv中所有的用户点击数据读取,并存入all_click。去除用户ID-文章ID-时间戳相同的重复数据
def get_all_click_df(data_path, offline=True):
"""
读取点击数据
如果是为了获取线上提交结果应该将测试集中的点击数据合并到总的数据中
如果是为了线下验证模型的有效性或者特征的有效性,可以只使用训练集
:param data_path: 原数据的存储路径
:param offline: 是否需要获取线上提交结果
:return: 点击数据
"""
print("是否需要线上结果:"+str(offline))
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']))
print("成功读取点击数据!")
return all_click
1.2.2读取文章基本属性
文章ID、类别ID、时间、单词数
def get_item_info_df(data_path):
"""
读取文章的基本属性
:param data_path: 原数据的存储路径
:return: 文章ID、类别ID、时间、单词数信息
"""
item_info_df = pd.read_csv(data_path + 'articles.csv')
# 为了方便与训练集中的click_article_id拼接,需要把article_id修改成click_article_id
item_info_df = item_info_df.rename(columns={'article_id': 'click_article_id'})
return item_info_df
1.2.3读取文章的embedding
读取每篇文章的embedding表示,存储为dict,key为文章ID,value为文章embedding
def get_item_emb_dict(data_path, save_path):
"""
读取文章的Embedding数据
:param data_path: 原数据的存储路径
:param save_path: emb存储路径
:return: 文章emb
"""
item_emb_df = pd.read_csv(data_path + 'articles_emb.csv')
item_emb_cols = [x for x in item_emb_df.columns if 'emb' in x]
# 将一个内存不连续存储的数组转换为内存连续存储的数组,使得运行速度更快
item_emb_np = np.ascontiguousarray(item_emb_df[item_emb_cols])
# 进行归一化
item_emb_np = item_emb_np / np.linalg.norm(item_emb_np, axis=1, keepdims=True)
# 将文章id和emb合为dict
item_emb_dict = dict(zip(item_emb_df['article_id'], item_emb_np))
# 存储文章emb的dict
pickle.dump(item_emb_dict, open(save_path + 'item_content_em.pkl', 'wb'))
print("成功读取所有文章embedding!")
return item_emb_dict
1.3数据处理
1.3.1 key用户-[(点击文章,点击时间)]字典
将一条一条的”用户ID、点击文章ID、点击时间、点击环境、点击设备、操作系统、点击次数、地区、点击时文章来源“数据,整理成字典,键为用户ID,值为(点击文章,点击时间)的列表
def get_user_item_time(click_df):
"""
根据点击时间获取用户的点击文章序列 {user1: {item1: time1, item2: time2..}...}
:param click_df: 读取的用户点击信息
:return: key用户-[(点击文章,点击时间)]字典
"""
def make_item_time_pair(df):
return list(zip(df['click_article_id'], df['click_timestamp']))
click_df = click_df.sort_values('click_timestamp')
user_item_time_df = click_df.groupby('user_id')[['click_article_id', 'click_timestamp']].apply(
lambda x: make_item_time_pair(x)).reset_index().rename(columns={0: 'item_time_list'})
user_item_time_dict = dict(zip(user_item_time_df['user_id'], user_item_time_df['item_time_list']))
print("成功获得用户-点击文章-点击时间字典!")
return user_item_time_dict
1.3.2 key文章-[(用户ID,点击时间)]字典
将一条一条的”用户ID、点击文章ID、点击时间、点击环境、点击设备、操作系统、点击次数、地区、点击时文章来源“数据,整理成字典,键为文章ID,值为(用户ID,点击时间)的列表
def get_item_user_time_dict(click_df):
"""
根据时间获取商品被点击的用户序列 {item1: {user1: time1, user2: time2...}...}
这里的时间是用户点击当前商品的时间
:param click_df: 读取的用户点击信息
:return:
"""
def make_user_time_pair(df):
return list(zip(df['user_id'], df['click_timestamp']))
click_df = click_df.sort_values('click_timestamp')
item_user_time_df = click_df.groupby('click_article_id')[['user_id', 'click_timestamp']].apply(
lambda x: make_user_time_pair(x)).reset_index().rename(columns={0: 'user_time_list'})
item_user_time_dict = dict(zip(item_user_time_df['click_article_id'], item_user_time_df['user_time_list']))
print("成功获得文章-点击用户-点击时间字典!")
return item_user_time_dict
1.3.3 划分历史信息和最后一次点击信息
将用户所有的点击信息划分为历史信息和最后一次点击信息,用户召回评估
def get_hist_and_last_click(all_click):
"""
获取当前数据的历史点击和最后一次点击
:param all_click: 用户全部点击日志
:return: 历史点击信息,最后一次点击信息
"""
all_click = all_click.sort_values(by=['user_id', 'click_timestamp'])
click_last_df = all_click.groupby('user_id').tail(1)
# 如果用户只有一个点击,hist为空了,会导致训练的时候这个用户不可见,此时默认泄露一下
def hist_func(user_df):
if len(user_df) == 1:
return user_df
else:
return user_df[:-1]
click_hist_df = all_click.groupby('user_id').apply(hist_func).reset_index(drop=True)
print("划分历史点击信息和最后一次点击信息!")
return click_hist_df, click_last_df
1.3.4 文章-类型,文章-单词数,文章-创建时间字典
将文章相关信息整理为①文章-类型,②文章-单词数,③文章-创建时间三个字典
def get_item_info_dict(item_info_df):
"""
获取文章id对应的基本属性,保存成字典的形式,方便后面召回阶段,冷启动阶段直接使用
:param item_info_df: 文章信息df
:return: 文章-类型,文章-单词数,文章-创建时间字典
"""
item_info_df['created_at_ts'] = item_info_df[['created_at_ts']].apply(max_min_scaler)
item_type_dict = dict(zip(item_info_df['click_article_id'], item_info_df['category_id']))
item_words_dict = dict(zip(item_info_df['click_article_id'], item_info_df['words_count']))
item_created_time_dict = dict(zip(item_info_df['click_article_id'], item_info_df['created_at_ts']))
return item_type_dict, item_words_dict, item_created_time_dict
1.3.5 获取用户点击历史文章
用户-点击文章类型字典:{user_id: set(category_id)}
用户-点击文章ID字典:{user_id: set(click_article_id)}
用户-点击文章平均字数字典:{user_id: set(words_count)}
用户-最后一次点击文章的创建时间字典:{user_id: set(click_timestamp)}
def get_user_hist_item_info_dict(all_click):
"""
获取user_id对应的用户历史点击文章类型、单词数、创建时间的集合字典
:param all_click:
:return:
"""
# 获取user_id对应的用户历史点击文章类型的集合字典
user_hist_item_typs = all_click.groupby('user_id')['category_id'].agg(set).reset_index()
user_hist_item_typs_dict = dict(zip(user_hist_item_typs['user_id'], user_hist_item_typs['category_id']))
# 获取user_id对应的用户点击文章的集合
user_hist_item_ids_dict = all_click.groupby('user_id')['click_article_id'].agg(set).reset_index()
user_hist_item_ids_dict = dict(zip(user_hist_item_ids_dict['user_id'], user_hist_item_ids_dict['click_article_id']))
# 获取user_id对应的用户历史点击的文章的平均字数字典
user_hist_item_words = all_click.groupby('user_id')['words_count'].agg('mean').reset_index()
user_hist_item_words_dict = dict(zip(user_hist_item_words['user_id'], user_hist_item_words['words_count']))
# 获取user_id对应的用户最后一次点击的文章的创建时间
all_click_ = all_click.sort_values('click_timestamp')
user_last_item_created_time = all_click_.groupby('user_id')['created_at_ts'].apply(lambda x: x.iloc[-1]).reset_index()
user_last_item_created_time['created_at_ts'] = user_last_item_created_time[['created_at_ts']].apply(max_min_scaler)
user_last_item_created_time_dict = dict(zip(user_last_item_created_time['user_id'], user_last_item_created_time['created_at_ts']))
return user_hist_item_typs_dict, user_hist_item_ids_dict, user_hist_item_words_dict, user_last_item_created_time_dict