当前位置:   article > 正文

计算机毕业设计:基于python考研院校推荐系统+爬虫+推荐算法+可视化分析 +django框架+混合推荐算法_基于django的考研院校数据分析及院校推荐系统

基于django的考研院校数据分析及院校推荐系统

Python项目——毕业设计选题参考

本科生毕业设计选题大全——计算机类(Python/Java)

感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助更多的人 。

1、项目介绍

(1)技术栈:
Python语言 MySQL数据库 Django框架 协同过滤推荐算法 requests网络爬虫 pyecharts数据可视化 html页面
爬取院校信息:https://yz.chsi.com.cn/sch/(研招网)

考研院校推荐系统 爬虫+混合推荐+协同过滤推荐算法+Echarts可视化
基于Python考研院校推荐系统 爬虫+混合推荐+协同过滤推荐算法+Echarts可视化 考研推荐 专业推荐 计算机毕业设计

2、项目界面

(1)数据可视化分析
在这里插入图片描述
(2)系统首页—高校信息

在这里插入图片描述

(3)高校信息排行榜可视化分析
在这里插入图片描述
(4)院校推荐模块

在这里插入图片描述

(5)高校院校页面

在这里插入图片描述

(6)高校分数线页面

在这里插入图片描述

(7)查高校录取比页面

在这里插入图片描述

(8)查高校专业页面
在这里插入图片描述

(9)我的评分页面

在这里插入图片描述

(10)我的收藏页面

在这里插入图片描述

(11)后台数据管理页面

在这里插入图片描述

(12)数据采集爬虫页面
在这里插入图片描述

3、项目说明

基于Python的考研院校推荐系统是一款利用Python语言和相关技术,为考生提供个性化院校推荐服务的应用系统。以下是该系统的主要介绍:

数据收集:系统采集了全国各地公布的考研数据,包括历年各省份考研报名人数、报考人数、录取分数线等信息,以及各高校的专业、科研情况、学术声誉等数据。通过对这些数据进行整合处理,系统建立了一个完整的数据仓库。

数据挖掘:系统利用机器学习和数据挖掘技术,对用户输入的专业、成绩、地区等信息进行分析,确定用户的兴趣和需求,以此为基础,利用协同过滤算法、基于内容的推荐算法等多种算法方法,实现个性化的院校推荐。

推荐算法:系统根据用户的输入信息,利用机器学习算法对已有的数据进行模型训练和预测,计算出与用户最匹配的院校推荐结果。

用户界面和交互设计:系统提供友好的用户界面和交互设计,用户可以根据自己的需求输入专业、成绩、地区等信息,同时还可以根据自己的偏好进行院校筛选和优化。

可视化展示:系统采用图表和图形等方式,直观地呈现推荐结果,使用户能够更加清晰明了地理解推荐结果,并进一步提高决策效率。

综上所述,基于Python的考研院校推荐系统是一款利用Python技术进行开发的应用系统,旨在为考生提供个性化的院校推荐服务。通过数据挖掘和机器学习技术,系统可以根据用户的兴趣和需求,给出符合用户背景和选校要求的院校推荐,提高用户决策效率,帮助他们实现顺利升学。

4、部分源码

import random

from django.shortcuts import render
import math
from app01 import models
from app01.models import School, UserScore, User, UserCollection
from app01.utils.pagination import Pagination


def jaccard_similarity(a, b):
     计算杰卡德相似度
     将布尔向量转换为集合
    set_a = set(i for i, x in enumerate(a) if x)
     print("set_a:", set_a)
    set_b = set(i for i, x in enumerate(b) if x)
     print("set_b:", set_b)
     计算交集和并集的大小
    intersection = len(set_a.intersection(set_b))
     print("a和b交集:", set_a.intersection(set_b))
    union = len(set_a.union(set_b))
     print("a和b并集:", set_a.union(set_b))
     计算相似度
    similarity = intersection / union if union else 0
    return similarity

重载字典计算方法
class MyDict(dict):
    def __add__(self, other):
        res = MyDict(self)
        for key, val in other.items():
            if key in res:
                res[key] += val
            else:
                res[key] = val
        return res

    def __mul__(self, factor):
        res = MyDict()
        for key, val in self.items():
            res[key] = val * factor
        return res

    def __rmul__(self, factor):
        return self.__mul__(factor)


def cosine_similarity(v1, v2):
     计算余弦相似度
    numerator = sum([a * b for a, b in zip(v1, v2)])   两向量的内积作为分子
    denominator = math.sqrt(sum([a ** 2 for a in v1])) * math.sqrt(sum([b ** 2 for b in v2]))   两向量模长的乘积作为分母
    if denominator > 0:
        return numerator / denominator
    else:
        return 0


 基于用户收藏计算当前用户与其他用户的杰卡德相似度
def user_jaccard_similarity_collections(user_id, default_similarity_jaccard=0):
     获取当前用户的收藏数据
    user_collections = UserCollection.objects.filter(user_id=user_id).values('school_id', 'collection')
     获取当前用户收藏的学校id
    user_collections_school_id = [user_collection['school_id'] for user_collection in user_collections]
     print("当前用户收藏情况:")
     print(user_collections_school_id)
     print("基于用户收藏的邻居用户收藏情况:")
     构造当前用户收藏向量
    user_collection_vector = [0 for i in range(999)]
    for school_id in user_collections_school_id:
        user_collection_vector[school_id] = 1

    similarities_jaccard = {}   定义字典来存放与当前用户相似用户的id和相似度
    for user in User.objects.exclude(id=user_id):
         获取当前用户与其他用户共同收藏的物品的id
        collections = user.usercollections.filter(school_id__in=user_collections_school_id).values('school_id')
        if collections:   如果当前用户与该用户有共同收藏的学校,则计算当前用户与该用户的相似度,这里使用杰卡德
             获取该用户所有的收藏情况:(school_id)
            collections = user.usercollections.filter().values('school_id')
            collections_school_id = [(collection['school_id']) for collection in collections]
             print(collections_school_id)
             构造该用户收藏向量:collection_vector
            collection_vector = [0 for i in range(999)]
            for school_id in collections_school_id:
                collection_vector[school_id] = 1
                 collection_vector[0] = user.id
             print(collection_vector)
             计算两用户之间的杰卡德相似度
            similarity_jaccard = jaccard_similarity(user_collection_vector, collection_vector)
            if similarity_jaccard > default_similarity_jaccard:
                similarities_jaccard[user.id] = similarity_jaccard
    return similarities_jaccard


 基于用户收藏计算当前用户对邻居收藏院校的jaccard兴趣度
def user_recommendations_jaccard_collections(user_id, similarities, similarities_jaccard):
     获取当前用户的收藏数据
    user_collections = UserCollection.objects.filter(user_id=user_id).values('school_id', 'collection')
     获取当前用户收藏的学校id
    user_collections_school_id = [user_collection['school_id'] for user_collection in user_collections]
    recommendations_jaccard = {}
     print("邻居用户已收藏的学校中目标用户未收藏的学校:",
           UserCollection.objects.filter(user_id__in=similarities).exclude(
               school_id__in=user_collections_school_id).values_list('school_id', flat=True).distinct())
     邻居用户已收藏的学校中目标用户未收藏的学校
    for school_id in UserCollection.objects.filter(user_id__in=similarities).exclude(
            school_id__in=user_collections_school_id).values_list('school_id', flat=True).distinct():
         获取收藏了当前物品的用户:用户id和收藏情况(collection = 1)
        item_collections = UserCollection.objects.filter(school_id=school_id).values('user_id', 'collection')
         初始化一个空列表
        weighted_scores = []
         遍历 item_ratings 中的每一条记录
        for collection in item_collections:
             如果该收藏记录对应的用户在 similarities_jaccard 字典中,则计算该收藏记录对该物品的权重得分
            if collection['user_id'] in similarities_jaccard:
                 获取该收藏记录对应用户与目标用户的相似度
                similarity = similarities_jaccard[collection['user_id']]
                 计算该收藏记录对该物品的权重得分
                weighted_score = similarity * collection['collection']
                 将该权重得分添加到列表中
                weighted_scores.append(weighted_score)
        numerator = sum(weighted_scores)
        denominator = sum(similarities_jaccard.values())
        if denominator > 0:
            recommendations_jaccard[school_id] = round(numerator / denominator, 2)
     print("邻居用户已收藏的学校中目标用户未收藏的学校:", UserCollection.objects.filter(user_id__in=similarities).exclude(
         school_id__in=user_collections_school_id).values_list('school_id', flat=True).distinct())
     print("基于用户收藏的兴趣度得分情况:",recommendations_jaccard)
    return recommendations_jaccard


 基于用户评分计算当前用户和其他用户的余弦相似度
def user_cosine_similarity_ratings(user_id, default_similarity_cosine=0):
     获取当前用户评分数据
    user_ratings = UserScore.objects.filter(user_id=user_id).values('school_id', 'score')
    user_ratings_school_id = [user_rating['school_id'] for user_rating in user_ratings]
     获取当前用户评分学校的评分情况:(school_id,score)
    user_ratings_school = [(user_rating['school_id'], user_rating['score']) for user_rating in user_ratings]
     print("当前用户评分情况:")
     print(user_ratings_school)
     print("基于用户评分的邻居用户评分情况:")
     构造当前用户评分向量:user_rating_vector
    user_rating_vector = [0 for i in range(999)]
    for school_id, score in user_ratings_school:
        user_rating_vector[school_id] = score
         根据评分情况计算所有用户的相似度:如果两用户之间没有共同评分的学校,则相似度为0
    similarities_cosine = {}
    for user in User.objects.exclude(id=user_id):
         获取当前用户与其他用户共同评价的物品的评分数据
        ratings = user.userscores.filter(school_id__in=user_ratings_school_id).values('school_id', 'score')
        if ratings:   如果当前用户与该用户有共同评分的学校,则计算当前用户与该用户的相似度,这里使用余弦相似度
             获取该用户所有的评分学校的评分情况:(school_id,score)
            ratings = user.userscores.filter().values('school_id', 'score')
            ratings_school = [(rating['school_id'], rating['score']) for rating in ratings]
             print(ratings_school)
             构造该用户评分向量:rating_vector
            rating_vector = [0 for i in range(999)]
            for school_id, score in ratings_school:
                rating_vector[school_id] = score
             print(rating_vector)
             计算两用户之间的余弦相似度
            similarity_cosine = cosine_similarity(user_rating_vector, rating_vector)
            if similarity_cosine > default_similarity_cosine:
                similarities_cosine[user.id] = similarity_cosine
    return similarities_cosine


 基于用户评分计算当前用户对邻居评分院校的cosine兴趣度
def user_recommendations_cosine_ratings(user_id, similarities, similarities_cosine):
     获取当前用户评分数据
    user_ratings = UserScore.objects.filter(user_id=user_id).values('school_id', 'score')
    user_ratings_school_id = [user_rating['school_id'] for user_rating in user_ratings]

     根据相似度值为用户推荐物品
    recommendations_cosine = {}   定义字典存放物品id和物品相似度

     邻居用户已评分的学校中目标用户未评分的学校
    for school_id in UserScore.objects.filter(user_id__in=similarities).exclude(
            school_id__in=user_ratings_school_id).values_list('school_id', flat=True).distinct():
         获取评价了当前物品的用户和评分数据
        item_ratings = UserScore.objects.filter(school_id=school_id).values('user_id', 'score')
         print("item_ratings:", item_ratings)
         初始化一个空列表
        weighted_scores = []
         遍历 item_ratings 中的每一条记录
        for rating in item_ratings:
             如果该评分记录对应的用户在 similarities 字典中,则计算该评分记录对该物品的权重得分
            if rating['user_id'] in similarities_cosine:
                 获取该评分记录对应用户与目标用户的相似度
                similarity = similarities_cosine[rating['user_id']]
                 计算该评分记录对该物品的权重得分
                weighted_score = similarity * rating['score']
                 将该权重得分添加到列表中
                weighted_scores.append(weighted_score)
        numerator = sum(weighted_scores)
        denominator = sum(similarities_cosine.values())
        if denominator > 0:
            recommendations_cosine[school_id] = round(numerator / denominator, 2)
     print("邻居用户已评分的学校中目标用户未评分的学校:", UserScore.objects.filter(user_id__in=similarities).exclude(
         school_id__in=user_ratings_school_id).values_list('school_id', flat=True).distinct())
     print("基于用户评分的兴趣度得分情况:", recommendations_cosine)
    return recommendations_cosine

补充推荐结果
def recommendations_supply(user_id, top_items: [tuple], top_n):
    print("top_items:", top_items)
    user_ratings = UserScore.objects.filter(user_id=user_id).values('school_id', 'score')
    user_ratings_school_id = [user_rating['school_id'] for user_rating in user_ratings]
     获取当前用户的收藏数据
    user_collections = UserCollection.objects.filter(user_id=user_id).values('school_id', 'collection')
     获取当前用户收藏的学校id
    user_collections_school_id = [user_collection['school_id'] for user_collection in user_collections]
    if len(top_items) < top_n:
        rest = top_n - len(top_items)
        exists_school_id = list(
            [top_item[0] for top_item in top_items]) + user_ratings_school_id + user_collections_school_id
        rest_id = set()
        while len(rest_id) < rest:
            random_id = random.randint(1, 855)
            if random_id not in exists_school_id:
                rest_id.add(random_id)
        recommendations_id = [item[0] for item in top_items] + list(rest_id)
    else:
        recommendations_id = [item[0] for item in top_items][:top_n]
    return recommendations_id


def user_based_recommend(request, default_similarity_jaccard=0, default_similarity_cosine=0, alpha=10):
    alpha_user = request.GET.get('alpha_user', '')
    if alpha_user != '':
        alpha_user = int(float(alpha_user))
        if 0 <= alpha_user <= 10:
            alpha = alpha_user
        elif alpha_user < 0:
            alpha_user = 0
        elif alpha_user > 10:
            alpha_user = 10
    alpha = alpha / 10
     print("推荐依据:评分情况:{0},收藏情况:{1}".format(alpha, 1 - alpha))
    top_n = 12
     获取当前用户id
    user_id = list(request.session.values())[0].get('id')
    similarities_cosine = user_cosine_similarity_ratings(user_id, default_similarity_cosine=default_similarity_cosine)
    similarities_jaccard = user_jaccard_similarity_collections(user_id,
                                                               default_similarity_jaccard=default_similarity_jaccard)
     print("similarities_cosine:", similarities_cosine)
     print("similarity_jaccard:", similarities_jaccard)
    similarities = alpha * MyDict(similarities_cosine) + (1 - alpha) * MyDict(similarities_jaccard)
     print("similarities:", similarities)

     测试:打印基于用户评分的用户相似度矩阵:
     print("基于用户评分的用户相似度矩阵:")
     print("user_id:", [i for i in similarities_cosine])
     print("similarity:", [round(i, 2) for i in similarities_cosine.values()])

     测试:打印基于用户收藏的用户相似度矩阵:
     print("基于用户收藏的用户相似度矩阵:")
     print("user_id:", [i for i in similarities_jaccard])
     print("similarity:", [round(i, 2) for i in similarities_jaccard.values()])

     根据相似度值为用户推荐物品
      打印推荐字典
    recommendations_cosine = user_recommendations_cosine_ratings(user_id=user_id, similarities=similarities,
                                                                 similarities_cosine=similarities_cosine)
    recommendations_jaccard = user_recommendations_jaccard_collections(user_id=user_id, similarities=similarities,
                                                                       similarities_jaccard=similarities_jaccard)
    print("当alpha=0.5时基于评分的兴趣度得分情况:\n", recommendations_cosine)
    print("当alpha=0.5时基于收藏的兴趣度得分情况:\n", recommendations_jaccard)
    
     测试:打印目标用户对于邻居用户中未评分学校的兴趣度得分
    recommendations = alpha * MyDict(recommendations_cosine) + (1 - alpha) * MyDict(recommendations_jaccard)

    recommendations = dict(filter(lambda item: item[1] > 0, recommendations.items()))
    print("当alpha=0.5时的加权兴趣度得分情况:\n", recommendations)

     返回前 top_n 个物品
    top_items = sorted(recommendations.items(), key=lambda x: x[1], reverse=True)
     print("Top items:", top_items)

     如果返回的数量不够top_n,就去随机补充一些没有被推荐和没有被当前用户评分过的学校id,补充至top_n个,返回top_n个被推荐学校的id
     如果够,直接返回top_n个被推荐学校的id
    recommendations_id = recommendations_supply(user_id=user_id, top_items=top_items, top_n=top_n)

     从数据库中根据id找到被推荐的学校,打乱顺序返回
    recommended_schools = models.School.objects.filter(id__in=recommendations_id).order_by('?')
     不打乱顺序,得分较高的排在前面
     recommended_schools = models.School.objects.filter(id__in=[item[0] for item in top_items])
     2.实例化分页对象
    page_object = Pagination(request, recommended_schools, page_size=12)

    context = {
        "alpha": alpha_user,
        "a5": "active",
        "title": "基于用户推荐",
        "link": "https://yz.chsi.com.cn/",
        "recommended_schools": page_object.page_queryset,
        "page_string": page_object.html()   生成页码
    }
    return render(request, 'recommend_base.html', context)

 def user_based_recommend_ratings(request, default_similarity=0):
     top_n = 12
      获取当前用户id
     user_id = list(request.session.values())[0].get('id')
      获取当前用户评分数据
     user_ratings = UserScore.objects.filter(user_id=user_id).values('school_id', 'score')
      获取当前用户评分的学校id
     user_ratings_school_id = [user_rating['school_id'] for user_rating in user_ratings]

      获取当前用户评分学校的评分情况:(school_id,score)
     user_ratings_school = [(user_rating['school_id'], user_rating['score']) for user_rating in user_ratings]
      print("目标用户评分情况:")
      print(user_ratings_school)
      测试:打印所有用户评分信息
      print("所有用户评分信息:")
      all_user_score = UserScore.objects.filter().order_by('user_id')
      print("user_id"+'\t\t'+"school_id"+"\t\t\t\t"+"score")
      for user in all_user_score:
          print(str(user.user_id) + "\t\t\t" + str(user.school)+"\t\t\t\t" + str(user.score))

      测试:构造用户评分矩阵
      print("用户评分矩阵:")
      print("user_id" + "\t" + "score_list")

      构造当前用户评分向量:user_rating_vector
     user_rating_vector = [0 for i in range(999)]
     for school_id, score in user_ratings_school:
         user_rating_vector[school_id] = score
      user_rating_vector[0] = user_id
      print(user_rating_vector)

      计算所有用户的相似度:如果两用户之间没有共同评分的学校,则相似度为0
     similarities = {}   定义字典来存放与当前用户相似用户的id和相似度
      print("邻居用户评分情况:")
     for user in User.objects.exclude(id=user_id):
          获取当前用户与其他用户共同评价的物品的评分数据
         ratings = user.userscores.filter(school_id__in=user_ratings_school_id).values('school_id', 'score')

         if ratings:   如果当前用户与该用户有共同评分的学校,则计算当前用户与该用户的相似度,这里使用余弦相似度
              获取该用户所有的评分学校的评分情况:(school_id,score)
             ratings = user.userscores.filter().values('school_id', 'score')
             ratings_school = [(rating['school_id'], rating['score']) for rating in ratings]
              print(ratings_school)
              构造该用户评分向量:rating_vector
             rating_vector = [0 for i in range(999)]
             for school_id, score in ratings_school:
                 rating_vector[school_id] = score
              rating_vector[0] = user.id
              print(rating_vector)
              计算两用户之间的余弦相似度
             similarity = cosine_similarity(user_rating_vector, rating_vector)
             if similarity > default_similarity:
                 similarities[user.id] = similarity
      打印相似度字典
      print("Similarities:", similarities)

      测试:打印用户相似度矩阵
      print("用户相似度矩阵:")
      print("用户id:", [round(i,2) for i in similarities])
      print("相似度:",[round(i,2) for i in similarities.values()])

      根据相似度值为用户推荐物品
     recommendations = {}   定义字典存放物品id和物品相似度
      print("邻居用户中目标用户未评分的学校:",UserScore.objects.filter(user_id__in=similarities).exclude(
              school_id__in=user_ratings_school_id).values_list('school_id', flat=True).distinct())

     for school_id in UserScore.objects.filter(user_id__in=similarities).exclude(
             school_id__in=user_ratings_school_id).values_list('school_id', flat=True).distinct():
          获取当前物品被评价的用户和评分数据
         item_ratings = UserScore.objects.filter(school_id=school_id).values('user_id', 'score')
          print("item_ratings:", item_ratings)

          初始化一个空列表
         weighted_scores = []
          遍历 item_ratings 中的每一条记录
         for rating in item_ratings:
              如果该评分记录对应的用户在 similarities 字典中,则计算该评分记录对该物品的权重得分
             if rating['user_id'] in similarities:
                  获取该评分记录对应用户与目标用户的相似度
                 similarity = similarities[rating['user_id']]
                  计算该评分记录对该物品的权重得分
                 weighted_score = similarity * rating['score']
                  将该权重得分添加到列表中
                 weighted_scores.append(weighted_score)
         numerator = sum(weighted_scores)
         denominator = sum(similarities.values())
         if denominator > 0:
             recommendations[school_id] = round(numerator / denominator, 2)
      打印推荐字典
      print("Recommendations:", recommendations)

      测试:打印目标用户对于邻居用户中未评分学校的兴趣度得分
      print("兴趣度得分情况:",recommendations)

      返回前 top_n 个物品
     top_items = sorted(recommendations.items(), key=lambda x: x[1], reverse=True)
     print("Top items:", top_items)

      如果返回的数量不够top_n,就去随机补充一些没有被推荐和没有被当前用户评分过的学校id,补充至top_n个
     if len(top_items) < top_n:
         rest = top_n - len(top_items)
         exists_school_id = list(recommendations.keys()) + user_ratings_school_id
         rest_id = set()
         while len(rest_id) < rest:
             random_id = random.randint(1, 855)
             if random_id not in exists_school_id:
                 rest_id.add(random_id)
         recommendations_id = [item[0] for item in top_items] + list(rest_id)
     else:
         recommendations_id = [item[0] for item in top_items][:12]
      从数据库中根据id找到被推荐的学校
     recommended_schools = models.School.objects.filter(id__in=recommendations_id).order_by('?')

      2.实例化分页对象
     page_object = Pagination(request, recommended_schools, page_size=12)

     context = {
         "a5": "active",
         "title": "基于用户推荐",
         "link": "https://yz.chsi.com.cn/",
         "recommended_schools": page_object.page_queryset,
          "page_string": page_object.html()   生成页码
     }

     return render(request, 'recommend_base.html', context)


 def user_based_recommend(request):
     top_n = 12
      获取当前用户id
     user_id = list(request.session.values())[0].get('id')
      获取当前用户评分数据
     user_ratings = UserScore.objects.filter(user_id=user_id).values('school_id', 'score')
      获取当前用户评分的学校id
     user_ratings_school_id = [user_rating['school_id'] for user_rating in user_ratings]
     user_ratings_school = [(user_rating['school_id'],user_rating['score']) for user_rating in user_ratings]
     print(user_ratings_school)

     获取当前用户评分的学校分数

     构造当前用户评分向量:
     user_rating_vector = [ 0 for i in range(1000)]
     for school_id,score in user_ratings_school:
         user_rating_vector[school_id] = score


      计算所有用户的相似度:如果两用户之间没有共同评分的学校,则相似度为0
     similarities = {}

     for user in User.objects.exclude(id=user_id):
          获取当前用户与其他用户共同评价的物品的评分数据
         ratings = user.userscores.filter(school_id__in=user_ratings_school_id).values('school_id','score')
         print("{0}:{1}".format(user, ratings))
         if ratings:如果当前用户与该用户有共同评分的学校,则计算当前用户与该用户的相似度,这里使用余弦相似度
             构造该用户评分向量:
             ratings_school = [(rating['school_id'], rating['score']) for rating in ratings]
             rating_vector = [0 for i in range(1000)]
             for school_id, score in ratings_school:
                 rating_vector[school_id] = score

             print("当前用户:",user_rating_vector)
             print("该用户:",rating_vector)
             similarity = cosine_similarity(user_rating_vector, rating_vector)
             similarities[user.id] = similarity
      打印相似度字典
     print("Similarities:", similarities)

      根据相似度值为用户推荐物品
     recommendations = {}

     for school_id in UserScore.objects.filter(user_id__in=similarities.keys()).exclude(
             school_id__in=user_ratings_school_id).values_list('school_id', flat=True).distinct():
          获取当前物品被评价的用户和评分数据
         print(school_id)
         item_ratings = UserScore.objects.filter(school_id=school_id).values('user_id', 'score')
         print("item_ratings:", item_ratings)

          初始化一个空列表
         weighted_scores = []
          遍历 item_ratings 中的每一条记录
         for rating in item_ratings:
              如果该评分记录对应的用户在 similarities 字典中,则计算该评分记录对该物品的权重得分
             if rating['user_id'] in similarities:
                  获取该评分记录对应用户与目标用户的相似度
                 similarity = similarities[rating['user_id']]
                  计算该评分记录对该物品的权重得分
                 weighted_score = similarity * rating['score']
                  将该权重得分添加到列表中
                 weighted_scores.append(weighted_score)
          numerator = sum([similarities[user_id] * score for user_id, score in item_ratings if user_id in similarities])
         numerator = sum(weighted_scores)
         print("numerator:", numerator)
          denominator = sum([similarities[user_id] for user_id in similarities])
         denominator = sum(similarities.values())

         print("denominator:", denominator)
         if denominator > 0:
             recommendations[school_id] = numerator / denominator
      打印推荐字典
     print("Recommendations:", recommendations)

      返回前 top_n 个物品
      top_items = sorted(recommendations.items(), key=lambda x: x[1], reverse=True)[:top_n]
     top_items = sorted(recommendations.items(), key=lambda x: x[1], reverse=True)
     print("top_items", top_items)
      recommended_schools = models.School.objects.filter(id__in=[item[0] for item in top_items]).order_by("?")[:top_n]
     recommended_schools = models.School.objects.filter(id__in=[item[0] for item in top_items])
     print(recommended_schools)
      2.实例化分页对象
     page_object = Pagination(request, recommended_schools, page_size=12)

     context = {
         "title": "基于用户推荐",
         "link": "https://yz.chsi.com.cn/",
         "recommended_schools": page_object.page_queryset,
         "page_string": page_object.html()   生成页码
     }

     return render(request, 'recommend_base.html', context)


 注释调试版
 def user_based_recommend(request, default_similarity_jaccard=0, default_similarity_cosine=0, alpha=1):
     top_n = 12
      获取当前用户id
     user_id = list(request.session.values())[0].get('id')
      获取当前用户评分数据
     user_ratings = UserScore.objects.filter(user_id=user_id).values('school_id', 'score')
      获取当前用户收藏数据
     user_collections = UserCollection.objects.filter(user_id=user_id).values('school_id', 'collection')
      获取当前用户评分的学校id
     user_ratings_school_id = [user_rating['school_id'] for user_rating in user_ratings]
      获取当前用户收藏的学校id
     user_collections_school_id = [user_collection['school_id'] for user_collection in user_collections]

      获取当前用户评分学校的评分情况:(school_id,score)
     user_ratings_school = [(user_rating['school_id'], user_rating['score']) for user_rating in user_ratings]
      获取当前用户的收藏情况:(school_id,1)
      user_collections_school = [(user_collection['school_id'], user_collection['collection']) for user_collection in
                                 user_collections]
      print("目标用户评分情况:")
      print(user_ratings_school)
      测试:打印所有用户评分信息
      print("所有用户评分信息:")
      all_user_score = UserScore.objects.filter().order_by('user_id')
      print("user_id"+'\t\t'+"school_id"+"\t\t\t\t"+"score")
      for user in all_user_score:
          print(str(user.user_id) + "\t\t\t" + str(user.school)+"\t\t\t\t" + str(user.score))

      测试:构造用户评分矩阵
      print("用户评分矩阵:")
      print("user_id" + "\t" + "score_list")

      构造当前用户评分向量:user_rating_vector
     user_rating_vector = [0 for i in range(999)]
     for school_id, score in user_ratings_school:
         user_rating_vector[school_id] = score
      构造当前用户收藏向量
     user_collection_vector = [0 for i in range(999)]
     for school_id in user_collections_school_id:
         user_collection_vector[school_id] = 1
      user_rating_vector[0] = user_id
      print(user_rating_vector)

      计算所有用户的相似度:如果两用户之间没有共同评分的学校,则相似度为0
     similarities_jaccard = {}   定义字典来存放与当前用户相似用户的id和相似度
      print("邻居用户评分情况:")

     for user in User.objects.exclude(id=user_id):
          获取当前用户与其他用户共同收藏的物品的id
         collections = user.usercollections.filter(school_id__in=user_ratings_school_id).values('school_id')

         if collections:   如果当前用户与该用户有共同收藏的学校,则计算当前用户与该用户的相似度,这里使用杰卡德
              获取该用户所有的收藏情况:(school_id,score)
             collections = user.usercollections.filter().values('school_id')
             collections_school_id = [(collection['school_id']) for collection in collections]
              print(ratings_school)
              构造该用户收藏向量:collection_vector
             collection_vector = [0 for i in range(999)]
             for school_id in collections_school_id:
                 collection_vector[school_id] = 1
              rating_vector[0] = user.id
              print(rating_vector)
              计算两用户之间的杰卡德相似度
             similarity_jaccard = jaccard_similarity(user_rating_vector, collection_vector)
             if similarity_jaccard > default_similarity_jaccard:
                 similarities_jaccard[user.id] = similarity_jaccard

     similarities_cosine = {}
     for user in User.objects.exclude(id=user_id):
          获取当前用户与其他用户共同评价的物品的评分数据
         ratings = user.userscores.filter(school_id__in=user_ratings_school_id).values('school_id', 'score')

         if ratings:   如果当前用户与该用户有共同评分的学校,则计算当前用户与该用户的相似度,这里使用余弦相似度
              获取该用户所有的评分学校的评分情况:(school_id,score)
             ratings = user.userscores.filter().values('school_id', 'score')
             ratings_school = [(rating['school_id'], rating['score']) for rating in ratings]
              print(ratings_school)
              构造该用户评分向量:rating_vector
             rating_vector = [0 for i in range(999)]
             for school_id, score in ratings_school:
                 rating_vector[school_id] = score
              rating_vector[0] = user.id
              print(rating_vector)
              计算两用户之间的余弦相似度
             similarity_cosine = cosine_similarity(user_rating_vector, rating_vector)
             if similarity_cosine > default_similarity_cosine:
                 similarities_cosine[user.id] = similarity_cosine
      打印相似度字典
      print("Similarities:", similarities)

      测试:打印用户相似度矩阵
      print("用户相似度矩阵:")
      print("用户id:", [round(i,2) for i in similarities])
      print("相似度:",[round(i,2) for i in similarities.values()])
     print("similarities_cosine:", similarities_cosine)
     print("similarity_jaccard:", similarities_jaccard)
     similarities = alpha * MyDict(similarities_cosine) + (1 - alpha) * MyDict(similarities_jaccard)
     print("similarities:", similarities)

      根据相似度值为用户推荐物品
     recommendations_cosine = {}   定义字典存放物品id和物品相似度
     print("邻居用户已评分的学校中目标用户未评分的学校:", UserScore.objects.filter(user_id__in=similarities).exclude(
         school_id__in=user_ratings_school_id).values_list('school_id', flat=True).distinct())

      邻居用户已评分的学校中目标用户未评分的学校
     for school_id in UserScore.objects.filter(user_id__in=similarities).exclude(
             school_id__in=user_ratings_school_id).values_list('school_id', flat=True).distinct():
          获取评价了当前物品的用户和评分数据
         item_ratings = UserScore.objects.filter(school_id=school_id).values('user_id', 'score')
          print("item_ratings:", item_ratings)
          初始化一个空列表
         weighted_scores = []
          遍历 item_ratings 中的每一条记录
         for rating in item_ratings:
              如果该评分记录对应的用户在 similarities 字典中,则计算该评分记录对该物品的权重得分
             if rating['user_id'] in similarities_cosine:
                  获取该评分记录对应用户与目标用户的相似度
                 similarity = similarities_cosine[rating['user_id']]
                  计算该评分记录对该物品的权重得分
                 weighted_score = similarity * rating['score']
                  将该权重得分添加到列表中
                 weighted_scores.append(weighted_score)
         numerator = sum(weighted_scores)
         denominator = sum(similarities_cosine.values())
         if denominator > 0:
             recommendations_cosine[school_id] = round(numerator / denominator, 2)

     recommendations_jaccard = {}
     print("邻居用户已收藏的学校中目标用户未收藏的学校:",
           UserCollection.objects.filter(user_id__in=similarities).exclude(
               school_id__in=user_collections_school_id).values_list('school_id', flat=True).distinct())
      邻居用户已收藏的学校中目标用户未收藏的学校
     for school_id in UserCollection.objects.filter(user_id__in=similarities).exclude(
             school_id__in=user_collections_school_id).values_list('school_id', flat=True).distinct():
          获取收藏了当前物品的用户:用户id和收藏情况(collection = 1)
         item_collections = UserCollection.objects.filter(school_id=school_id).values('user_id', 'collection')
          print("item_ratings:", item_ratings)
          初始化一个空列表
         weighted_scores = []
          遍历 item_ratings 中的每一条记录
         for collection in item_collections:
              如果该收藏记录对应的用户在 similarities_jaccard 字典中,则计算该收藏记录对该物品的权重得分
             if collection['user_id'] in similarities_jaccard:
                  获取该评分记录对应用户与目标用户的相似度
                 similarity = similarities_jaccard[collection['user_id']]
                  计算该评分记录对该物品的权重得分
                 weighted_score = similarity * collection['collection']
                  将该权重得分添加到列表中
                 weighted_scores.append(weighted_score)
         numerator = sum(weighted_scores)
         denominator = sum(similarities_jaccard.values())
         if denominator > 0:
             recommendations_jaccard[school_id] = round(numerator / denominator, 2)

       打印推荐字典
     print("Recommendations_cosine:", recommendations_cosine)
     print("Recommendations_jaccard:", recommendations_jaccard)
     
      测试:打印目标用户对于邻居用户中未评分学校的兴趣度得分
     recommendations = alpha * MyDict(recommendations_cosine) + (1 - alpha) * MyDict(recommendations_jaccard)

     recommendations = dict(filter(lambda item: item[1] > 0, recommendations.items()))
     print("兴趣度得分情况:", recommendations)

      返回前 top_n 个物品
     top_items = sorted(recommendations.items(), key=lambda x: x[1], reverse=True)
     print("Top items:", top_items)

      如果返回的数量不够top_n,就去随机补充一些没有被推荐和没有被当前用户评分过的学校id,补充至top_n个
     if len(top_items) < top_n:
         rest = top_n - len(top_items)
         exists_school_id = list(recommendations.keys()) + user_ratings_school_id
         rest_id = set()
         while len(rest_id) < rest:
             random_id = random.randint(1, 855)
             if random_id not in exists_school_id:
                 rest_id.add(random_id)
         recommendations_id = [item[0] for item in top_items] + list(rest_id)
     else:
         recommendations_id = [item[0] for item in top_items][:12]
      从数据库中根据id找到被推荐的学校
     recommended_schools = models.School.objects.filter(id__in=recommendations_id).order_by('?')

      2.实例化分页对象
     page_object = Pagination(request, recommended_schools, page_size=12)

     context = {
         "a5": "active",
         "title": "基于用户推荐",
         "link": "https://yz.chsi.com.cn/",
         "recommended_schools": page_object.page_queryset,
         "page_string": page_object.html()   生成页码
     }

     return render(request, 'recommend_base.html', context)


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • 469
  • 470
  • 471
  • 472
  • 473
  • 474
  • 475
  • 476
  • 477
  • 478
  • 479
  • 480
  • 481
  • 482
  • 483
  • 484
  • 485
  • 486
  • 487
  • 488
  • 489
  • 490
  • 491
  • 492
  • 493
  • 494
  • 495
  • 496
  • 497
  • 498
  • 499
  • 500
  • 501
  • 502
  • 503
  • 504
  • 505
  • 506
  • 507
  • 508
  • 509
  • 510
  • 511
  • 512
  • 513
  • 514
  • 515
  • 516
  • 517
  • 518
  • 519
  • 520
  • 521
  • 522
  • 523
  • 524
  • 525
  • 526
  • 527
  • 528
  • 529
  • 530
  • 531
  • 532
  • 533
  • 534
  • 535
  • 536
  • 537
  • 538
  • 539
  • 540
  • 541
  • 542
  • 543
  • 544
  • 545
  • 546
  • 547
  • 548
  • 549
  • 550
  • 551
  • 552
  • 553
  • 554
  • 555
  • 556
  • 557
  • 558
  • 559
  • 560
  • 561
  • 562
  • 563
  • 564
  • 565
  • 566
  • 567
  • 568
  • 569
  • 570
  • 571
  • 572
  • 573
  • 574
  • 575
  • 576
  • 577
  • 578
  • 579
  • 580
  • 581
  • 582
  • 583
  • 584
  • 585
  • 586
  • 587
  • 588
  • 589
  • 590
  • 591
  • 592
  • 593
  • 594
  • 595
  • 596
  • 597
  • 598
  • 599
  • 600
  • 601
  • 602
  • 603
  • 604
  • 605
  • 606
  • 607
  • 608
  • 609
  • 610
  • 611
  • 612
  • 613
  • 614
  • 615
  • 616
  • 617
  • 618
  • 619
  • 620
  • 621
  • 622
  • 623
  • 624
  • 625
  • 626
  • 627
  • 628
  • 629
  • 630
  • 631
  • 632
  • 633
  • 634
  • 635
  • 636
  • 637
  • 638
  • 639
  • 640
  • 641
  • 642
  • 643
  • 644
  • 645
  • 646
  • 647
  • 648
  • 649
  • 650
  • 651
  • 652
  • 653
  • 654
  • 655
  • 656
  • 657
  • 658
  • 659
  • 660
  • 661
  • 662
  • 663
  • 664
  • 665
  • 666
  • 667
  • 668
  • 669
  • 670
  • 671
  • 672
  • 673
  • 674
  • 675
  • 676
  • 677
  • 678
  • 679
  • 680
  • 681
  • 682
  • 683
  • 684
  • 685
  • 686
  • 687
  • 688
  • 689
  • 690
  • 691
  • 692
  • 693
  • 694
  • 695
  • 696
  • 697
  • 698
  • 699
  • 700
  • 701
  • 702
  • 703
  • 704
  • 705
  • 706
  • 707
  • 708
  • 709
  • 710
  • 711
  • 712
  • 713
  • 714
  • 715
  • 716

源码获取:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/123610?site
推荐阅读
相关标签