推荐算法的Python实现——MF(矩阵分解)

Posted 白水baishui

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了推荐算法的Python实现——MF(矩阵分解)相关的知识,希望对你有一定的参考价值。

1. 数据集

本博客用Movielens-1m数据集的ratings.dat作为推荐数据来训练MF推荐模型。第一列是用户id(user_id)、第二列是物品id(item_id)、第三列是用户对物品的评分(score)、第四列是时间戳(timestamp)。

在Movielens-1m的元素数据集中,ratings.dat是用::作为分隔符的。在本次的python实现中,提前将分隔符::替换为了,,文件名ratings.dat改为了ratings.csv

如果嫌麻烦不想改ratings.dat文件的内容,改代码也可以,主要替换以下内容:

dataset = pd.read_csv("./ratings.csv", sep=",", names=["user_id", "item_id", "rating", "timestamp"])
# 替换为
dataset = pd.read_csv("./ratings.dat", sep="::", names=["user_id", "item_id", "rating", "timestamp"])

2. 代码

import numpy as np
import pandas as pd
import os
from tensorflow import keras # tensorflow == 2.X
import warnings
from tqdm import tqdm
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
warnings.filterwarnings('ignore')

# 进行推荐
def recommend(user_id, uel, mel, N):
    movies = uel[user_id-1] @ mel.T # -1是因为预处理后的用户id从0开始
    mids = np.argpartition(movies, -N)[-N:]
    return mids

if __name__ == "__main__":
    # ------ 读入数据 ------ #
    dataset = pd.read_csv("./ratings.csv", sep=",", names=["user_id", "item_id", "rating", "timestamp"])
    # 数据预处理,下标从0开始,去除缺失值使得值连续
    dataset.user_id = dataset.user_id.astype('category').cat.codes.values
    dataset.item_id = dataset.item_id.astype('category').cat.codes.values
    # 获取用户和项目列表
    user_arr = dataset.user_id.unique()
    movies_arr = dataset.item_id.unique()
    # 获取用户和项目数量
    n_users, n_movies = len(user_arr), len(movies_arr)  # 6040 3706
    n_latent_factors = 20

    # ------ 设置Keras参数 ------ #
    # 设置项目参数
    movie_input = keras.layers.Input(shape=[1], name='Item')
    movie_embedding = keras.layers.Embedding(n_movies + 1, n_latent_factors, name='Movie-Embedding')(movie_input)
    movie_vec = keras.layers.Flatten(name='FlattenMovies')(movie_embedding)
    # 设置用户参数
    user_input = keras.layers.Input(shape=[1], name='User')
    user_embedding = keras.layers.Embedding(n_users + 1, n_latent_factors, name='User-Embedding')(user_input)
    user_vec = keras.layers.Flatten(name='FlattenUsers')(user_embedding)
    # 计算项目向量与用户张量的点乘
    prod = keras.layers.dot([movie_vec, user_vec], axes=1, name='DotProduct')
    # 创建用户-项目模型
    model = keras.Model([user_input, movie_input], prod)
    # 设置模型优化器、损失函数、测量指标
    model.compile(optimizer='adam', loss='mean_squared_error', metrics=['mae', 'mse'])

    # ------ 训练模型 ------ #
    # 训练用户-项目模型
    # verbose=0:不输出日志;verbose=1:输出每一个step的训练进度及日志;verbose=2:输出每个epochs的日志
    model.fit([dataset.user_id, dataset.item_id], dataset.rating, epochs=5, verbose=1)
    # 获得用户和项目的嵌入矩阵
    user_embedding_learnt = model.get_layer(name='User-Embedding').get_weights()[0]
    movie_embedding_learnt = model.get_layer(name='Movie-Embedding').get_weights()[0]

    # ------ 进行推荐 ------ #
    # 给用户1推荐top10
    user = 1
    topN = recommend(user_id=user, uel=user_embedding_learnt, mel=movie_embedding_learnt, N=10)
    temp_topN = topN.tolist()

    print("------ user ------")
    print(user)
    print("------ temp_topN ------")
    print(temp_topN)

    # 给所有用户推荐Top10
    # for each_user in tqdm(user_arr, total=len(user_arr)):
    #     topN = recommend(user_id=each_user, uel=user_embedding_learnt, mel=movie_embedding_learnt, N=10)
    #     temp_topN = topN.tolist()
    #     print("------ each_user ------")
    #     print(each_user)
    #     print("------ temp_topN ------")
    #     print(temp_topN)

对用户1(user_id=1)产生一次推荐的输出结果:

Epoch 1/5
31257/31257 [==============================] - 29s 921us/step - loss: 2.5751 - mae: 1.1559 - mse: 2.5751
Epoch 2/5
31257/31257 [==============================] - 29s 941us/step - loss: 0.8758 - mae: 0.7376 - mse: 0.8758
Epoch 3/5
31257/31257 [==============================] - 28s 910us/step - loss: 0.8173 - mae: 0.7106 - mse: 0.8173
Epoch 4/5
31257/31257 [==============================] - 28s 888us/step - loss: 0.7707 - mae: 0.6886 - mse: 0.7707
Epoch 5/5
31257/31257 [==============================] - 26s 843us/step - loss: 0.7284 - mae: 0.6680 - mse: 0.7284
------ user ------
1
------ temp_topN ------
[579, 1618, 2131, 576, 309, 892, 513, 1563, 106, 346]

以上是关于推荐算法的Python实现——MF(矩阵分解)的主要内容,如果未能解决你的问题,请参考以下文章

推荐算法的Python实现——MF(矩阵分解) 基于TensorFlow

推荐算法的Python实现——MF(矩阵分解) 基于TensorFlow

推荐算法的Python实现——MF(矩阵分解) 基于TensorFlow

推荐系统矩阵分解MF利用BASIC-SVD分解

推荐系统中的矩阵分解演变方式

原理篇 | 推荐系统之矩阵分解模型