基于用户的协同过滤推荐系统

一、什么是基于用户的协同过滤推荐系统

基于用户的协同过滤算法是一种在推荐系统中广泛应用的算法,它主要依据用户之间的相似性来为目标用户提供推荐,以下是其详细介绍:

基本原理

  • 该算法认为,具有相似兴趣爱好的用户可能会对相同或相似的物品有偏好。通过分析用户对不同物品的行为数据(如评分、点击、购买等),找到与目标用户兴趣相似的其他用户,然后将这些相似用户喜欢的物品推荐给目标用户

二、创建数据库、数据表

1、安装msql

参考 : MySQL安装(保姆级教程)_mysql安装教程-优快云博客^v102^pc_search_result_base9&utm_term=%E5%AE%89%E8%A3%85mysql&spm=1018.2226.3001.4187

2、安装navicat

Navicat——安装使用(图文详解)-优快云博客^v102^pc_search_result_base9&spm=1018.2226.3001.4187

3、创建数据库、数据表

(1)创建用户行为数据表
CREATE TABLE user_behavior (
    id INT NOT NULL AUTO_INCREMENT COMMENT 'ID',
    user_id VARCHAR(255) NOT NULL COMMENT '用户ID',
    image_id VARCHAR(255) NOT NULL COMMENT '图片ID',
    action VARCHAR(255) NOT NULL COMMENT '用户行为: 点击图片、点赞图片、制作同款、保存图片',
    count INT NOT NULL DEFAULT 1 COMMENT '次数,默认为1',
    image_type INT NOT NULL COMMENT '系统=1,用户=2',
    create_time DATETIME NOT NULL COMMENT '创建时间',
    PRIMARY KEY (id)
);

(2)创建推荐结果表

CREATE TABLE recommendation_results (
    id INT NOT NULL AUTO_INCREMENT COMMENT 'ID',
    user_id VARCHAR(255) NOT NULL COMMENT '用户ID',
    image_id VARCHAR(255) NOT NULL COMMENT '图片ID',
    image_type INT NOT NULL COMMENT '图片类型',
    create_time DATETIME NOT NULL COMMENT '创建时间',
    PRIMARY KEY (id)
);

4、生成模拟数据

import mysql.connector
import random
import string
from datetime import datetime


# 记录开始时间
start_time = datetime.now()
# 数据库连接配置
# 数据库配置信息字典,需替换为实际的数据库连接信息
db_config = {
    # 数据库用户名
    'user':'user',
    # 数据库用户密码
    'password': '123456',
    # 数据库主机地址及端口号
    'host': '127.0.0.1',
    'port': 3306,
    # 要连接的数据库名称
    'database': 'image_recommendation',
    # 当出现警告时是否抛出异常
    'raise_on_warnings': True
}

# 连接到数据库
conn = mysql.connector.connect(**db_config)
cursor = conn.cursor()

# 模拟数据插入
num_records = 10000  # 要插入的记录数量
actions = ["点击图片", "点赞图片", "制作同款", "保存图片"]
image_types = [1, 2]

for _ in range(num_records):
    # 生成 0 到 50 之间的随机整数
    random_num = random.randint(0, 100)
    # 拼接字符串
    user_id = f"user_{random_num}"
    # 生成 0 到 50 之间的随机整数
    random_num1 = random.randint(0, 1000)
    # 拼接字符串
    image_id = f"image_{random_num1}"
    action = random.choice(actions)
    count = 1
    image_type = 2
    create_time = datetime.now()

    query = """
    INSERT INTO user_behavior (user_id, image_id, action, count, image_type, create_time)
    VALUES (%s, %s, %s, %s, %s, %s)
    """
    values = (user_id, image_id, action, count, image_type, create_time)

    cursor.execute(query, values)

# 提交事务并关闭连接
conn.commit()
cursor.close()
conn.close()

print(f"已成功插入 {num_records} 条模拟数据到 user_behavior 表中。")

# 记录结束时间
end_time = datetime.now()
# 计算时间差
elapsed_time = end_time - start_time
# 提取秒数
elapsed_seconds = int(elapsed_time.total_seconds())
print(f"用时: {elapsed_seconds} 秒")

三、代码

定时运行,每天进行一次协同过滤的推荐

import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity
from sqlalchemy import create_engine
import datetime
from apscheduler.schedulers.blocking import BlockingScheduler

# 记录开始时间
start_time = datetime.datetime.now()

# 推荐的topN
img_top_num = 20
user_top_num = 20

# 数据库配置信息字典,需替换为实际的数据库连接信息
db_config = {
    # 数据库用户名
    'user':'user',
    # 数据库用户密码
    'password': '123456',
    # 数据库主机地址及端口号
    'host': '127.0.0.1',
    'port': 3306,
    # 要连接的数据库名称
    'database': 'image_recommendation',
    # 当出现警告时是否抛出异常
    'raise_on_warnings': True
}

# 推荐的方法
def run_recommendation():
    try:
        # 创建数据库连接
        engine = create_engine(
            f"mysql+pymysql://{db_config['user']}:{db_config['password']}@{db_config['host']}/{db_config['database']}")

        # 读取 user_behavior 表
        query = "SELECT user_id, image_id, action, count, image_type FROM user_behavior"
        user_behavior_df = pd.read_sql(query, engine)
    except Exception as e:
        print(f"数据库连接或查询出错: {e}")
        raise

    # 为不同行为分配权重
    action_weights = {
        '点击图片': 1,
        '点赞图片': 3,
        '制作同款': 4,
        '保存图片': 2
    }

    # 根据行为权重和行为次数计算得分
    user_behavior_df['score'] = user_behavior_df.apply(
        lambda row: row['count'] * action_weights.get(row['action'], 0), axis=1)

    # 数据预处理:将用户行为转换为用户 - 物品交互矩阵
    user_item_matrix = user_behavior_df.pivot_table(index='user_id',
                                                    columns='image_id',
                                                    values='score', fill_value=0)

    # 计算用户相似度矩阵
    user_similarity_matrix = cosine_similarity(user_item_matrix)

    # 将相似度矩阵转换为 DataFrame
    user_similarity_df = pd.DataFrame(user_similarity_matrix, index=user_item_matrix.index,
                                      columns=user_item_matrix.index)

    # 生成推荐结果
    def generate_recommendations(user_id, user_similarity_df, user_item_matrix, top_n=20):
        """
        根据目标用户、用户相似度矩阵和用户-物品交互矩阵生成推荐结果。

        :param user_id: 目标用户的ID
        :param user_similarity_df: 用户相似度矩阵的DataFrame
        :param user_item_matrix: 用户-物品交互矩阵的DataFrame
        :param top_n: 要获取的相似用户数量,默认为20
        :return: 推荐的图片ID列表
        """
        try:
            # 获取目标用户的相似用户
            similar_users = user_similarity_df[user_id].sort_values(ascending=False)[1:top_n + 1]

            # 获取相似用户喜欢的物品
            similar_users_items = user_item_matrix.loc[similar_users.index]

            # 计算推荐分数
            recommendations = similar_users_items.mean(axis=0).sort_values(ascending=False)

            # 过滤掉用户已经交互过的物品
            user_interacted_items = user_item_matrix.loc[user_id]
            recommendations = recommendations[user_interacted_items == 0]

            return recommendations.index.tolist()
        except Exception as e:
            print(f"生成推荐结果时出错: {e}")
            return []

    # 为每个用户生成推荐结果
    recommendation_results = []
    for user_id in user_item_matrix.index:
        recommended_items = generate_recommendations(user_id, user_similarity_df, user_item_matrix)
        recommendation_results.append({
            'user_id': user_id,
            'image_id': recommended_items,
            'image_type': 2,  # 假设推荐的图片类型为系统图片
            'create_time': pd.Timestamp.now()
        })

    # 将推荐结果转换为 DataFrame
    recommendation_results_df = pd.DataFrame(recommendation_results)

    # 截取每个 user_id 对应的 image_id 列表的前 20 个
    recommendation_results_df['image_id'] = recommendation_results_df['image_id'].apply(lambda x: x[:top_num])

    # 将 image_id 列转换为字符串,因为数据库可能不支持直接存储列表
    recommendation_results_df['image_id'] = recommendation_results_df['image_id'].apply(lambda x: ','.join(x))

    try:
        # 将推荐结果存储到 recommendation_results 表
        recommendation_results_df.to_sql('recommendation_results', engine, if_exists='replace', index=False)
        print("推荐结果已成功存储到 recommendation_results 表中。")
    except Exception as e:
        print(f"存储推荐结果时出错: {e}")

    # 记录结束时间
    end_time = datetime.datetime.now()
    # 计算时间差
    elapsed_time = end_time - start_time
    # 提取秒数
    elapsed_seconds = int(elapsed_time.total_seconds())
    print(f"用时: {elapsed_seconds} 秒")

if __name__ == "__main__":
    scheduler = BlockingScheduler()
    # 设置每天运行一次,这里设置为每天凌晨0点运行,你可以根据需要调整时间
    scheduler.add_job(run_recommendation, 'cron', hour=0)
    try:
        scheduler.start()
    except (KeyboardInterrupt, SystemExit):
        pass

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值