基于知识图谱的电影推荐系统——Neo4jPython

news/2025/2/19 8:06:52/

文章目录

  • 1. 数据解下载与配置
  • 2. 将处理好的数据导入数据库中
  • 3. 执行项目

1. 数据解下载与配置

选择TMDB电影数据集,Netflix Prize 数据集下载。

也可直接从这里下载:链接: https://pan.baidu.com/s/1l6wjwcUzy5G_dIlVDbCkpw 提取码: pkq6 。

在这里插入图片描述

在这里插入图片描述

执行preproc.py文件,进行数据预处理,生成5个处理后的文件:

import pandas as pd
import json
import redef Netflix(MAX_USER = 1000):d_movie = dict()s_movie = set()out_movies = open("../out_movies.csv","w")out_movies.write("title\n")for line in open("../movie_titles.csv","r",encoding = 'ISO-8859-1'):line = line.strip().split(',')movie_id = int(line[0])title = line[2].replace("\"","")title = "\"" + title + "\""d_movie[movie_id] = titleif title in s_movie:continues_movie.add(title)out_movies.write(f"{title}\n")out_movies.close()out_grade = open("../out_grade.csv","w")out_grade.write("user_id,title,grade\n")files = ["../combined_data_1.txt"]for f in files:movie_id = -1for line in open(f,"r"):pos = line.find(":")if pos != -1: # is a new usermovie_id = int(line[:pos])continueline = line.strip().split(",")user_id = int(line[0])rating = int(line[1])if user_id > MAX_USER:continueout_grade.write(f"{user_id},{d_movie[movie_id]},{rating}\n")out_grade.close()def TMDB():pattern = re.compile("[A-Za-z0-9]+")# 提取电影类型out_genre = open("../out_genre.csv","w",encoding='utf-8')out_genre.write("title,genre\n")# 提取电影关键词out_keyword = open("../out_keyword.csv","w",encoding='utf-8')out_keyword.write("title,keyword\n")# 提取电影制片人out_productor = open("../out_productor.csv","w",encoding='utf-8')out_productor.write("title,productor\n")df = pd.read_csv("../tmdb_5000_movies.csv", sep=",")json_columns = ['genres', 'keywords', 'production_companies']for column in json_columns:df[column] = df[column].apply(json.loads)df = df[["genres", "keywords", "original_title","production_companies"]]for _, row in df.iterrows():title = row["original_title"]if not pattern.fullmatch(title):continuetitle = "\"" + title + "\""for g in row["genres"]:genre = g["name"]genre = "\"" + genre + "\""out_genre.write(f"{title},{genre}\n")for g in row["keywords"]:keyword = g["name"]keyword = "\"" + keyword + "\""out_keyword.write(f"{title},{keyword}\n")for g in row["production_companies"]:productor = g["name"]productor = "\"" + productor + "\""out_productor.write(f"{title},{productor}\n")if __name__ == "__main__":Netflix()TMDB()

在这里插入图片描述

2. 将处理好的数据导入数据库中

将上面数据预处理生成的5个文件,放入import文件夹中:

在这里插入图片描述

在这里插入图片描述

3. 执行项目

修改main.py中的driver,输入自己数据库的用户名与密码。

执行main.py文件:

from neo4j import GraphDatabase
import pandas as pduri = "neo4j://localhost:7687"
driver = GraphDatabase.driver(uri, auth=("neo4j", "Liu881389."))k = 10 # nearest neighbors (most similar users) to consider
movies_common = 3 # how many movies in common to be consider an user similar
users_common = 2 # minimum number of similar users that have seen the movie to consider it
threshold_sim = 0.9 # threshold to consider users similardef load_data():with driver.session() as session:session.run("""MATCH ()-[r]->() DELETE r""")session.run("""MATCH (r) DELETE r""")print("Loading movies...")#加载数据,创建Movie标签,title属性的实体session.run("""LOAD CSV WITH HEADERS FROM "file:///out_movies.csv" AS csvCREATE (:Movie {title: csv.title})""")print("Loading gradings...")#加载评分数据,MERGE是搜索给定模式,如果存在,则返回结果如果它不存在于图中,则它创建新的节点/关系并返回结果。session.run("""LOAD CSV WITH HEADERS FROM "file:///out_grade.csv" AS csvMERGE (m:Movie {title: csv.title}) MERGE (u:User {id: toInteger(csv.user_id)})CREATE (u)-[:RATED {grading : toInteger(csv.grade)}]->(m)""")#加载影片类型数据    print("Loading genres...")session.run("""LOAD CSV WITH HEADERS FROM "file:///out_genre.csv" AS csvMERGE (m:Movie {title: csv.title})MERGE (g:Genre {genre: csv.genre})CREATE (m)-[:HAS_GENRE]->(g)""")print("Loading keywords...")#加载关键词数据    session.run("""LOAD CSV WITH HEADERS FROM "file:///out_keyword.csv" AS csvMERGE (m:Movie {title: csv.title})MERGE (k:Keyword {keyword: csv.keyword})CREATE (m)-[:HAS_KEYWORD]->(k)""")print("Loading productors...")#制片人    session.run("""LOAD CSV WITH HEADERS FROM "file:///out_productor.csv" AS csvMERGE (m:Movie {title: csv.title})MERGE (p:Productor {name: csv.productor})CREATE (m)-[:HAS_PRODUCTOR]->(p)""")def queries():while True:userid = int(input("请输入要为哪位用户推荐电影,输入其ID即可: "))m = int(input("为该用户推荐多少个电影呢? "))genres = []if int(input("是否需要过滤掉不喜欢的类型?(输入0或1)")):#过滤掉不喜欢的类型with driver.session() as session:try:q = session.run(f"""MATCH (g:Genre) RETURN g.genre AS genre""")result = []for i, r in enumerate(q):result.append(r["genre"])#找到图谱中所有的电影类型df = pd.DataFrame(result, columns=["genre"])print()print(df)inp = input("输入不喜欢的类型索引即可,例如:1 2 3  ")if len(inp) != 0:inp = inp.split(" ")genres = [df["genre"].iloc[int(x)] for x in inp]except:print("Error")with driver.session() as session:#找到当前ID评分的电影q = session.run(f"""MATCH (u1:User {{id : {userid}}})-[r:RATED]-(m:Movie)RETURN m.title AS title, r.grading AS gradeORDER BY grade DESC""")print()print("Your ratings are the following:")result = []for r in q:result.append([r["title"], r["grade"]])if len(result) == 0:print("No ratings found")else:df = pd.DataFrame(result, columns=["title", "grade"])print()print(df.to_string(index=False))print()session.run(f"""MATCH (u1:User)-[s:SIMILARITY]-(u2:User)DELETE s""")#找到当前用户评分的电影以及这些电影被其他用户评分的用户,with是把查询集合当做结果以便后面用where 余弦相似度计算session.run(f"""MATCH (u1:User {{id : {userid}}})-[r1:RATED]-(m:Movie)-[r2:RATED]-(u2:User)WITHu1, u2,COUNT(m) AS movies_common,SUM(r1.grading * r2.grading)/(SQRT(SUM(r1.grading^2)) * SQRT(SUM(r2.grading^2))) AS simWHERE movies_common >= {movies_common} AND sim > {threshold_sim}MERGE (u1)-[s:SIMILARITY]-(u2)SET s.sim = sim""")Q_GENRE = ""if (len(genres) > 0):Q_GENRE = "AND ((SIZE(gen) > 0) AND "Q_GENRE += "(ANY(x IN " + str(genres) + " WHERE x IN gen))"Q_GENRE += ")"#找到相似的用户,然后看他们喜欢什么电影 Collect:将所有值收集到一个集合list中q = session.run(f"""MATCH (u1:User {{id : {userid}}})-[s:SIMILARITY]-(u2:User)WITH u1, u2, sORDER BY s.sim DESC LIMIT {k}MATCH (m:Movie)-[r:RATED]-(u2)OPTIONAL MATCH (g:Genre)--(m)WITH u1, u2, s, m, r, COLLECT(DISTINCT g.genre) AS genWHERE NOT((m)-[:RATED]-(u1)) {Q_GENRE}WITHm.title AS title,SUM(r.grading * s.sim)/SUM(s.sim) AS grade,COUNT(u2) AS num,genWHERE num >= {users_common}RETURN title, grade, num, genORDER BY grade DESC, num DESCLIMIT {m}""")print("Recommended movies:")result = []for r in q:result.append([r["title"], r["grade"], r["num"], r["gen"]])if len(result) == 0:print("No recommendations found")print()continuedf = pd.DataFrame(result, columns=["title", "avg grade", "num recommenders", "genres"])print()print(df.to_string(index=False))print()if __name__ == "__main__":if int(input("是否需要重新加载并创建知识图谱?(请选择输入0或1)")):load_data()queries()

运行main.py文件后:

在这里插入图片描述

系统会询问是否需要重新加载并创建知识图谱,在第一次时输入1。

在这里插入图片描述

加载完成后可以在neo4j中查看:

在这里插入图片描述

接下来输入需要查询的信息:

在这里插入图片描述

输出结果:

在这里插入图片描述


http://www.ppmy.cn/news/435727.html

相关文章

幻灯片转换为一页多张讲义打印格式

在实际学习过程中, 我们有时会需要将PPT格式的幻灯片打印出来,为了节省纸张,可以在一页上打印多页幻灯片。但直接在WPS或powerpoint设置打印格式,会使得白边过多,打印效果不够紧凑。为此,本篇博文将利用WPS…

单张PPT转成单张PDF的PDF文件怎么设置打印出一页纸有6页PPT

感谢天津大学李森的技术帮助atomer 常见的PPT可以在打印的时候设置的时候设置每页纸打印6页PPT(由于下面电脑没有连接打印机,所以没法设置打印页边距,导致现在的页边距比较宽,PPT页面和纸张大小不一致) 但是举办方为了保护用户的版权&#xf…

php针式打印机打多张,ppt打印怎么一页打多个

ppt打印一页多个的方法:首先在电脑上找到需要打印的PPT;然后找到点击“文件”,并在出现的信息中点击“打印”;接着找到“打印内容”,点击一下,并在出现的信息中选择“讲义”;最后点击选择数量即…

如何在PPT中实现多张图片叠加在一起,点击消失一张出来下一张的效果

原文:http://blog.sina.com.cn/s/blog_4fc125320100p9ub.html 这两天在帮忙修改一个PPT的课件,主要内容是让学生学习关于职业的单词,在PPT里的有一个效果是在同一张幻灯片里,点击出来第一张图片,学习完之后&#xff0…

PPT打印处理 深色背景/白色字体转换 + 多分页占满

目录 1. 初始样式 2. 设置背景 3. 设置分页 4. 设置纯黑白,使文字打印出来 1. 初始样式 背景为深色,而字体为白色,但打印的时候希望整体为白色,否则打印机消耗太大。 2. 设置背景 首先如下图将背景设置为白色,如…

PPT打印技巧——A4纸如何完美紧凑打印九页ppt

先上效果图(边框可选,可自行设置页眉页码等): 紧凑版: 宽松版: office 2016 ppt 原生讲义模式打印效果: 具体操作: ppt设置打印整页,加框/不加框 打印机设置横…

如何在PPT中同时插入多张图片且每张占一页

前提 有时候,我们需要在在PPT中插入大量图片,比如成百上千张图片,如果我们手动一张一张插入图片,然后再一张一张调格式,想一想都让人头皮发麻。而且亲身实验,按上述方法做完之后,整个人差不多废…

ppt怎么设置页面比例为4:3

ppt怎么设置页面比例为4:3