ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Django+MySQL文本相似度系统毕设实战指南

Django+MySQL文本相似度系统毕设实战指南

简介:本资源是一份面向计算机专业本科生的毕业设计文档,聚焦Python文本相似度计算系统的设计与实现,适用于自然语言处理入门学习、课程设计及毕设参考。文档完整覆盖系统需求分析、技术选型(Python+Django+MySQL)、核心模块实现(文本清洗、NLTK/spaCy分词、TF-IDF关键词提取、余弦相似度算法原理与代码逻辑)、可视化界面说明及实验评估结果,内容兼具理论深度与工程落地性。资源为单个749KB的Word文档(.docx),结构清晰,含中英文摘要、目录、六章正文(含绪论、可行性分析、系统设计、实现细节、测试结果与展望)及规范参考文献,可直接用于开题汇报、论文撰写与答辩材料整理。目前已有138人学习下载,读者可快速掌握NLP基础任务的全流程实现思路,并复用其中的预处理策略、向量构建方法与相似度计算模板。

1. 为什么一个“只算两段话像不像”的系统,要搭 Django + MySQL + 词向量表三件套?

这不是小题大做,而是我带过三个文本类毕设后踩出的血泪经验:学生交的“能跑通余弦相似度.py”,答辩时被问一句“如果用户明天要查1000篇新闻和他输入的标题匹配度,你这单文件脚本怎么接?”当场哑火。
真正能落地、能答辩、能写进“系统设计”章节的文本相似度方案,必须回答三个硬问题:第一,文本来了怎么存——不能每次运行都重分词、重算TF-IDF;第二,算法选了不止一种(余弦/Jaccard/编辑距离),怎么让用户点一下就切,而不是改代码再重启;第三,结果不是打印在控制台,而是要让老师在浏览器里输两段话、点按钮、看进度条、见柱状图、导出Excel。
所以这份基于 Python 的文本相似度计算系统,本质是一个「可存、可切、可展」的最小可行 Web 系统:用 Django 撑起用户入口和路由调度,用 MySQL 固化预处理结果与历史记录,用 jieba+sklearn 构建可复用的向量化流水线——它不追求 SOTA 模型,但保证从“同学A交作业”到“导师B部署试用”之间,没有断层。适合计算机/软件工程专业做毕设或课设,尤其当你被要求写“数据库设计”“模块划分”“测试用例”时,这套结构能直接填满第四章、第五章、第六章的全部骨架。


2. 总体架构设计:B/S 三层结构与四个核心模块的职责边界

这个系统不是“Python 脚本 + Flask 临时凑个网页”,而是按工业级 Web 系统逻辑拆解的四层责任链:用户触达层 → 业务调度层 → 算法执行层 → 数据持久层。每一层只干一件事,改算法不影响前端,换数据库不碰分词逻辑。下面这张表不是画给老师看的示意图,而是你写“4.1 系统模块总体设计”时可以直接抄的职责说明书:

模块名称所属层级核心职责交付物示例(答辩可展示)
Web 交互模块用户触达层渲染 HTML 页面、校验输入长度、发起 Ajax 请求、接收 JSON 响应、绘制 ECharts 柱状图templates/similarity_input.html中的双文本框+下拉选择器
任务调度模块业务调度层解析 HTTP 请求参数、判断使用哪种相似度算法、调用对应算法类、组装返回字典views.py中calculate_similarity()视图函数
算法引擎模块算法执行层封装预处理、向量化、相似度计算三步逻辑,每个算法(余弦/Jaccard/编辑距离)独立成类algorithms/cosine_calculator.py中的CosineCalculator类
数据服务模块数据持久层管理 MySQL 表结构、缓存向量化结果、记录用户查询日志、支持按日期导出历史记录models.py中SimilarityRecord模型定义及迁移文件

提示:很多同学把“算法模块”写成一坨if-elif-else堆在视图里,这是答辩翻车高发区。正确做法是——算法必须封装为独立类,且每个类只依赖numpy和sklearn,不 importdjango.db或requests。这样未来换成 FastAPI 或迁移到微服务,只需替换调度层,算法层代码一行不用动。

2.1 Web 交互模块:用 Bootstrap + Django Forms 实现零 JS 编码的表单

别被“可视化界面”吓住。本系统所有前端交互,靠 Django 自带的 Form 机制 + Bootstrap CSS 就能闭环,无需手写一行 JavaScript。关键在于理解 Django Forms 如何把“用户输入”变成“可控对象”:

# forms.py from django import forms class TextCompareForm(forms.Form): text_a = forms.CharField( label="文本A", widget=forms.Textarea(attrs={ 'class': 'form-control', 'rows': 4, 'placeholder': '请输入第一段待比较文本(支持中文)' }) ) text_b = forms.CharField( label="文本B", widget=forms.Textarea(attrs={ 'class': 'form-control', 'rows': 4, 'placeholder': '请输入第二段待比较文本' }) ) algorithm = forms.ChoiceField( label="选择算法", choices=[ ('cosine', '余弦相似度'), ('jaccard', 'Jaccard 相似度'), ('edit', '编辑距离(归一化)') ], widget=forms.Select(attrs={'class': 'form-control'}) )

这段代码生成的 HTML,自带 Bootstrap 样式、响应式栅格、必填校验(Django 默认校验空值)、CSRF 保护({% csrf_token %})。你只需要在模板里写:

<!-- templates/similarity_input.html --> <form method="post"> {% csrf_token %} {{ form.as_p }} <!-- 自动渲染所有字段为 <p> 包裹的 label+input --> <button type="submit" class="btn btn-primary">开始计算</button> </form>

设计说明:

  • as_p是最省事的渲染方式,它把每个字段转成<p><label>...<input>...</p>,Bootstrap 的.form-control类会自动适配宽度和圆角;
  • placeholder不是装饰,而是降低用户输入门槛的关键——毕设答辩时老师随手输入“人工智能发展很快”和“AI技术进步迅猛”,你得确保系统能接住这种非标准输入;
  • algorithm字段用ChoiceField而非CharField,是为了后续在视图中直接form.cleaned_data['algorithm']拿到字符串'cosine',避免手动解析下拉框 value。

2.2 任务调度模块:视图函数如何成为算法与 Web 的“翻译官”

Django 视图不是“写业务逻辑的地方”,而是“协议转换器”:它把 HTTP 请求(GET/POST 参数)翻译成算法能懂的 Python 对象,再把算法返回的数字结果翻译成 JSON 或渲染模板。以下是views.py中最核心的调度函数,也是你写“5.1.2 文本相似度计算模块”时的范本:

# views.py from django.shortcuts import render from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt from .forms import TextCompareForm from .algorithms.cosine_calculator import CosineCalculator from .algorithms.jaccard_calculator import JaccardCalculator from .algorithms.edit_distance_calculator import EditDistanceCalculator from .models import SimilarityRecord def calculate_similarity(request): if request.method == 'POST': form = TextCompareForm(request.POST) if form.is_valid(): # 1. 提取清洗后的原始文本 text_a = form.cleaned_data['text_a'].strip() text_b = form.cleaned_data['text_b'].strip() algo_name = form.cleaned_data['algorithm'] # 2. 根据算法名实例化对应计算器 calculator_map = { 'cosine': CosineCalculator(), 'jaccard': JaccardCalculator(), 'edit': EditDistanceCalculator() } calculator = calculator_map[algo_name] # 3. 执行计算(内部已包含预处理) try: similarity_score = calculator.calculate(text_a, text_b) except Exception as e: return render(request, 'error.html', {'message': f'计算失败:{str(e)}'}) # 4. 保存记录到 MySQL(可选,但毕设加分项) SimilarityRecord.objects.create( text_a=text_a[:200], # 防止超长文本撑爆字段 text_b=text_b[:200], algorithm=algo_name, score=round(similarity_score, 4), created_at=timezone.now() ) # 5. 返回渲染结果(非 AJAX 场景) return render(request, 'result.html', { 'text_a': text_a, 'text_b': text_b, 'algorithm': dict(form.fields['algorithm'].choices)[algo_name], 'score': similarity_score, 'interpretation': get_score_interpretation(similarity_score) }) else: form = TextCompareForm() return render(request, 'similarity_input.html', {'form': form})

参数说明与设计逻辑:

  • form.is_valid()是安全底线:它自动校验文本非空、长度不超过max_length(你可在 Form 中设置),比手写if not text_a:可靠十倍;
  • calculator_map字典是解耦关键:新增算法(比如明年加 BM25)只需写新类、加字典项,不碰调度逻辑;
  • SimilarityRecord.objects.create()这行代码,就是你写“数据库设计”章节的实物证据——它证明你真用了 MySQL,不是口头说说;
  • get_score_interpretation()是答辩亮点函数(见后文),把 0.82 这种数字翻译成“高度相似”,让老师一眼看懂结果价值。

2.3 算法引擎模块:为什么预处理必须和相似度计算捆在一起?

很多毕设代码把“分词”“去停用词”“向量化”写在视图里,导致同一个文本每次请求都重复计算。而本系统强制规定:每个算法类的calculate()方法,必须内部完成“原始文本→清洗→分词→向量化→相似度计算”全链路。以CosineCalculator为例:

# algorithms/cosine_calculator.py import jieba import numpy as np from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.metrics.pairwise import cosine_similarity class CosineCalculator: def __init__(self): # 初始化停用词表(实际项目应从文件读取) self.stopwords = {'的', '了', '在', '是', '我', '有', '和', '就', '不', '人', '都', '一', '一个'} def _preprocess(self, text): """内部预处理:清洗 + 分词 + 去停用词""" # 清洗:只保留中文、英文字母、数字、空格 cleaned = ''.join([c for c in text if c.isalnum() or c.isspace() or '\u4e00' <= c <= '\u9fff']) # 分词 words = jieba.lcut(cleaned) # 去停用词 & 过滤单字(提升效果) filtered = [w for w in words if w not in self.stopwords and len(w) > 1] return ' '.join(filtered) def calculate(self, text_a, text_b): """主计算方法:端到端输出相似度""" # 1. 预处理两段文本 processed_a = self._preprocess(text_a) processed_b = self._preprocess(text_b) # 2. TF-IDF 向量化(注意:必须用同一 vectorizer 对两文本向量化) vectorizer = TfidfVectorizer() tfidf_matrix = vectorizer.fit_transform([processed_a, processed_b]) # 3. 计算余弦相似度 similarity_matrix = cosine_similarity(tfidf_matrix[0:1], tfidf_matrix[1:2]) return float(similarity_matrix[0][0])

为什么这么设计?

  • _preprocess()私有方法封装所有脏活,calculate()方法签名干净(只接受原始文本,返回浮点数),方便单元测试;
  • TfidfVectorizer在calculate()内部创建,而非__init__中——因为毕设场景文本量小,无需全局缓存;若未来扩展为百万文档库,则需升级为vectorizer单例 +pickle序列化;
  • float(similarity_matrix[0][0])强制转为 Python 原生 float,避免numpy.float64导致 JSON 序列化报错(这是答辩现场调试 30 分钟才发现的玄学坑)。

2.4 数据服务模块:MySQL 表结构如何支撑“可追溯、可统计”的毕设需求

毕设论文里写“采用 MySQL 数据库存储”,不能只停留在这句话。你必须给出真实可用的表结构,且该结构要支撑两类刚需:一是记录每一次计算行为(供老师抽查验证),二是支持按月导出使用报告(体现系统价值)。models.py定义如下:

# models.py from django.db import models from django.utils import timezone class SimilarityRecord(models.Model): """文本相似度计算历史记录表""" text_a = models.CharField(max_length=500, verbose_name="文本A(前200字)") text_b = models.CharField(max_length=500, verbose_name="文本B(前200字)") algorithm = models.CharField( max_length=20, choices=[ ('cosine', '余弦相似度'), ('jaccard', 'Jaccard 相似度'), ('edit', '编辑距离') ], verbose_name="使用算法" ) score = models.DecimalField( max_digits=5, decimal_places=4, verbose_name="相似度得分" ) created_at = models.DateTimeField( default=timezone.now, verbose_name="创建时间" ) class Meta: db_table = 'similarity_record' verbose_name = "相似度记录" verbose_name_plural = "相似度记录" ordering = ['-created_at'] # 默认按时间倒序 def __str__(self): return f"{self.text_a[:10]}... vs {self.text_b[:10]}... = {self.score}"

生成迁移文件并同步数据库的命令(写进你的“部署说明.md”):

python manage.py makemigrations python manage.py migrate

这张表解决的实际问题:

  • text_a/text_b字段限制 500 字,是因为 MySQLVARCHAR(500)足够存摘要,又避免TEXT类型影响查询性能;
  • score用DecimalField而非FloatField,确保 0.9250 这种值不变成 0.9249999999999999(答辩时老师放大截图看小数位,这是细节可信度);
  • ordering = ['-created_at']让 Django Admin 后台默认显示最新记录,你演示时不用手动排序。

3. 关键实现细节:从分词策略到向量降维的 5 个落地决策点

教科书讲“jieba 分词”,但没告诉你:中文分词不是开箱即用,而是要根据你的文本类型调参。比如你用新闻语料测试,jieba.cut("苹果公司发布了新款iPhone")默认切成['苹果', '公司', '发布', '了', '新款', 'iPhone'],但“苹果公司”作为实体被拆开,相似度计算必然失真。本系统在实现中做了 5 个关键决策,每一条都对应毕设报告里的“设计依据”章节。

3.1 分词引擎选型:jieba 精确模式 + 自定义词典的必要性

jieba有三种模式:精确模式(默认)、全模式、搜索引擎模式。毕设必须用精确模式 + 自定义词典,原因如下:

场景精确模式(无词典)精确模式(加词典)为什么选后者
输入:“深度学习模型训练很耗时”['深度', '学习', '模型', '训练', '很', '耗时']['深度学习', '模型', '训练', '很', '耗时']“深度学习”是固定术语,拆开后 TF-IDF 权重分散
输入:“COVID-19 疫情”['CO', 'VID', '-', '19', '疫情']['COVID-19', '疫情']英文缩写必须整体识别,否则向量空间错乱

落地代码(algorithms/base_calculator.py):

import jieba # 加载自定义词典(实际项目放于 data/dict.txt,每行一个词) custom_words = [ '深度学习', '机器学习', '自然语言处理', 'ChatGPT', 'Transformer', 'COVID-19', 'SARS-CoV-2', '人工智能', '大数据', '云计算' ] for word in custom_words: jieba.add_word(word) class BaseCalculator: def _cut_with_jieba(self, text): return jieba.lcut(text) # lcut 返回列表,比 cut() 更稳定

注意:jieba.add_word()必须在项目启动时执行一次(如放于apps.py的ready()方法),不能在每次calculate()中重复调用,否则性能暴跌。

3.2 停用词表构建:为什么不能直接用 NLTK 的英文停用词?

中文停用词表必须定制。NLTK 的stopwords.words('chinese')只有 100 多个词,且含大量古汉语词(如“之乎者也”),对现代新闻/论文文本无效。本系统采用三级停用词过滤:

  1. 基础停用词(189 个):来自哈工大停用词表精简版,覆盖“的、了、在、是、我、有、和、就、不、人”等高频虚词;
  2. 标点符号:正则re.sub(r'[^\w\s\u4e00-\u9fff]', ' ', text)全局清理;
  3. 业务停用词(动态添加):如你处理的是医疗文本,可额外加入“患者”“医生”“治疗”等泛化词,避免它们主导向量。

停用词过滤代码(接续CosineCalculator._preprocess):

def _remove_stopwords(self, words): # 基础停用词(硬编码,确保离线可用) base_stops = {'的', '了', '在', '是', '我', '有', '和', '就', '不', '人', '都', '一', '一个', '上', '也', '很', '到', '说', '要', '去', '你', '会', '着', '没有', '看', '好', '自己', '这'} # 业务停用词(按需扩展) biz_stops = {'详见', '如下', '因此', '综上所述', '总而言之'} # 新闻/论文常见冗余短语 all_stops = base_stops | biz_stops return [w for w in words if w not in all_stops and len(w) > 1]

3.3 向量化方案:TF-IDF 为何比 Word2Vec 更适合毕设场景?

搜索“文本相似度算法”,你会看到 Word2Vec、BERT、Sentence-BERT 等炫酷名词。但毕设必须选TF-IDF + 余弦相似度,理由铁硬:

维度TF-IDF + 余弦Word2Vec / BERT毕设适配性
环境依赖scikit-learn单包,pip install5 秒搞定Word2Vec 需gensim+ 预训练模型(300MB+),BERT 需transformers+ GPU你答辩用的笔记本可能没 GPU,也没外网下模型
可解释性每个维度对应一个词,vectorizer.get_feature_names_out()可打印全部词汇向量是黑匣子,无法告诉老师“为什么‘人工智能’和‘AI’相似度高”答辩时老师问“这个向量怎么来的?”,你得指着屏幕说清楚
计算速度1000 篇新闻向量化 < 2 秒(CPU)Word2Vec 训练需分钟级,BERT 单句编码 > 1 秒/句毕设演示要求“秒出结果”,不能让老师等进度条

TF-IDF 参数调优实战(CosineCalculator.calculate内部):

vectorizer = TfidfVectorizer( max_features=5000, # 限制最多 5000 个特征词,防内存爆炸 ngram_range=(1, 2), # 启用 1-gram 和 2-gram(捕获“深度学习”这种双词) min_df=2, # 词频<2 的词直接丢弃(过滤拼写错误/噪声) max_df=0.95 # 出现在 >95% 文档的词丢弃(如“的”“了”) )

3.4 相似度算法对比:为什么编辑距离要“归一化”才能和余弦值横向比较?

系统提供三种算法,但它们的数值范围天差地别:

  • 余弦相似度:[-1.0, 1.0],通常[0.0, 1.0];
  • Jaccard 相似度:[0.0, 1.0];
  • 编辑距离:原始值是整数(如 5),表示最少修改次数,必须归一化为[0.0, 1.0]才能放入同一张结果页。

归一化公式与代码(edit_distance_calculator.py):

import Levenshtein class EditDistanceCalculator: def calculate(self, text_a, text_b): # 原始编辑距离 distance = Levenshtein.distance(text_a, text_b) # 归一化:1 - distance / max_len,确保值域 [0,1] max_len = max(len(text_a), len(text_b)) if max_len == 0: return 1.0 # 两空串完全相同 normalized = 1.0 - (distance / max_len) return max(0.0, min(1.0, normalized)) # 强制截断到 [0,1]

设计说明:Levenshtein.distance比difflib.SequenceMatcher更准,且python-Levenshtein包是 C 实现,速度比纯 Python 快 10 倍。安装命令:pip install python-Levenshtein。

3.5 结果可视化:用 ECharts 画柱状图,但只传 JSON 不传 HTML

很多同学把 ECharts 代码全写在 HTML 里,导致图表逻辑和业务逻辑混杂。正确做法是:后端只返回 JSON 数据,前端用原生 JS 渲染。这样你写“系统测试”章节时,可以单独测views.py的 JSON 输出,不依赖前端。

后端返回 JSON(修改calculate_similarity视图):

# 替换原来的 render(...) 为: return JsonResponse({ 'success': True, 'data': { 'text_a': text_a[:50] + '...' if len(text_a) > 50 else text_a, 'text_b': text_b[:50] + '...' if len(text_b) > 50 else text_b, 'algorithm': dict(form.fields['algorithm'].choices)[algo_name], 'score': round(similarity_score, 4), 'interpretation': get_score_interpretation(similarity_score) } })

前端渲染代码(templates/result.html):

<div id="chart" style="width: 600px; height: 400px;"></div> <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script> <script> fetch('/calculate/', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({/* 表单数据 */}) }) .then(r => r.json()) .then(data => { const chartDom = document.getElementById('chart'); const myChart = echarts.init(chartDom); const option = { title: { text: `相似度分析结果:${data.data.algorithm}` }, tooltip: {}, xAxis: { data: ['相似度'] }, yAxis: {}, series: [{ name: '得分', type: 'bar', data: [data.data.score], itemStyle: { color: data.data.score > 0.7 ? '#52c418' : data.data.score > 0.4 ? '#faad14' : '#f5222d' } }] }; myChart.setOption(option); }); </script>

为什么这么做?

  • fetchAPI 是现代浏览器标配,无需 jQuery,减少依赖;
  • itemStyle.color根据分数变色(>0.7 绿,0.4~0.7 黄,<0.4 红),让老师一眼看出质量;
  • 图表宽高写死600x400,避免响应式导致答辩时布局错乱。

4. 常见问题排查:毕设开发中 5 个最高频翻车点与解法

别等答辩前一天才 debug。这 5 个问题,是我帮 A 同学、B 同学、C 同学救火时总结的“必现坑”,按出现频率排序,每一条都附真实报错和修复命令。

4.1 现象:页面提交后报MultiValueDictKeyError at /calculate/

原因:Django 表单字段名和视图中request.POST.get()的 key 不一致。例如表单定义text_a,但视图写了request.POST.get('text1')。
解决:

  • 检查forms.py中字段名(如text_a);
  • 检查views.py中form.cleaned_data['text_a']的 key 是否完全一致(大小写、下划线);
  • 终极验证:在视图开头加print(request.POST),看实际提交的 key 是什么。

4.2 现象:计算结果全是0.0或nan

原因:TF-IDF 向量化时,两段文本预处理后变成空字符串(如全被停用词过滤掉),TfidfVectorizer对空输入返回全零向量,余弦相似度为0/0 = nan。
解决:

  • 在_preprocess()后加防御性检查:
    processed_a = self._preprocess(text_a) processed_b = self._preprocess(text_b) if not processed_a or not processed_b: raise ValueError("预处理后文本为空,请检查输入内容及停用词表")
  • 或在calculate()开头加兜底:
    if processed_a == processed_b == '': return 1.0 # 两空串视为完全相同

4.3 现象:MySQL 报错1071 Specified key was too long

原因:Django 默认为CharField创建VARCHAR(255)索引,但 MySQL utf8mb4 字符集下,255 字符 * 4 字节 = 1020 字节 > InnoDB 索引最大 767 字节。
解决:

  • 修改models.py中字段定义,显式指定db_index=False(不需要索引的字段):
    text_a = models.CharField(max_length=500, db_index=False) text_b = models.CharField(max_length=500, db_index=False)
  • 或在数据库层面调大innodb_large_prefix(不推荐,毕设环境难操作)。

4.4 现象:中文在网页显示为?????或乱码

原因:MySQL 数据库、数据表、连接三者字符集不统一。Django 默认用utf8,但 MySQL 8.0+ 推荐utf8mb4。
解决:

  • 创建数据库时指定字符集:
    CREATE DATABASE text_similarity DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  • Djangosettings.py中配置:
    DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'text_similarity', 'OPTIONS': { 'charset': 'utf8mb4', }, } }
  • 执行python manage.py dbshell进入 MySQL,运行:
    ALTER DATABASE text_similarity CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;

4.5 现象:pip install jieba成功,但运行时报ModuleNotFoundError: No module named 'jieba'

原因:PyCharm/VSCODE 使用了错误的 Python 解释器(如系统 Python 而非项目虚拟环境)。
解决:

  • 终端进入项目根目录,确认激活虚拟环境:
    source venv/bin/activate # Linux/Mac # 或 venv\Scripts\activate # Windows
  • 运行which python(Linux/Mac)或where python(Windows),确认路径含venv;
  • 在 IDE 设置中,将 Python Interpreter 指向venv/bin/python(Linux/Mac)或venv\Scripts\python.exe(Windows)。

5. 答辩验收指南:从“能跑”到“能讲”的 4 个必做动作

答辩不是代码审查,而是价值传递。老师不会逐行看你jieba.lcut()写得对不对,但会盯着你演示时的每一个操作,判断:“这学生真懂设计,还是只会 Ctrl+C/V?”。以下 4 个动作,是我带过的毕设中,100% 被老师追问、且 90% 学生答不全的核心验收点。做完它们,你的答辩通过率从 70% 拉到 95%。

5.1 动作一:准备三组“有故事”的测试用例,覆盖算法差异

别用“今天天气很好”和“明天阳光明媚”这种弱对比。准备三组能讲出技术逻辑的输入,每组配一句解释:

测试组文本A文本B预期现象与解释答辩话术
同义词组“人工智能正在改变世界”“AI技术正在重塑全球格局”余弦相似度 > 0.6,Jaccard 较低(因“人工智能”vs“AI”被当不同词)“这里体现了 TF-IDF 对同义词的捕捉能力,而 Jaccard 严格匹配字面,说明我们提供多算法是必要的”
长短文本“深度学习”“深度学习是机器学习的一个分支,它通过多层神经网络模拟人脑处理信息的方式……(200字)”余弦相似度 ≈ 0.85(因共享关键词),编辑距离归一化值 ≈ 0.1(因长度悬殊)“编辑距离擅长短文本,TF-IDF 更适应长短不一的文档,这正是我们设计多算法切换的意义”
对抗样本“苹果手机很好用”“苹果是一种水果,富含维生素C”所有算法得分 < 0.3,尤其余弦相似度接近 0(因“苹果”在两文中语义完全不同,TF-IDF 无法消歧)“这暴露了传统方法的局限性,也引出了未来可结合 BERT 等上下文感知模型的方向——这正是我在‘展望’章节提到的”

实操建议:把这三组数据存在test_cases.txt文件里,答辩时直接复制粘贴,避免手打出错。老师让你现场演示,你就说:“我准备了典型场景,现在为您展示第三组对抗样本……”

5.2 动作二:导出一份“本月使用报告”,证明系统不是玩具

毕设系统最大的信任危机是:“这东西真有人用吗?”。解决方案:用 Django Admin 或写个简易脚本,导出一张 Excel 表,标题就叫《2024年X月文本相似度系统使用报告》。内容必须包含:

日期文本A(摘要)文本B(摘要)算法得分备注
2024-05-01人工智能发展…AI技术进步…余弦相似度0.82同义词匹配成功
2024-05-02苹果手机…苹果是一种水…编辑距离0.15语义歧义检测

生成脚本(export_report.py):

import pandas as pd from datetime import datetime, timedelta from myapp.models import SimilarityRecord # 查询本月数据 start_date = datetime.now().replace(day=1) end_date = start_date + timedelta(days=31) records = SimilarityRecord.objects.filter( created_at__range=(start_date, end_date) ).values('created_at', 'text_a', 'text_b', 'algorithm', 'score') df = pd.DataFrame(list(records)) df['created_at'] = df['created_at <p> <a href="https://download.csdn.net/download/2301_78021017/88891558" style="color:#ec7500;font-size:14px;"> 本文还有配套的精品资源,点击获取 </a> <img alt="menu-r.4af5f7ec.gif" src="https://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif" style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;"> </p>
返回列表