numpy 矩阵 秩_大规模电商推荐数据分析-基于矩阵分解的召回

6eca8007e105a894f38f9dfd7ff4f1a8.png

前面两篇文章回顾了我们团队做天池数据比赛《CIKM 2019 EComm AI:用户行为预测》的复赛方案,现在让我们的目光回到初赛。初赛数据组织和复赛一样,只是数据量差异较大。(初赛才2G数据,复赛28G啊。。。)

25235dc36ee67780c8e3115d1c2360d3.png

所以,初赛尝试的方案更多,这次就先说明基于矩阵分解的方案。

矩阵分解为什么能做推荐系统呢,昨天机器学习爱好者群里还有同学问过这个问题,这里借用中南大学卢博士的回答:

矩阵分解问题是通过少数的矩阵观测值,恢复矩阵中的其他未知元素。而这个问题是无法直接求解的,因此提出了低秩假设,即对原问题做了松弛近似-----人对电影的评分是由少数的用户特征和少数的电影特征决定的。原问题转换为低秩近似问题,而低秩近似问题是采用交替最小二乘(ALS)来求解的。

所以,采用ALS的方法,对初赛的用户-物品交互数据集做了相关分析,并得到推荐列表。关于ALS算法,网上有太多的资料可以学习,这里就不做赘述了,我们采用的是python中implicit库实现的ALS算法,可以跑在GPU上。(注意:只是训练可以,预测就不行,很难受

from implicit.als import AlternatingLeastSquares
from implicit.approximate_als import FaissAlternatingLeastSquares
import pandas as pd
from tqdm import tqdm, trange
from scipy.sparse import coo_matrix, csr_matrix
import numpy as np
import deepdish as dd
import pickle
import os
from dask import dataframe
import pandas as pd
import gc
os.environ["MKL_NUM_THREADS"] = "1"

raw_data = pd.read_csv("/data/ECommAI/round2_a/3Tuple/raw_data.csv", names=["user_index", "item_index", "ratings"])
user_id = raw_data["user_index"].values
item_id = raw_data["item_index"].values
ratings = raw_data["ratings"].values

首先是加载数据并读取文件,交互数据的格式是这样的:

4fc0f85a3ebdf730929ed0bb1a9ed3cd.png
《CIKM 2019 EComm AI:用户行为预测》用户历史行为

实际上会发现,这个数据格式和movielens的数据没什么区别,只是行为描述不再是评分,所以我们将行为字符串转换成评分,这里直接做的一一映射,如:

behavior_map = {"clk": 1.0 ,"collect":2.0 ,"cart" : 3.0 ,"buy" : 4.0}

这个操作实际上就是对一个列进行map操作,词典转换而已。(实际上对用户id和物品id也要做map_id的操作,毕竟要把数据放到矩阵里)

接着,我们将数据放入稀疏压缩矩阵csr_matrix中,然后调用ALS的模型训练函数fit,存储模型生成结果user和item的隐向量。

item_user_data = csr_matrix((ratings, (item_id, user_id)), shape=(max(item_id) + 1, max(user_id) + 1))
print("Done")
# initialize a model
model = AlternatingLeastSquares(factors=64, use_gpu=True, iterations=100, calculate_training_loss=True)
# train model
model.fit(item_user_data)
dd.io.save("/data/ECommAI/round1_b/user_factors.h5", model.user_factors, compression=False)
dd.io.save("/data/ECommAI/round1_b/item_factors.h5", model.item_factors, compression=False)

由于预测部分实在是太慢了,我们就把隐向量拿出来自己组织逻辑,完成推荐结果输出。

import deepdish as dd
import tensorflow as tf
import numpy as np
from tqdm import trange

tf.enable_eager_execution()
user_factors = dd.io.load("/data/ECommAI/round1_b/user_factors.h5")
item_factors = dd.io.load("/data/ECommAI/round1_b/item_factors.h5")

首先加载模型训练好的用户隐向量和物品隐向量。

# recommend_result = None

def make_recommendation(index, scale):
    item_tensor = tf.convert_to_tensor(item_factors)
    user_tensor = tf.convert_to_tensor(user_factors[index:index + scale, :])
    idx0 = tf.shape(user_tensor)[0]
    if idx0 != 0:
        recommendation = tf.tensordot(user_tensor, item_tensor, axes=[1, 1])
        recommendation_k = tf.math.top_k(recommendation, k=50)
        return recommendation_k[1]
    else:
        return None

由于矩阵分解的预测阶段实际就是向量内积操作,通过tensorflow框架是可以并行化处理的,所以我们次啊用基于tensor的向量内积批量计算结果,并存储在list内。

scale = 200
recommend_result = make_recommendation(0, scale).numpy()

user_count = user_factors.shape[0]
for i in trange(1, user_count // scale + 1):
    recommend_result = np.concatenate((recommend_result, make_recommendation(i * scale, scale).numpy()), axis=0)

dd.io.save("/data/ECommAI/round1_b/ALS_recommendations.h5", recommend_result, compression=None)

最终,我们对每200个用户进行批量内积计算结果,即用户

结果进行排序,得到最终的推荐结果。

这个方案的线上评分在0.016左右,baseline的基于物品热度召回都有0.04,还是存在不少差距的。

这里有篇关于implicit库的文章可以参考:

使用python实战开发基于隐式反馈(点击,点赞,浏览,收藏,评论)的协同过滤的推荐系统(implicit库)​blog.csdn.net
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值