基于深度学习的图书管理推荐系统(python版)

news2024/11/26 6:20:20

基于深度学习的图书管理推荐系统

1、效果图

在这里插入图片描述

1/1 [==============================] - 0s 270ms/step
[13 11  4 19 16 18  8  6  9  0]
[0.1780757  0.17474999 0.17390694 0.17207369 0.17157653 0.16824844
 0.1668652  0.16665359 0.16656876 0.16519257]
keras_recommended_book_ids深度学习推荐列表 [9137, 10548, 1, 10546, 2, 1024, 10, 10550, 7, 512]

2、算法原理

​ 使用Keras框架实现一个简单的深度学习推荐算法。Keras是建立在Python之上的高级神经网络API。Keras提供了一种简单、快速的方式来构建和训练深度学习模型。

​ 根据用户对书籍的评分表,使用Emmbeding深度学习训练得到一个模型,预测用户可能评分高的书籍,并把前5本推荐给用户。

Emmbeding是从离散对象(如书籍 ID)到连续值向量的映射。
这可用于查找离散对象之间的相似性。
Emmbeding向量是低维的,并在训练网络时得到更新。
设计一个模型,将用户id作为用户向量,物品id作为物品向量。
分别Emmbeding两个向量,再Concat连接起来,最后加上3个全连接层构成模型,进行训练。
使用adam优化器,用均方差mse来衡量预测评分与真实评分之间的误差

流程图:
在这里插入图片描述

3、算法流程

1、从数据库中读取评分表信息并转成二维数组
2、数据预处理,把用户id,物品id映射成顺序字典
3、统计用户数量、物品数量
4、划分训练集与测试集
5、构建Embedding模型并进行数据训练得到模型
6、调用模型预测评分高的物品并推荐给用户

4、主体代码

# -*- coding: utf-8 -*-

"""
@contact: 微信 1257309054
@file: recommend_keras.py
@time: 2024/3/30 16:21
@author: LDC
使用Keras框架实现一个深度学习推荐算法
"""

import os
import django
from django.conf import settings

os.environ["DJANGO_SETTINGS_MODULE"] = "book_manager.settings"
django.setup()

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import pymysql
from sklearn.model_selection import train_test_split
import warnings

warnings.filterwarnings('ignore')

from book.models import UserSelectTypes, LikeRecommendBook, Book, RateBook
from keras.layers import Input, Embedding, Flatten, Dot, Dense, Concatenate, Dropout
from keras.models import Model

from keras.models import load_model


def get_select_tag_book(user_id, book_id=None):
    # 获取用户注册时选择的书籍类别各返回10门书籍
    category_ids = []
    us = UserSelectTypes.objects.get(user_id=user_id)
    for category in us.category.all():
        category_ids.append(category.id)
    unlike_book_ids = [d['book_id'] for d in
                       LikeRecommendBook.objects.filter(user_id=user_id, is_like=0).values('book_id')]
    if book_id and book_id not in unlike_book_ids:
        unlike_book_ids.append(book_id)
    book_list = Book.objects.filter(tags__in=category_ids).exclude(id__in=unlike_book_ids).distinct().order_by(
        "-like_num")[:10]
    return book_list


def get_data():
    '''
    从数据库获取数据
    '''
    conn = pymysql.connect(host=settings.DATABASE_HOST,
                           user=settings.DATABASE_USER,
                           password=settings.DATABASE_PASS,
                           database=settings.DATABASE_NAME,
                           charset='utf8mb4',
                           use_unicode=True)

    sql_cmd = 'SELECT book_id, user_id,mark FROM rate_book'
    dataset = pd.read_sql(sql=sql_cmd, con=conn)
    conn.close()  # 使用完后记得关掉

    return dataset


def preprocessing(dataset):
    '''
    数据预处理
    '''
    book_val_counts = dataset.book_id.value_counts()
    book_map_dict = {}
    for i in range(len(book_val_counts)):
        book_map_dict[book_val_counts.index[i]] = i

    # print(map_dict)
    dataset["book_id"] = dataset["book_id"].map(book_map_dict)

    user_id_val_counts = dataset.user_id.value_counts()
    # 映射字典
    user_id_map_dict = {}
    for i in range(len(user_id_val_counts)):
        user_id_map_dict[user_id_val_counts.index[i]] = i
    # 将User_ID映射到一串字典
    dataset["user_id"] = dataset["user_id"].map(user_id_map_dict)

    return dataset, book_map_dict, user_id_map_dict


def train_model():
    '''
    训练模型
    '''
    dataset = get_data()  # 获取数据
    dataset, book_map_dict, user_id_map_dict = preprocessing(dataset)  # 数据预处理
    n_users = len(dataset.user_id.unique())  # 统计用户数量
    print('n_users', n_users)

    n_books = len(dataset.book_id.unique())  # 统计书籍数量
    print('n_books', n_books)

    # 划分训练集与测试集
    train, test = train_test_split(dataset, test_size=0.2, random_state=42)
    # 开始训练
    # creating book embedding path
    book_input = Input(shape=[1], name="Book-Input")
    book_embedding = Embedding(n_books + 1, 5, name="Book-Embedding")(book_input)
    Dropout(0.2)
    book_vec = Flatten(name="Flatten-Books")(book_embedding)

    # creating user embedding path
    user_input = Input(shape=[1], name="User-Input")
    user_embedding = Embedding(n_users + 1, 5, name="User-Embedding")(user_input)
    Dropout(0.2)
    user_vec = Flatten(name="Flatten-Users")(user_embedding)

    # concatenate features
    conc = Concatenate()([book_vec, user_vec])

    # add fully-connected-layers
    fc1 = Dense(128, activation='relu')(conc)
    Dropout(0.2)
    fc2 = Dense(32, activation='relu')(fc1)
    out = Dense(1)(fc2)

    # Create model and compile it
    model2 = Model([user_input, book_input], out)
    model2.compile('adam', 'mean_squared_error')

    history = model2.fit([train.user_id, train.book_id], train.mark, epochs=10, verbose=1)
    model2.save('regression_model2.h5')
    loss = history.history['loss']  # 训练集损失
    # 显示损失图像
    plt.plot(loss, 'r')
    plt.title('Training loss')
    plt.xlabel("Epochs")
    plt.ylabel("Loss")
    plt.show()
    print('训练完成')


def predict(user_id, dataset):
    '''
    将预测评分高的图书推荐给该用户user_id
    '''

    model2 = load_model('regression_model2.h5')

    '''
    先拿到所有的图书索引ISBN,并去重成为book_data。
    再添加一个和book_data长度相等的用户列表user,不过这里的user列表中的元素全是1,
    因为我们要做的是:预测第1个用户对所有图书的评分,再将预测评分高的图书推荐给该用户。
    '''
    book_data = np.array(list(set(dataset.book_id)))
    user = np.array([user_id for i in range(len(book_data))])
    predictions = model2.predict([user, book_data])
    # 更换列->行
    predictions = np.array([a[0] for a in predictions])
    # 根据原array,取其中数值从大到小的索引,再只取前top10
    recommended_book_ids = (-predictions).argsort()[:10]
    print(recommended_book_ids)
    print(predictions[recommended_book_ids])
    return recommended_book_ids


def embedding_main(user_id, book_id=None, is_rec_list=False):
    '''
    1、获取数据、数据预处理
    2、划分训练集与测试集
    3、训练模型、模型评估
    4、预测
    user_id: 用户id
    book_id: 用户已经评分过的书籍id,需要在推荐列表中去除
    is_rec_list: 值为True:返回推荐[用户-评分]列表,值为False:返回推荐的书籍列表
    '''
    dataset = get_data()  # 获取数据
    # print(dataset.head())
    if user_id not in dataset.user_id.unique():
        # 用户未进行评分则推荐注册时选择的图书类型
        print('用户未进行评分则推荐注册时选择的图书类型')
        if is_rec_list:
            return []
        # 推荐列表为空,按用户注册时选择的书籍类别各返回10门
        return get_select_tag_book(user_id, book_id)
    dataset, book_map_dict, user_id_map_dict = preprocessing(dataset)
    # user_id需要转换为映射后的user_id传到predict函数中
    predict_book_ids = predict(user_id_map_dict[user_id], dataset)  # 预测的书籍Id
    recommend_list = []  # 最后推荐的书籍id
    # 把映射的值转为真正的书籍id
    for book_id in predict_book_ids:
        for k, v in book_map_dict.items():
            if book_id == v:
                recommend_list.append(k)
    print('keras_recommended_book_ids深度学习推荐列表', recommend_list)

    if not recommend_list:
        # 推荐列表为空,且is_rec_list: 值为True:返回推荐[用户-评分]列表
        if is_rec_list:
            return []
        # 推荐列表为空,按用户注册时选择的书籍类别
        return get_select_tag_book(user_id, book_id)
    if is_rec_list:
        # 推荐列表不为空,且且is_rec_list: 值为True:返回推荐[用户-评分]列表
        return recommend_list

    # 过滤掉用户反馈过不喜欢的书籍
    unlike_book_ids = [d['book_id'] for d in
                       LikeRecommendBook.objects.filter(user_id=user_id, is_like=0).values('book_id')]

    # 过滤掉用户已评分的数据
    already_mark_ids = [d['book_id'] for d in RateBook.objects.filter(user_id=user_id).values('book_id')]
    unrecommend = list(set(unlike_book_ids + already_mark_ids))
    if book_id and book_id not in unrecommend:
        unrecommend.append(book_id)
    book_list = Book.objects.filter(id__in=recommend_list).exclude(id__in=unrecommend).distinct().order_by("-like_num")
    return book_list


if __name__ == '__main__':
    train_model() # 训练模型
    embedding_main(2) # 调用模型

输出:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1558900.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis 事务 与 管道

redis事务 谈到事务大家可能就会想起mysql中的事务 注意这里的事务不是指的是事务的四大特性acid 持久性 原子性 隔离性 一致性 事务的概念就是 一组命令,串行化执行而不被打断 这里redis的事务和mysql的事务就不太一样 传统关系型数据库的事务主要强调的是一个没有执行完成就…

python3——基础概要

基础 数据结构 Python 3.x中有6种标准的对象类型: Number(数字)、String(字符串)、List(列表)、Tuple(元组)、Sets(集合)、Dictionary&#xff08…

B+Tree讲解

B-/B树看 MySQL索引结构 B-树 B-树,这里的 B 表示 balance( 平衡的意思),B-树是一种多路自平衡的搜索树.它类似普通的平衡二叉树,不同的一点是B-树允许每个节点有更多的子节点。下图是 B-树的简化图. B-树有如下特点: 所有键值分布在整颗树中; 任何一个…

【MySQL】内外连接——内连接、外连接、左外连接、右外连接、内外连接的区别、左外连接和右外连接的区别

文章目录 MySQLMySQL表的内连接和外连接1. 内连接2. 外连接2.1 左外连接2.2 右外连接 3. 内外连接的区别4. 左外连接和右外连接的区别 MySQL MySQL表的内连接和外连接 MySQL 中的内连接(INNER JOIN)和外连接(包括左外连接 LEFT JOIN 和右外连…

数据分析之Tebleau 简介、安装及数据导入

Tebleau简介 Tebleau基于斯坦福大学突破性交互式技术 可以将结构化数据快速生成图表、坐标图、仪表盘与报告 将维度拖放到画布等地方是他的主要操作方式 例:Tebleau是手机相机 (相对来说更简单) POWER BI是单反相机 Tebleau各类产品 Teblea…

GPT提示词分享 —— 智能域名生成器

提示词👇 我希望你能充当一个聪明的域名生成器。我将告诉你我的公司或想法是什么,你将根据我的提示回复我一份域名备选清单。你只需回复域名列表,而不是其他。域名应该是最多 7-8 个字母,应该简短但独特,可以是朗朗上口…

ubuntu16.04 不支持 gcc-11,g++11

总结 ubuntu16.04 不支持 gcc-11,需要升级 18.04 或更高的版本。 背景 最近需要在我的 ubuntu16.04 电脑上安装 gcc-11,g-11,使用更高的版本来编译代码。根据网上查到的方式是添加以下的源并进行安装 sudo add-apt-repository ppa:ubuntu…

第十三届蓝桥杯JavaA组省赛真题 - 求和

解题思路&#xff1a; 这&#xff0c;真的是&#xff0c;省赛真题吗... public class Main {public static void main(String[] args) {long res 0;for (int i 1; i < 20230408; i) {res i;}System.out.print(res);} }

1.5编写一个程序,输入梯形的上底,下底和高,输出梯形的面积。

1、编写一个程序,输入梯形的上底,下底和高,输出梯形的面积。 package com.kangning.web.controller.system;import java.util.Scanner;/*** 编写一个程序,输入梯形的上底,下底和高,输出梯形的面积。*/ public class CountArea {public static void main(String[] args) …

Available platform plugins are: linuxfb, minimal, offscreen, vnc.

说明&#xff1a; buildroots根文件中已经移植好了QT的库&#xff0c;但是运行QT交叉编译之后的可执行文件报错&#xff1a; qt.qpa.plugin: Could not find the Qt platform plugin "eglfs" in "" This application failed to start because no Qt platf…

Linux 理解进程信号

目录 一、共享内存通信机制中的临界资源访问与同步控制 1、概念 2、生活角度理解信号机制 3、信号量的操作 二、信号 1、生活角度的信号 2、技术应用角度的信号 3、操作系统角度的信号 信号如何产生 理解组合键变为信号 理解信号如何被进程保存 时钟中断&#xff0…

【面试题】RocketMQ如何保证消息不丢失?

前言&#xff1a;在面试的时候如果你会用消息中间件&#xff0c;那么面试一般都会问到MQ是如何保证消息不丢失的这个问题&#xff0c;所以这个问题对于面试和日常工作都非常之重要&#xff0c;本文主要讲述RocketMQ是如何保证消息不丢失的&#xff0c;但是我们可以举一反三&…

C语言操作符详细讲解

前言 本次博客一定会让刚刚学习C语言小白有所收获 本次操作符讲解不仅分类还会有代码示例 好好看 好好学 花上几分钟就可以避免许多坑 1 操作符的基本使用 1.1操作符的分类 按功能分 算术操作符&#xff1a; 、- 、* 、/ 、% 移位操作符: >> << 位操作符…

内存池的实现与场景分析

内存管理库 jemalloc 内存管理&#xff0c;C 语言。tcmalloc 内存管理&#xff0c;C。在头文件中引入即可。 确定 block 的大小、不确定 block 的释放时间&#xff0c;如何设计内存池 ? #include <stdio.h> #include <stdlib.h>// gcc mem_pool_v1.c -o mem_poo…

Linux: 进程优先级

Linux: 进程优先级 一、进程优先级概念二、如何查看进程优先级三、如何修改进程的优先级&#xff08;PRL vs NI&#xff09;四、为何优先级PRL必须限定范围五、进程其他特性 一、进程优先级概念 优先级的本质就是排队&#xff0c;而排队则是资源不足所引起的。在计算机中&#…

Sublime 彻底解决中文乱码

1. 按ctrl&#xff0c;打开Console&#xff0c;输入如下代码&#xff1a; import urllib.request,os; pf Package Control.sublime-package; ipp sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHand…

LLM:函数调用(Function Calling)

1 函数调用 虽然大模型能解决很多问题&#xff0c;但大模型并不能知晓一切。比如&#xff0c;大模型不知道最新消息(GPT-3.5 的知识截至 2021年9月&#xff0c;GPT-4 是 2023 年12月)。另外&#xff0c;大模型没有“真逻辑”。它表现出的逻辑、推理&#xff0c;是训练文本的统计…

spring注解@EventListener实现监听原理

文章目录 EventListener使用方式EventListener实现原理1.引入时机2 初始化时机3 作用时机->将加了EventListener注解的方法识别出来&#xff0c;并封装为监听器&#xff0c;加载spring容器中 总结 EventListener使用方式 package com.cyl.listener;import org.springframew…

区间预测 | Matlab实现带有置信区间的GRNN广义回归神经网络时间序列未来趋势预测

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 Matlab实现带有置信区间的GRNN广义回归神经网络时间序列未来趋势预测 带有置信区间的GRNN(广义回归神经网络)时间序列未来趋势预测结合了广义回归神经网络(GRNN)的预测能力和置信区间的统计度量,以提供对未来…

Linux系统下NAT网卡出现问题,无法上网的解决办法

NTA连接无法上网&#xff0c;如果你试过网上所有教程&#xff0c;检测了Windows环境和Ubuntu环境没问题&#xff0c;且无法启动系统服务、ping网络失败、重置虚拟机网络配置器也无效等种种以下所列原因无法解决&#xff0c;可能在于没有获取IP地址&#xff0c;才不能上网 netw…