1.项目结构
2.项目需求
1.用户管理模块
2.数据采集模块
3.知识管理模块
4.智能匹配模块
5.个人收藏模块
6.数据分析模块
7.页面展示模块
3.知识点
1.智能匹配模块推荐算法的实现原理
TF (Term Frequency):词频,表示一个词在文档中出现的频率。如果一个词在文档中出现的次数越多,那么它的 TF 值就越大。
IDF (Inverse Document Frequency):逆文档频率,表示一个词的稀有程度。如果一个词在很多文档中都出现过,那么它的 IDF 值就越低,说明这个词的重要性可能不高。IDF 的计算方式是对总文档数目除以包含该词的文档数目,然后取对数。
TF-IDF 的计算方式是将 TF 和 IDF 相乘,以衡量一个词在文档中的重要性。TF-IDF 旨在找出在当前文档中频繁出现,但在整个文集中很少出现的词,这些词可能具有较高的区分度。
接下来,使用 TF-IDF 转换文本内容为特征向量,主要步骤如下:
分词:首先将文本内容进行分词,将其划分为单词或者短语。
计算词频 TF:对于每个词或短语,计算其在文档中出现的频率。
计算逆文档频率 IDF:对于整个文集中的每个词或短语,计算其逆文档频率。
计算 TF-IDF 值:将每个词或短语的 TF 乘以 IDF,得到 TF-IDF 值。
特征向量表示:将每个文档表示为一个向量,其中向量的每个维度对应一个词或短语的 TF-IDF 值。
一旦文本内容被转换为 TF-IDF 特征向量,就可以使用余弦相似度来计算文档之间的相似度。余弦相似度是一种常用的相似度度量方法,计算两个向量之间的余弦值,值越接近1表示两个向量越相似,值越接近0表示两个向量越不相似。在这个场景下,使用余弦相似度可以度量用户收藏的法律文件与所有法律文件之间的相似度,从而找出最相似的法律文件进行推荐。
2.余弦相似度是什么?
余弦相似度是一种用于衡量两个向量之间相似度的方法。在机器学习和信息检索等领域经常会用到余弦相似度来比较文本、图像、音频等数据之间的相似程度。
余弦相似度通常用于处理高维度的数据,特别是文本数据。在文本数据中,每个文档可以表示为一个向量,其中每个维度对应于一个单词,并且向量的值表示该单词在文档中的出现频率或权重。然后可以使用余弦相似度来比较两个文档之间的相似程度。
余弦相似度的计算公式如下:
similarity(𝐴,𝐵)=𝐴⋅𝐵∥𝐴∥∥𝐵∥similarity(A,B)=∥A∥∥B∥A⋅B
其中,𝐴A 和 𝐵B 是两个向量,𝐴⋅𝐵A⋅B 是它们的点积,∥𝐴∥∥A∥ 和 ∥𝐵∥∥B∥ 分别是它们的范数(长度)。
余弦相似度的取值范围在 -1 到 1 之间,当两个向量方向相同时取得最大值1,方向相反时取得最小值-1,如果两个向量正交(垂直),则相似度为0。
在实际应用中,通常将余弦相似度用于计算两个文档之间的相似程度,以便进行文本分类、信息检索、推荐系统等任务。
4.主要代码(部分)
#用户数据分析
def data_analysis(request):if 'user_id' in request.session:user_id = request.session['user_id']# 执行SQL查询with connection.cursor() as cursor:cursor.execute("""SELECT 法律.*FROM 用户收藏INNER JOIN 法律 ON 用户收藏.legal_id = 法律.IDWHERE 用户收藏.user_id = %s""", [user_id])rows = cursor.fetchall()cursor.close()if rows:# 将查询结果转换成DataFramecolumns = ['ID', '标题', '办公室', '发布日期', '到期日期', '类型', '状态', 'URL', '点击量']df = pd.DataFrame(rows, columns=columns)# 统计分析num_collections = len(df)type_counts = df['类型'].value_counts()plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文字体为黑体plt.rcParams['axes.unicode_minus'] = False # 解决负号显示为方块的问题# 可视化分析plt.figure(figsize=(8, 6))type_counts.plot(kind='bar')plt.title('收藏法律文件类型统计')plt.xlabel('文件类型')plt.ylabel('收藏数量')plt.xticks(rotation=45)plt.tight_layout()# 将图表数据转换成base64编码的字符串buffer = io.BytesIO()plt.savefig(buffer, format='png')buffer.seek(0)plot_data = base64.b64encode(buffer.read()).decode('utf-8')plt.close()# 查询时间序列数据with connection.cursor() as cursor:cursor.execute("""SELECT DATE(timestamp) AS date, COUNT(*) AS num_collectionsFROM 用户收藏WHERE user_id = %sGROUP BY DATE(timestamp)ORDER BY DATE(timestamp)""", [user_id])rows = cursor.fetchall()cursor.close()# 将查询结果转换成DataFramecolumns = ['date', 'num_collections']time_series_df = pd.DataFrame(rows, columns=columns)# 时间序列可视化分析plt.figure(figsize=(10, 6))plt.plot(time_series_df['date'], time_series_df['num_collections'], marker='o', linestyle='-')plt.title('收藏数量随时间变化趋势')plt.xlabel('日期')plt.ylabel('收藏数量')plt.xticks(rotation=45)plt.tight_layout()# 将时间序列图表数据转换成base64编码的字符串buffer = io.BytesIO()plt.savefig(buffer, format='png')buffer.seek(0)time_series_plot_data = base64.b64encode(buffer.read()).decode('utf-8')plt.close()# 查询与当前用户共享收藏的其他用户数量with connection.cursor() as cursor:cursor.execute("""SELECT COUNT(DISTINCT user_id) AS shared_usersFROM 用户收藏WHERE legal_id IN (SELECT legal_idFROM 用户收藏WHERE user_id = %s)AND user_id != %s""", [user_id, user_id])shared_users_count = cursor.fetchone()[0]cursor.close()# 将统计分析和时间序列分析的结果和图表数据传递给模板context = {'num_collections': num_collections,'type_counts': type_counts,'plot_data': plot_data,'time_series_plot_data': time_series_plot_data,'shared_users_count': shared_users_count,}return render(request, 'data_analysis.html', context)else:return render(request, 'data_analysis.html', context = {'num_collections': '','type_counts': '','plot_data': '','time_series_plot_data': '','shared_users_count': '',})else:return render(request, 'login.html')
def user_management(request):if 'user_id' in request.session:if request.method == 'POST':email = request.POST.get('email')new_password = request.POST.get('new_password')user_id = request.session['user_id']# 检查用户输入的邮箱是否存在于数据库中try:user = User.objects.get(email=email,id=user_id)except User.DoesNotExist:return render(request, 'user_management.html', {'error_message': 'Invalid email'})# 更新用户密码为新密码user.password = new_passworduser.save()return render(request, 'user_management.html', {'reset_password_sent': True})else:return render(request, 'user_management.html')else:return render(request, 'login.html')
5.运行效果
6.遇到问题及总结:
1.特别多的问题,例如前端获取不到数据给后端,ajax传递数据老是报错,
2.学会了很多,例如模态框,数据大屏,推荐算法等等