本文利用Python的Django框架从0开始最终实现一个简单的基于协同过滤算法的电影推荐系统。
电影推荐算法我们采用用户的评分历史和相似度矩阵。
目录
一个简单的系统的核心功能模块如下:
- 用户注册、登录、登出
- 电影列表展示(主页):展示所有电影的列表页面。支持通过搜索查询特定电影。
- 电影详情(评分):
-
- 展示特定电影的详细信息页面。
- 用户可以管理自己的观看列表(添加或移除电影)和进行电影评分。
- 根据用户的评分行为,显示电影评分和是否已评分的标志。
- 观看列表管理:
-
- 展示用户添加到观看列表中的电影列表。
- 支持通过搜索查询特定电影。
- 电影推荐:
-
- 实现电影推荐算法,根据用户的评分历史和相似度矩阵推荐电影。
- 为新用户(未进行过评分的用户)提供默认推荐电影。
- 推荐电影列表排除用户已观看的电影。
设计数据库之间我们先简单了解下什么是基于协同过滤算法
协同过滤算法的基本原理是通过分析不同用户的历史行为数据,找到用户间的相似性,并据此进行个性化推荐。具体而言,该算法基于两个关键步骤进行:一是相似度的计算,二是预测与推荐。
相似度计算:
协同过滤算法首先计算用户或物品之间的相似度。对于基于用户的协同过滤,算法会分析用户的历史行为记录(如购买、浏览、评分等),计算用户之间的相似度。对于基于物品的协同过滤,算法会分析不同物品被用户交互的记录,计算物品之间的相似度。相似度的计算方法有多种,如余弦相似度、皮尔逊相关系数等。
预测与推荐:
在计算了用户或物品间的相似度后,协同过滤算法会根据相似用户或相似物品的评价来预测目标用户对未知物品的评价或喜好程度。对于基于用户的协同过滤,算法会找到与目标用户相似的其他用户,根据这些用户对物品的评价来预测目标用户的喜好。对于基于物品的协同过滤,算法会找到与目标用户喜欢的物品相似的其他物品,推荐给目标用户。
本系统中我们实现电影推荐大概的系统运行过程如下图所示:
为了实现以上功能模块我们需要简单设计一下数据库,大致包含如下几个表:
电影表
表名: movie
列名 | 类型 | 描述 |
id | Integer | 主键,自增,Django 自动添加 |
title | CharField | 电影标题,最大长度200个字符 |
title_zh | CharField | 中文电影标题,最大长度200个字符,可以为空 |
genre | CharField | 电影类型,最大长度100个字符 |
genre_zh | CharField | 中文电影类型,最大长度100个字符 |
movie_logo | FileField | 电影Logo,存储文件路径 |
电影评分表
表名: myrating
列名 | 类型 | 描述 |
id | Integer | 主键,自增,Django 自动添加 |
user_id | ForeignKey | 关联到 User 表的用户ID,外键 |
movie_id | ForeignKey | 关联到 Movie 表的电影ID,外键 |
rating | IntegerField | 评分,默认值为0,取值范围在0到5之间 |
收藏喜爱表
表名: mylist
列名 | 类型 | 描述 |
id | Integer | 主键,自增,Django 自动添加 |
user_id | ForeignKey | 关联到 User 表的用户ID,外键 |
movie_id | ForeignKey | 关联到 Movie 表的电影ID,外键 |
watch | BooleanField | 是否已观看,默认值为False |
系统实现
下面开始撸代码:
创建项目
django-admin startproject django_movie_recommender
进入项目文件夹
cd django_movie_recommender
或者重新用Pycharm打开项目文件夹
创建虚拟环境
python -m venv venv
进入虚拟环境
venv\Scripts\activate.bat
成功进入虚拟环境有如下标识:
在虚拟环境中安装Django
pip install django
创建app
Django框架下的核心的模型和视图都需要在app中实现,我们简单点就创建一个app名为app01,实际项目中可以根据模块创建多个app。
python manage.py startapp app01
截止到目前的文件结构
安装app
在文件 django_movie_recommender/settings.py
中更新代码如下
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01',#添加此项
]
定义模型
根据我们前面的数据库定义模型如下:
app01/models.py
from django.db import models
from django.core.validators import MaxValueValidator, MinValueValidator
from django.contrib.auth.models import User
# Create your models here.
class Movie(models.Model):
title = models.CharField(max_length=200)
title_zh = models.CharField(max_length=200,null='True')
genre = models.CharField(max_length=100)
genre_zh = models.CharField(max_length=100,null='True')
movie_logo = models.FileField()
def __str__(self):
return self.title
class Myrating(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
movie = models.ForeignKey(Movie, on_delete=models.CASCADE)
rating = models.IntegerField(default=0, validators=[MaxValueValidator(5), MinValueValidator(0)])
class MyList(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
movie = models.ForeignKey(Movie, on_delete=models.CASCADE)
watch = models.BooleanField(default=False)
安装连接MySQL的包
pip install mysqlclient
MySQL的安装就不详细讲了,大家自行安装。
手工创建一个数据库,名字为:mymovie_recommed
CREATE DATABASE mymovie_recommed;
连接MySQL数据库配置
django_movie_recommender/settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 数据库引擎
'NAME': 'mymovie_recommed', # 数据库名称
'HOST': '127.0.0.1', # 数据库地址,本机 ip 地址 127.0.0.1
'PORT': 3306, # 端口
'USER': 'root', # 数据库用户名
'PASSWORD': '123456', # 数据库密码
}
}
迁移模型
python manage.py makemigrations
每次模型有变动需要执行命令,以便让Django能够识别。
更新迁移表
python manage.py migrate
根据上述命令识别到的模型变动,自动更新连接的数据库表,首次则会自动在签名配置的数据库中自动创建表结构。
数据表创建成功
创建超级用户
python manage.py createsuperuser
用户名:admin
密码:123456
运行服务器
python manage.py runserver
http://127.0.0.1:8000/ 出现下面界面说明我们Django 服务器正常运行。
输入后台网址看下:http://127.0.0.1:8000/admin/
登录后没有显示自定义的模型,还需要注册模型到后台。
模型注册到admin后台
app01/admin.py
from django.contrib import admin
from .models import Movie, Myrating, MyList
# Register your models here.
admin.site.register(Movie)
admin.site.register(Myrating)
admin.site.register(MyList)
尝试增加一条电影记录:
添加成功
详细功能和页面实现
以上我们已经完成了Django项目创建并连接到了MySQL数据库。
接下来我们来一步步实现各个核心模块的功能。
电影列表展示
从数据库抓取电影的标题,图片信息展示到前台。
Django的功能实现遵循MTV模式,其实跟Spring的MVC差不多,核心是模型(Model),模板(Template)和视图(View)。
模型是数据库层在Django中的表现,用户和数据库交互。
模板是前台展示的网页。
视图是一些函数,用于后端的数据处理,并传递数据到前台模板及接收模板数据更新数据库。
前端网页模板
在根目录下新建文件夹templates用于管理模板文件。
然后配置下模板位置,告诉Django我们的模板存放默认的位置。
import os
*...
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], # 添加此项
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
在templates
文件夹下新建一个电影列表模板文件:templates/list.html
,这里我们为了快速实现系统,直接引用在线Bootstrap的样式库。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>电影列表</title>
<!-- 引入 Bootstrap CSS 文件,使用中国 CDN 加速源 -->
<link rel="stylesheet" href="https://cdn.bootcss.com/twitter-bootstrap/4.6.0/css/bootstrap.min.css">
<style>
.movie-img {
max-width: 100px; /* 设置电影图片的最大宽度 */
height: auto; /* 图片高度自适应 */
}
</style>
</head>
<body>
<div class="container">
<h1 class="mt-5 mb-4 text-center">电影列表</h1>
<div class="row">
{% if movies %}
{% for movie in movies %}
<div class="col-md-2">
<div class="card mb-2 " style="border: none;">
<img class="movie-img mx-auto d-block mt-3" src="{{ movie.movie_logo.url }}" alt="电影图片">
<div class="card-body">
<h5 class="card-title text-center">{{movie.title_zh}}</h5>
</div>
</div>
</div>
{% endfor %}
{% endif %}
</div>
</div>
<!-- 引入 Bootstrap JS 文件,使用中国 CDN 加速源 -->
<script src="https://cdn.bootcss.com/twitter-bootstrap/4.6.0/js/bootstrap.bundle.min.js"></script>
</body>
</html>
视图函数
app01/views.py
,在文件中编写如下视图函数,将movies
的信息传递到我们前面的list.html
模板。
from django.shortcuts import render
# Create your views here.
# 首页视图函数,展示所有电影列表
from app01.models import Movie
def index(request):
movies = Movie.objects.all() # 获取所有电影对象
return render(request, 'list.html', {'movies': movies}) # 渲染并显示电影列表模板
路由URL配置
在如下文件django_movie_recommender/urls.py
配置路由信息。url可以理解为访问网站时输入的网址链接,配置好url后Django才知道怎样定位app。
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('index', views.index, name='index'),
]
重新运行服务器
输入地址:http://127.0.0.1:8000/index
图片没展示出来?原因是数据库只存了图片的文件名,DJango没找到对应的媒体文件。
找到django_movie_recommender/settings.py
中添加如下代码指定媒体文件的默认位置。
MEDIA_ROOT = os.path.join(BASE_DIR, '/media')
MEDIA_URL = '/media/'
在根目录下新建文件夹:media
,把电影Logo图片移动到此文件夹。
去admin后台我们直接在再多添加几条记录。
重新运行服务器,浏览器输入网址:http://127.0.0.1:8000/index ,图片已经可以正常展示。
致此,我们已经完成了一个Django项目系统的绝大部分的配置,同时基于MTV 的模式,完整的实现了一个电影主页列表展示的功能。
下一步我们将继续完善电影详情,电影推荐以及注册登录等核心功能模块的开发!
电影详情功能和页面
待续...
电影推荐功能页面
待续...
注册登录
待续...