基于协同过滤推荐的在线课程选修系统

2024-06-09 02:04

本文主要是介绍基于协同过滤推荐的在线课程选修系统,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基于协同过滤推荐的在线课程选修系统

demo

网站查看 http://course.qsxbc.com/all_course/
点我查看
效果
在这里插入图片描述

功能

登录注册、点赞收藏、评分评论,课程推荐,热门课程,个人中心,可视化,后台管理,课程选修

推荐算法

# -*-coding:utf-8-*-
"""
@contact: 微信 1257309054
@file: recommend_user.py
@time: 2024/6/8 16:21
@author: LDC
使用Keras框架实现一个深度学习推荐算法
"""import collections
import math
import os
import django
import operator
import numpy as np
from course.models import *
from k_means_utils import predictos.environ["DJANGO_SETTINGS_MODULE"] = "course_manager.settings"
django.setup()def get_default_recommend(user_id):# 获取默认推荐# 获取用户注册时选择的类别category_ids = []us = UserSelectTypes.objects.get(user_id=user_id)for category in us.category.all():category_ids.append(category.id)course_list = CourseInfo.objects.filter(tags__in=category_ids).distinct().order_by("-collect_num")[:30]return course_listclass UserCf:# 基于用户协同算法来获取推荐列表"""利用用户的群体行为来计算用户的相关性。计算用户相关性的时候我们就是通过对比他们选修过多少相同的课程相关度来计算的举例:--------+--------+--------+--------+--------+|   X    |    Y   |    Z   |    R   |--------+--------+--------+--------+--------+a   |   1    |    1   |    1   |    0   |--------+--------+--------+--------+--------+b   |   1    |    0   |    1   |    0   |--------+--------+--------+--------+--------+c   |   1    |    1   |    0   |    1   |--------+--------+--------+--------+--------+a用户选修了:X、Y、Zb用户选修了:X、Zc用户选修了:X、Y、R那么很容易看到a用户和b、c用户非常相似,给a用户推荐课程R,给b用户推荐课程Y给c用户推荐课程Z这就是基于用户的协同过滤。a用户向量为(1,1,1,0)b用户向量为(1,0,1,0)c用户向量为(1,1,0,1)找a用户的相似用户,则计算a向量与其他向量的夹角即可,夹角越小则说明越相近利用求高维空间向量的夹角,可以估计两组数据的吻合程度"""# 获得初始化数据def __init__(self, data):self.data = data# 计算N维向量的夹角def calc_vector_cos(self, a, b):'''cos=(ab的内积)/(|a||b|):param a: 向量a:param b: 向量b:return: 夹角值'''a_n = np.array(a)b_n = np.array(b)if any(b_n) == 0:return 0cos_ab = a_n.dot(b_n) / (np.linalg.norm(a_n) * np.linalg.norm(b_n))print('值为', cos_ab)return round(cos_ab, 2)# 计算与当前用户的距离,获得最临近的用户def nearest_user(self, username, n=2):distances = {}# 用户,相似度# 遍历整个数据集for user, rate_set in self.data.items():# 非当前的用户if user != username:print('获取{}与{}的向量夹角'.format(username, user))vector_a = tuple(self.data[username].values())vector_b = tuple(self.data[user].values())distance = self.calc_vector_cos(vector_a, vector_b)# 计算两个用户的相似度distances[user] = distance# 排序,按向量夹角由小到到排序closest_distance = sorted(distances.items(), key=operator.itemgetter(1), reverse=True)# 最相似的N个用户closest_users = []for cd in closest_distance:if cd[1] == 1:closest_users.append(cd)else:if len(closest_users) >= n:breakclosest_users.append(cd)print("closest user:", closest_users)return closest_users# 给用户推荐课程def recommend(self, username, n=1):recommend = set()nearest_user = self.nearest_user(username, n)  # 获取最相近的n个用户for user_id, _ in nearest_user:for usercourse in UserCourse.objects.filter(user_id=user_id):if usercourse.course.id not in self.data[username].keys():recommend.add(usercourse.course.id)return recommend# 用户推荐
def recommend_by_user_id(user_id, is_mix=False):# 通过用户协同算法来进行推荐current_user = User.objects.get(id=user_id)# 如果当前用户没有选修过课程,则按照收藏量降序返回if current_user.usercourse_set.count() == 0:if is_mix:return []return get_default_recommend(user_id)data = {}course_ids = []other_user_ids = set()# 把该用户选修过的课程变成向量字典:{'用户id': {'课程1id': 1, '课程2id': 1...}}for u_course in current_user.usercourse_set.all():# 遍历用户选修过的课程if not data:data[current_user.id] = {u_course.course.id: 1}  # 已选课程,设置值为1else:data[current_user.id][u_course.course.id] = 1course_ids.append(u_course.course)# 获取其他选修过该课程的用户idfor usercourse in UserCourse.objects.filter(course=u_course.course):if usercourse.user.id != current_user.id:other_user_ids.add(usercourse.user.id)# 把选修过其中课程的用户选修过的课程变成向量字典:{'用户2id': {'课程1id': 0, '课程2id': 1...}}for other_user in User.objects.filter(pk__in=other_user_ids):other_user_id = other_user.idfor i in range(len(course_ids)):course = course_ids[i]if UserCourse.objects.filter(user_id=other_user_id, course=course):is_select = 1else:is_select = 0if other_user_id not in data:data[other_user_id] = {course.id: is_select}  # 已选课程,设置值为1,未选课程设置为0else:data[other_user_id][course.id] = is_selectuser_cf = UserCf(data=data)recommend_ids = user_cf.recommend(current_user.id, 1)if not recommend_ids:# 如果没有找到相似用户则按照收藏量降序返回if is_mix:return []return get_default_recommend(user_id)if is_mix:return list(recommend_ids)return CourseInfo.objects.filter(is_show=True, id__in=recommend_ids).order_by('-select_num')# 物品推荐
class ItemCf:# 基于物品协同算法来获取推荐列表'''1.构建⽤户–>物品的对应表2.构建物品与物品的关系矩阵(同现矩阵)3.通过求余弦向量夹角计算物品之间的相似度,即计算相似矩阵4.根据⽤户的历史记录,给⽤户推荐物品'''def __init__(self, user_id):self.user_id = user_id  # 用户iddef get_data(self):# 获取用户评分过的课程rate_courses = RateCourse.objects.filter()if not rate_courses:return Falsedatas = {}for rate_course in rate_courses:user_id = rate_course.user_idif user_id not in datas:datas.setdefault(user_id, {})datas[user_id][rate_course.course.id] = rate_course.markelse:datas[user_id][rate_course.course.id] = rate_course.markreturn datasdef similarity(self, data):# 1 构造物品:物品的共现矩阵N = {}  # 喜欢物品i的总⼈数C = {}  # 喜欢物品i也喜欢物品j的⼈数for user, item in data.items():for i, score in item.items():N.setdefault(i, 0)N[i] += 1C.setdefault(i, {})for j, scores in item.items():if j != i:C[i].setdefault(j, 0)C[i][j] += 1print("---1.构造的共现矩阵---")print('N:', N)print('C', C)# 2 计算物品与物品的相似矩阵W = {}for i, item in C.items():W.setdefault(i, {})for j, item2 in item.items():W[i].setdefault(j, 0)W[i][j] = C[i][j] / math.sqrt(N[i] * N[j])print("---2.构造的相似矩阵---")print(W)return Wdef recommand_list(self, data, W, user, k=3, N=10):'''# 3.根据⽤户的历史记录,给⽤户推荐物品:param data: 用户数据:param W: 相似矩阵:param user: 推荐的用户:param k: 相似的k个物品:param N: 推荐物品数量:return:'''rank = {}for i, score in data[user].items():  # 获得⽤户user历史记录,如A⽤户的历史记录为{'唐伯虎点秋香': 5, '逃学威龙1': 1, '追龙': 2}for j, w in sorted(W[i].items(), key=operator.itemgetter(1), reverse=True)[0:k]:  # 获得与物品i相似的k个物品if j not in data[user].keys():  # 该相似的物品不在⽤户user的记录⾥rank.setdefault(j, 0)rank[j] += float(score) * w  # 预测兴趣度=评分*相似度print("---3.推荐----")print(sorted(rank.items(), key=operator.itemgetter(1), reverse=True)[0:N])return sorted(rank.items(), key=operator.itemgetter(1), reverse=True)[0:N]def recommendation(self, k=3, N=10):"""给用户推荐相似课程:param user: 推荐的用户:param k: 相似的k个物品:param N: 推荐物品数量"""data = self.get_data()if not data or self.user_id not in data:# 用户没有评分过任何课程,就返回空列表return []W = self.similarity(data)  # 计算物品相似矩阵sort_rank = self.recommand_list(data, W, self.user_id, k, N)  # 推荐return sort_rankdef recommend_by_item_id(user_id, is_mix=False):# 物品推荐cf_list = ItemCf(user_id).recommendation()  # 物品协同过滤得到的推荐列表course_ids = [s[0] for s in cf_list]if is_mix:return course_idscourse_list = CourseInfo.objects.filter(id__in=course_ids).distinct().order_by("-select_num")if not course_list:# 推荐列表为空if is_mix:return []return get_default_recommend(user_id)return course_list# k-means推荐
def recommend_by_k_mean(user_id, course_id=None, is_mix=False):# 使用机器学习K-means聚类算法推荐用户喜欢的课程try:data = []  # 用户课程类型挑选列表tag_dict = collections.OrderedDict()  # 课程类型字典(有序字典)# 获取所有类型,并设置值为0for tag in Tags.objects.filter():tag_dict[tag.name] = 0# 获取用户喜欢的课程类型us = UserSelectTypes.objects.get(user_id=user_id)for category in us.category.filter():# 在类型字典中设置用户喜欢的类型为1tag_dict[category.name] = 1data.append(list(tag_dict.values()))tag_like_list = predict(data)  # 预测数据if not tag_like_list:# 预测推荐集合为空,则返回用户注册时选择的类别if is_mix:return []return get_default_recommend(user_id)index = 0recommend_tag = []for tag, value in tag_dict.items():if tag_like_list[index] == 1:# 用户喜欢的课程类型recommend_tag.append(tag)index += 1print('推荐的类型', recommend_tag)rank_set = set()  # 推荐课程id集合# 获取各推荐课程类型中排行前三的课程推荐给用户,其中排行按照收藏量来计算for tag in recommend_tag:courses = CourseInfo.objects.filter(tags__name=tag).order_by("-collect_num")[:5]for course in courses:rank_set.add(course.id)print('推荐的列表id', rank_set)if is_mix:return list(rank_set)if rank_set:course_list = CourseInfo.objects.filter(id__in=rank_set).exclude(id=course_id).distinct().order_by("-collect_num")return course_listexcept Exception as e:print('k-means出错', e)# 预测推荐集合为空,则返回用户注册时选择的类别if is_mix:return []return get_default_recommend(user_id)# 混合推荐
def recommend_by_mix(user_id):recommend_user_ids = recommend_by_user_id(user_id, is_mix=True)  # 基于用户推荐print('recommend_user_ids', recommend_user_ids)recommend_item_ids = recommend_by_item_id(user_id, is_mix=True)  # 基于物品推荐print('recommend_item_ids', recommend_item_ids)recommend_kmean_ids = recommend_by_k_mean(user_id, is_mix=True)  # 基于k-means推荐print('recommend_kmean_ids', recommend_kmean_ids)recommend_ids = list(set(recommend_user_ids + recommend_item_ids + recommend_kmean_ids)) # 总的推荐列表print('总的推荐列表', recommend_ids)course_list = CourseInfo.objects.filter(is_show=True, id__in=recommend_ids).order_by('-select_num')if not course_list:# 推荐列表为空return get_default_recommend(user_id)return course_list

这篇关于基于协同过滤推荐的在线课程选修系统的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1043942

相关文章

kkFileView在线预览office的常见问题以及解决方案

《kkFileView在线预览office的常见问题以及解决方案》kkFileView在线预览Office常见问题包括base64编码配置、Office组件安装、乱码处理及水印添加,解决方案涉及版本适... 目录kkFileView在线预览office的常见问题1.base642.提示找不到OFFICE组件

Linux系统中查询JDK安装目录的几种常用方法

《Linux系统中查询JDK安装目录的几种常用方法》:本文主要介绍Linux系统中查询JDK安装目录的几种常用方法,方法分别是通过update-alternatives、Java命令、环境变量及目... 目录方法 1:通过update-alternatives查询(推荐)方法 2:检查所有已安装的 JDK方

Linux系统之lvcreate命令使用解读

《Linux系统之lvcreate命令使用解读》lvcreate是LVM中创建逻辑卷的核心命令,支持线性、条带化、RAID、镜像、快照、瘦池和缓存池等多种类型,实现灵活存储资源管理,需注意空间分配、R... 目录lvcreate命令详解一、命令概述二、语法格式三、核心功能四、选项详解五、使用示例1. 创建逻

Linux下在线安装启动VNC教程

《Linux下在线安装启动VNC教程》本文指导在CentOS7上在线安装VNC,包含安装、配置密码、启动/停止、清理重启步骤及注意事项,强调需安装VNC桌面以避免黑屏,并解决端口冲突和目录权限问题... 目录描述安装VNC安装 VNC 桌面可能遇到的问题总结描js述linux中的VNC就类似于Window

使用Python构建一个高效的日志处理系统

《使用Python构建一个高效的日志处理系统》这篇文章主要为大家详细讲解了如何使用Python开发一个专业的日志分析工具,能够自动化处理、分析和可视化各类日志文件,大幅提升运维效率,需要的可以了解下... 目录环境准备工具功能概述完整代码实现代码深度解析1. 类设计与初始化2. 日志解析核心逻辑3. 文件处

golang程序打包成脚本部署到Linux系统方式

《golang程序打包成脚本部署到Linux系统方式》Golang程序通过本地编译(设置GOOS为linux生成无后缀二进制文件),上传至Linux服务器后赋权执行,使用nohup命令实现后台运行,完... 目录本地编译golang程序上传Golang二进制文件到linux服务器总结本地编译Golang程序

Spring Boot spring-boot-maven-plugin 参数配置详解(最新推荐)

《SpringBootspring-boot-maven-plugin参数配置详解(最新推荐)》文章介绍了SpringBootMaven插件的5个核心目标(repackage、run、start... 目录一 spring-boot-maven-plugin 插件的5个Goals二 应用场景1 重新打包应用

Linux在线解压jar包的实现方式

《Linux在线解压jar包的实现方式》:本文主要介绍Linux在线解压jar包的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux在线解压jar包解压 jar包的步骤总结Linux在线解压jar包在 Centos 中解压 jar 包可以使用 u

Linux系统性能检测命令详解

《Linux系统性能检测命令详解》本文介绍了Linux系统常用的监控命令(如top、vmstat、iostat、htop等)及其参数功能,涵盖进程状态、内存使用、磁盘I/O、系统负载等多维度资源监控,... 目录toppsuptimevmstatIOStatiotopslabtophtopdstatnmon

Knife4j+Axios+Redis前后端分离架构下的 API 管理与会话方案(最新推荐)

《Knife4j+Axios+Redis前后端分离架构下的API管理与会话方案(最新推荐)》本文主要介绍了Swagger与Knife4j的配置要点、前后端对接方法以及分布式Session实现原理,... 目录一、Swagger 与 Knife4j 的深度理解及配置要点Knife4j 配置关键要点1.Spri