写在前面
| 这个作业属于哪个课程 | |
|---|---|
| 这个作业要求在哪里 | |
| 这个作业的目标 |
GitHub仓库
PSP表格
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | 30 | 40 |
| Estimate | 估计这个任务需要多少时间 | 30 | 30 |
| Development | 开发 | 3600 | 4800 |
| Analysis | 需求分析 (包括学习新技术) | 30 | 40 |
| Design Spec | 生成设计文档 | 30 | 30 |
| Design Review | 设计复审 | 20 | 20 |
| Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
| Design | 具体设计 | 60 | 60 |
| Coding | 具体编码 | 240 | 180 |
| Code Review | 代码复审 | 30 | 30 |
| Test | 测试(自我测试,修改代码,提交修改) | 180 | 200 |
| Reporting | 报告 | 30 | 60 |
| Test Repor | 测试报告 | 20 | 20 |
| Size Measurement | 计算工作量 | 10 | 10 |
| Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 20 | 20 |
| 合计 | 4340 | 5540 |
设计算法
-
设计思路
![流程图]()
-
Python依赖
- jieba
本文使用Python的jieba库对文本进行分词。 - gensim
本文使用Python的gensim库计算文本相似度。
- jieba
-
核心算法
def calc_similarity(text1, text2):
"""
计算余弦相似度
:param text1: 文本1
:param text2: 文本2
:return: 相似度
"""
texts = [text1, text2]
# 建立词袋模型向量化文本
dictionary = gensim.corpora.Dictionary(texts)
corpus = [dictionary.doc2bow(text) for text in texts]
similarity = gensim.similarities.Similarity('-Similarity-index', corpus, num_features=len(dictionary)) # 计算余弦相似度
test_corpus = dictionary.doc2bow(text1) # 将文本转换为bow向量
cosine_sim = similarity[test_corpus][1] # 变量类型为<class 'numpy.float32'>
result = round(cosine_sim.item(), 2) # 转化为<class 'float'>,并取小数点后两位
return result
性能分析
-
改进前
![改进前]()
由于单元测试模块中是调用os.system()方法执行cmd命令,所以上图性能分析图中性能的消耗主要在os.system()上,无法体现出各个模块的具体情况。
-
改进后
![改进后]()
通过分析后得出,对文本进行分词的模块是程序中消耗最大的函数。
单元测试
- 导入Python自带的单元测试模块unittest
- 对给定的测试文件进行测试
- 部分测试代码如下:
import unittest
class Test(unittest.TestCase):
orig_path = "../data/test1/orig.txt"
ans_path = "answer.txt"
def test_dis15_2(self, orig_path=orig_path, ans_path=ans_path):
test_path = "../data/test2/orig_0.8_dis_15.txt"
text1 = main.filter_words(main.read_file(orig_path))
text2 = main.filter_words(main.read_file(test_path))
main.save_answer(ans_path, main.calc_similarity(text1, text2))
main.get_answer(ans_path)
if __name__ == '__main__':
unittest.main()
-
测试覆盖率
![代码覆盖率]()
对代码覆盖结果进行分析,可以得到,未被覆盖代码主要是异常检测部分。
异常处理
-
ValueError
执行main.py时需要传递三个参数(原文文件路径,抄袭文件路径,答案文件),若参数缺失,则会引发ValueError异常,需要对其进行捕获。
![ValueError]()
-
FileNotFoundError
读取的文件不存在是会引发FileNotFoundError异常,需要对其进行捕获。
![FileNotFoundError]()
总结
- 由于是第一次学习对代码进行性能分析和测试,故本次个人编程项目主要的时间花费在学习性能分析工具的使用和测试模块的编写上。
- 算法部分没有做过多优化,选取了最简单的词袋模型,故准确度不够理想,算法仍有改进的空间。






posted on
浙公网安备 33010602011771号