综合设计——多源异构数据采集与融合应用综合实践
| 项目属性 | 内容 |
|---|---|
| 课程名称 | 102202128 |
| 项目名称 | 都给爷爬 |
| 102202128 | 林子豪 |
| 项目简介 | 本项目旨在开发一个免费的公益音乐疗愈平台,为心理疾病患者提供个性化的音乐推荐服务。 项目目标: 现有的音乐软件大多需要付费会员,并且存在打榜等非个性化推荐现象。我们希望通过该项目,为心理疾病患者提供一个免费、个性化的音乐疗愈平台,帮助他们通过音乐缓解心理压力,改善情绪。 项目需求: 市面上的音乐软件大多存在付费门槛和打榜现象,无法满足个性化推荐需求。我们希望开发一个能够根据患者和医生的建议,提供个性化音乐推荐的系统,帮助患者获得更舒适的音乐疗愈体验。 |
| 项目技术路线 | Python(Django, PyTorch, TensorFlow) 爬虫技术 MySQL |
| 团队成员 | 102202135 102202146 102202127 102202125 102202139 102202109 102202128 |
| 项目目标 | 我们希望通过该公益项目,为有心理疾病的患者提供免费、个性化的音乐疗愈服务。我们可以根据患者和医生的建议,推荐适合的音乐,帮助患者获得更舒适的音乐疗愈体验。 |
| 其他参考文献 | 【1】 【2】 【3】 【4】 |
| 其他参考文献 | 【1】https://github.com/marl/openl3 【2】https://eva.fing.edu.uy/pluginfile.php/524749/mod_folder/content/0/BERT Pre-training of Deep Bidirectional Transformers for Language Understanding.pdf 【3】https://link.springer.com/chapter/10.1007/978-1-4842-6168-2_6 【4】https://blog.csdn.net/weixin_42645636/article/details/135777479 |
| 项目整体介绍 | |
| 本项目旨在开发一个免费公益的音乐播放平台,专门为心理障碍人群提供个性化的音乐推荐服务。通过结合先进的智能推荐算法和心理健康分析技术,我们致力于为用户提供一个能够有效缓解心理压力、舒缓情绪的音乐体验平台。 | |
| 系统概述: |
- 前端
前端部分负责与用户交互,展示推荐结果和用户行为数据。在此项目中,前端将展示歌曲的推荐结果、用户偏好以及推荐算法反馈的数据。用户通过网页或移动端应用提交行为数据(如评分、评论、播放历史等),并接收根据多模态数据推荐的歌曲。前端与后端通过API进行数据交互,确保用户体验的流畅性和响应速度。 - 后端
后端主要负责处理用户请求、管理数据存储、执行推荐算法及特征提取和融合等逻辑。具体实现包括以下几个模块:
特征提取模块:负责从文本(BERT)、图像(ResNet50)、音频(梅尔频谱图、MFCC等)中提取多模态特征。通过并行处理提升性能。
推荐算法模块:结合内容推荐与协同过滤算法,通过加权融合提升推荐的多样性和精准性。
用户偏好建模模块:根据用户的多维度行为(收藏、评分、评论、播放历史)建立偏好模型。
特征融合模块:通过多头注意力机制和线性投影融合音频、图像、文本特征,输出统一的特征向量。
特征存储模块:利用Django ORM进行数据库操作,通过事务确保数据一致性,缓存机制提高特征读取效率。 - 数据库
数据库存储用户行为数据、歌曲信息以及提取的多模态特征。具体包括:
歌曲信息表:存储每首歌曲的基本信息(如歌名、歌手、专辑等)和相关的多模态特征(音频、文本、图像特征)。
用户行为数据表:存储用户的收藏、评分、评论及播放历史。
特征缓存表:存储提取的音频、文本、图像及融合后的特征,使用序列化存储以支持高效的读取和管理。 - AI接口
AI接口主要包含两个部分:
特征提取接口:提供音频、文本和图像特征的提取服务,分别利用预训练的BERT、ResNet50和自定义音频处理模型进行处理。接口通过异步或并行处理提高特征提取的效率。
推荐接口:基于用户行为数据和歌曲特征,提供基于内容推荐和协同过滤推荐的服务。通过加权融合推荐算法,生成最终的推荐列表,返回给前端展示。
5.爬虫
通过爬取千千音乐(https://music.91q.com),解析请求获取API,获取歌曲和歌单相应的信息并存到数据库中。
6.部署平台
使用华为云平台部署系统,保证系统的高可用和稳定性。
个人分工:
我负责主页面的代码编写
点击查看代码
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Favicon icon-->
<link rel="icon" type="image/png" href="/static/image/logo.png">
<!-- Libs CSS -->
<link href="/static/css/bootstrap-icons.css" rel="stylesheet">
<link href="/static/css/dropzone.css" rel="stylesheet">
<link href="/static/css/materialdesignicons.min.css" rel="stylesheet">
<link href="/static/css/prism-okaidia.css" rel="stylesheet">
{% load static %}
{# <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">#}
<!-- Theme CSS -->
<link rel="stylesheet" href="/static/css/theme.min.css">
<title>{% block title %}首页{% endblock %}</title>
</head>
<body class="bg-light">
<div id="db-wrapper">
<!-- navbar vertical -->
<!-- Sidebar -->
<nav class="navbar-vertical navbar">
<div class="nav-scroller">
<!-- Brand logo -->
<a class="navbar-brand" href="">
σσ音乐
</a>
<!-- Navbar nav -->
<ul class="navbar-nav flex-column" id="sideNavbar">
<li class="nav-item">
<a class="nav-link has-arrow" href="http://localhost:8000/admin" target="_blank">
{# <i data-feather="home" class="nav-icon icon-xs me-2"></i> 后台管理#}
<i class="bi bi-cursor-fill nav-icon icon-xs me-2"></i>后台管理
</a>
</li>
<!-- Nav item -->
<li class="nav-item">
<div class="navbar-heading">首页</div>
</li>
<!-- Nav item -->
<li class="nav-item">
<a class="nav-link has-arrow collapsed " href="#!" data-bs-toggle="collapse"
data-bs-target="#navPages" aria-expanded="false" aria-controls="navPages">
<i data-feather="layers" class="nav-icon icon-xs me-2">
</i> 首页
</a>
<div id="navPages" class="collapse " data-bs-parent="#sideNavbar">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link " href="/music/home/">
首页展示
</a>
</li>
<li class="nav-item">
<a class="nav-link has-arrow" href="/music/search/">
音乐搜索
</a>
</li>
</ul>
</div>
</li>
<!-- Nav item -->
<li class="nav-item">
<div class="navbar-heading">个人信息</div>
</li>
<li class="nav-item">
<a class="nav-link has-arrow collapsed " href="#!" data-bs-toggle="collapse"
data-bs-target="#navPagesTwo" aria-expanded="false" aria-controls="navPagesTwo">
<i data-feather="user" class="nav-icon icon-xs me-2">
</i> 个人信息
</a>
<div id="navPagesTwo" class="collapse " data-bs-parent="#sideNavbar">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link " href="/user/editProfile">
修改信息
</a>
</li>
<li class="nav-item">
<a class="nav-link has-arrow " href="/user/editPassword">
修改密码
</a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<div class="navbar-heading">我的功能</div>
</li>
<li class="nav-item">
<a class="nav-link has-arrow collapsed " href="#!" data-bs-toggle="collapse"
data-bs-target="#navPagesTir" aria-expanded="false" aria-controls="navPagesTir">
<i data-feather="aperture" class="nav-icon icon-xs me-2">
</i> 我的功能
</a>
<div id="navPagesTir" class="collapse " data-bs-parent="#sideNavbar">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link" href="/user/collectList">
我的收藏
</a>
</li>
<li class="nav-item">
<a class="nav-link has-arrow" href="/user/historyList">
播放记录
</a>
</li>
</ul>
</div>
</li>
<li class="nav-item">
<div class="navbar-heading">数据图表</div>
</li>
<li class="nav-item">
<a class="nav-link has-arrow collapsed " href="#!" data-bs-toggle="collapse"
data-bs-target="#navPagesFou" aria-expanded="false" aria-controls="navPagesFou">
<i data-feather="trending-down" class="nav-icon icon-xs me-2">
</i> 数据图表
</a>
<div id="navPagesFou" class="collapse " data-bs-parent="#sideNavbar">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link " href="/music/basicData">
基础数据
</a>
</li>
<li class="nav-item">
<a class="nav-link has-arrow" href="/music/typeData">
歌手类型数据
</a>
</li>
<li class="nav-item">
<a class="nav-link has-arrow" href="/music/titleCloud">
歌曲词云图
</a>
</li>
<li class="nav-item">
<a class="nav-link has-arrow" href="/music/singerCloud">
歌手词云图
</a>
</li>
</ul>
</div>
</li>
</ul>
</div>
</nav>
<!-- Page content -->
<div id="page-content">
<div class="header @@classList">
<!-- navbar -->
<nav class="navbar-classic navbar navbar-expand-lg">
<a id="nav-toggle" href="#"><i data-feather="menu" class="nav-icon me-2 icon-xs"></i></a>
<div class="ms-lg-3 d-none d-md-none d-lg-block">
<!-- Form -->
{# <form class="d-flex align-items-center">#}
{# <input type="search" class="form-control" placeholder="Search">#}
{# </form>#}
</div>
<!--Navbar nav -->
<ul class="navbar-nav navbar-right-wrap ms-auto d-flex nav-top-wrap">
<!-- List -->
<li class="dropdown ms-2">
<a class="rounded-circle" href="#" role="button" id="dropdownUser" data-bs-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
<div class="avatar avatar-md avatar-indicators avatar-online">
<img alt="avatar" src="/media/{{ userInfo.avatar }}" class="rounded-circle">
</div>
</a>
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="dropdownUser">
<div class="px-4 pb-0 pt-2">
<div class="lh-1 ">
<h5 class="mb-1">{{ userInfo.username }}</h5>
</div>
<div class=" dropdown-divider mt-3 mb-2"></div>
</div>
<ul class="list-unstyled">
<li>
<a class="dropdown-item" href="/user/editProfile">
<i class="me-2 icon-xxs dropdown-item-icon" data-feather="user"></i>修改个人资料
</a>
</li>
<li>
<a class="dropdown-item" href="/logOut">
<i class="me-2 icon-xxs dropdown-item-icon" data-feather="power"></i>退出登录
</a>
</li>
</ul>
</div>
</li>
</ul>
</nav>
</div>
<!-- Container fluid -->
{% block bg %}
<div class="bg-primary pt-10 pb-21" style="background-color:#f9fafb!important;"></div>
{% endblock %}
<div class="container-fluid mt-n22 px-6">
{% block content %}
<div class="row">
<div class="col-lg-12 col-md-12 col-12">
<!-- Page header -->
<div>
<div class="d-flex justify-content-between align-items-center">
<div class="mb-2 mb-lg-0">
<h3 class="mb-0" style="color: #919eab">首页</h3>
</div>
</div>
</div>
</div>
</div>
<div class="row my-6">
<div class="col-xl-9" style="margin: 0 auto;">
<!-- With Indicators -->
<div id="carouselExampleIndicators" class="carousel slide" data-bs-ride="carousel">
<ol class="carousel-indicators">
<li data-bs-target="#carouselExampleIndicators" data-bs-slide-to="0"
class="active"></li>
<li data-bs-target="#carouselExampleIndicators" data-bs-slide-to="1"></li>
<li data-bs-target="#carouselExampleIndicators" data-bs-slide-to="2"></li>
</ol>
<div class="carousel-inner">
<div class="carousel-item active">
<img src="https://x0.ifengimg.com/ucms/2022_28/EAB96759EAC089A562075159C72C0BFD45D55821_size948_w1268_h714.png"
class="d-block w-100 " alt="...">
</div>
<div class="carousel-item">
<img src="https://puui.qpic.cn/vpic_cover/a35136gvxfw/a35136gvxfw_1683990162_hz.jpg"
class="d-block w-100 " alt="...">
</div>
<div class="carousel-item">
<img src="https://x0.ifengimg.com/ucms/2022_30/FC8354E6F0C8F8498D7A403E1C981C45537FF02F_size30_w683_h383.jpg"
class="d-block w-100 " alt="...">
</div>
</div>
<a class="carousel-control-prev" href="#carouselExampleIndicators" role="button"
data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">上一张</span>
</a>
<a class="carousel-control-next" href="#carouselExampleIndicators" role="button"
data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">下一张</span>
</a>
</div>
</div>
</div>
<style>
.type-container {
display: flex;
align-items: center;
width: 100%;
}
.right-type {
flex-basis: 50px;
}
.left-type {
flex: 1;
}
.type {
border-radius: 40px;
height: 40px;
line-height: 40px;
margin-right: 10px;
padding: 10px 30px;
background: #000;
color: #909399;
}
.type:hover {
color: white;
}
.right-type a {
color: #909399;
cursor: pointer;
font-size: 20px;
display: block;
}
</style>
<div class="row my-6">
<div class="type-container">
<div class="left-type">
{% for type in typeList %}
<a class="type"
href="/music/songSheetList?defaultType={{ type.SongTypeId }}">{{ type.title }}</a>
{% endfor %}
</div>
<div class="right-type"><a href="/music/songSheetList/">更多</a></div>
</div>
</div>
<div class="row my-6">
<div class="recommend_container" style="padding: 0 15px; width: 100%;">
<h2 class="title">音乐推荐</h2>
</div>
<div class="row">
{% for item in recommendList %}
<div class="col-xl-3 col-lg-6 col-md-6" style="margin-bottom: 20px;">
<div class="card">
<img src="{{ item.img }}" style="width: 100%" alt="">
<div class="card-body">
<div class="card-title"><h5><a href="/music/music/{{ item.songId }}"
class="link-info">{{ item.title }}</a>
</h5>
</div>
<div class="card-text">
<div class="text-muted me-2">歌手:{{ item.singer }}</div>
</div>
<div class="card-text">
<div class="text-success">{{ item.type }}</div>
<a href="#" class="link-dark">时长:{{ item.duration }}秒</a>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<div class="row my-6">
<div class="recommend_container" style="padding: 0 15px; width: 100%;">
<h2 class="title">热门歌单</h2>
</div>
<div class="row">
{% for item in HotSongSheetList %}
<div class="col-xl-3 col-lg-6 col-md-6" style="margin-bottom: 20px;">
<!-- 添加了 margin-bottom -->
<div class="card">
<div class="card-body">
<img src="{{ item.img }}" alt=""
style="width: 100%; margin-bottom: 10px;">
<div class="card-title">
<h5><a href="/music/songSheetDetail/{{ item.sheetId }}"
class="link-info">{{ item.title }}</a></h5>
</div>
</div>
<div class="card-footer text-center">
<div class="text-success">歌曲数:{{ item.musicNum }}</div>
<a href="#" class="link-warning">类型:{{ item.song_type.title }}</a>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<div class="row my-6">
<div class="recommend_container" style="padding: 0 15px; width: 100%;">
<h2 class="title">新歌排行榜</h2>
</div>
<div class="card chart-card">
<div class="card-body pd-4">
<div class="chart-holder">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th style="text-align: center; ">排行</th>
<th style="text-align: center; ">歌名</th>
<th style="text-align: center; ">歌手</th>
<th style="text-align: center; ">图片</th>
<th style="text-align: center;">创建时间</th>
</tr>
</thead>
<tbody>
{% for i in TopData10 %}
<tr>
<td style="text-align: center; vertical-align: middle;"><span
style="color: red">{{ i.num }}</span></td>
<td style="text-align: center; vertical-align: middle;">
<a href="/music/music/{{ i.songId }}"
style="text-decoration:none; color: #22223E">{{ i.title }}</a>
</td>
<td style="text-align: center; vertical-align: middle; color: orange">{{ i.singer }}</td>
<td style="text-align: center; vertical-align: middle; width: 120px">
<a href="#">
<img src="{{ i.img }}" style="width: 100%" alt="">
</a>
</td>
<td style="text-align: center; vertical-align: middle;">{{ i.createTime }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{# <div class="row">#}
{# <div class="col-xl-3 col-lg-6 col-md-6">#}
{# <div class="card">#}
{# <img src="/media/avatar/default.png" style="width: 100%" alt="">#}
{# <div class="card-body">#}
{# <div class="card-title"><h5><a href="#" class="link-info">歌曲名称</a></h5></div>#}
{# <div class="card-text">#}
{# <div class="text-muted me-2">歌手:陶喆</div>#}
{# </div>#}
{# <div class="card-text">#}
{# <div class="text-success">R&B</div>#}
{# <a href="#" class="link-dark">时长:3分钟</a>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# <div class="row my-6">#}
{# <div class="recommend_container" style="padding: 0 15px; width: 100%;">#}
{# <h2 class="title">热门歌单</h2>#}
{# </div>#}
{# <div class="row">#}
{# <div class="col-xl-3 col-lg-6 col-md-6">#}
{# <div class="card">#}
{# <div class="card-body">#}
{# <img src="/media/avatar/default.png" alt=""#}
{# style="width: 100%;margin-bottom: 10px;">#}
{# <div class="card-title">#}
{# <h5><a href="#" class="link-info">标题</a></h5>#}
{# </div>#}
{# </div>#}
{# <div class="card-footer text-center">#}
{# <div class="text-success">歌曲数:999</div>#}
{# <a href="#" class="link-warning">类型:R&B</a>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
</div>
</div>
</div>
<!-- Scripts -->
<!-- Libs JS -->
<script src="/static/js/jquery.min.js"></script>
<script src="/static/js/bootstrap.bundle.min.js"></script>
<script src="/static/js/jquery.slimscroll.min.js"></script>
<script src="/static/js/feather.min.js"></script>
<script src="/static/js/prism.js"></script>
<script src="/static/js/apexcharts.min.js"></script>
<script src="/static/js/dropzone.min.js"></script>
<script src="/static/js/prism-toolbar.min.js"></script>
<script src="/static/js/prism-copy-to-clipboard.min.js"></script>
<!-- Theme JS -->
<script src="/static/js/theme.min.js"></script>
{% block script %}
{% endblock %}
</body>
</html>
页面展示






个性化音乐推荐系统项目开发心得
在参与开发“个性化音乐推荐系统”项目的过程中,我不仅加深了对Web开发技术的理解,还对智能推荐算法、数据处理以及用户需求有了更深刻的体会。以下是我在项目开发过程中的一些心得和体会。
- 技术选型与项目架构
1.1 技术选型
在项目初期,我们对技术栈进行了仔细的评估和选择:
前端: 使用HTML、CSS和JavaScript作为基础,结合Bootstrap框架和Font Awesome图标库,快速构建响应式和美观的用户界面。引入Prism和ApexCharts等第三方库,增强了代码展示和数据分析功能。
后端: 选择Django作为后端框架,主要因为其强大的模板引擎和丰富的生态系统,能够快速搭建Web应用。Django的ORM也简化了数据库操作。
数据处理: 使用Python的Pandas和NumPy进行数据清洗和预处理,结合OpenGL、BERT和ResNet-50等深度学习模型进行多模态特征提取。
数据库: 选择MySQL作为数据库管理系统,主要因为其稳定性和广泛的应用场景。
1.2 项目架构
项目采用了典型的MVC(Model-View-Controller)架构:
Model: 定义数据模型,处理数据库操作。
View: 负责渲染用户界面,使用Django模板引擎。
Controller: 处理用户请求,调用Model和View进行数据处理和页面渲染。
这种架构使得项目结构清晰,职责分明,便于开发和维护。
- 数据获取与处理
2.1 数据获取
我们采用了网络爬虫技术从各大音乐平台爬取歌曲和歌单数据。在爬取过程中,我们遇到了以下几个问题:
反爬机制: 一些音乐平台有严格的反爬机制,如IP封禁、验证码验证等。我们通过使用代理IP、设置请求头和频率控制等方法,成功绕过了这些限制。
数据清洗: 爬取到的数据存在格式不统一、缺失值等问题。我们使用Pandas进行数据清洗,填充缺失值,统一数据格式,确保数据质量。
2.2 数据处理
特征提取: 使用OpenGL对音频进行特征提取,BERT对歌词进行语义分析,ResNet-50对图像进行特征提取。不同模态的特征提取方法各有特点,需要根据具体需求进行选择和调整。
数据存储: 将处理后的数据存储到MySQL数据库中,并建立索引,提高查询效率。
3. 推荐算法
3.1 大模型分析
我们接入了大语言模型(如GPT系列)对用户输入进行分析,生成个性化的音乐推荐。大模型能够理解复杂的用户需求和情感表达,但需要大量的计算资源和时间。
3.2 协同过滤算法
结合用户的行为特征(如播放历史、收藏记录、搜索习惯),我们构建了一个协同过滤推荐算法。该算法能够根据相似用户的偏好进行推荐,但存在冷启动问题。
3.3 算法优化
为了提高推荐算法的准确性和效率,我们进行了以下优化:
混合推荐: 将大模型的分析结果与协同过滤算法相结合,既考虑了用户的个性化需求,又利用了群体智慧。
缓存机制: 对频繁访问的数据进行缓存,减少数据库查询次数,提高响应速度。
4. 用户体验
4.1 界面设计
我们注重用户界面的简洁性和易用性,使用Bootstrap框架构建响应式布局,确保在不同设备上都能提供良好的用户体验。
4.2 功能实现
搜索功能: 提供强大的搜索功能,支持关键词搜索、分类筛选等。
播放功能: 实现流畅的音乐播放功能,支持播放、暂停、上一曲、下一曲等操作。
用户交互: 提供收藏、点赞、评论等互动功能,增强用户粘性。
5. 项目管理
5.1 版本控制
我们使用Git进行版本控制,GitHub作为代码托管平台。通过合理的分支管理和代码提交规范,保证了代码的稳定性和可追溯性。
5.2 团队协作
项目团队成员分工明确,定期进行项目进度汇报和讨论,及时解决遇到的问题。通过有效的沟通和协作,保证了项目的顺利进行。
- 未来展望
未来,我们计划在以下几个方面进行改进和优化:
算法优化: 引入更多的推荐算法,如深度学习推荐模型,进一步提高推荐准确性。
数据扩展: 爬取更多的音乐数据,丰富平台资源。
功能扩展: 增加用户个性化设置、音乐推荐理由展示等功能,提升用户体验。
性能优化: 优化代码和数据库查询,提高系统性能。
总结
通过参与这个项目,我不仅掌握了Web开发的基本流程和技巧,还对智能推荐算法有了更深入的理解。在项目开发过程中,我深刻体会到了团队协作的重要性,以及面对问题时的解决思路和方法。这个项目让我受益匪浅,也为今后的学习和工作积累了宝贵的经验。

浙公网安备 33010602011771号