个人项目:论文查重

这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/Networkengineering1834
----------------- ---------------
这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/Networkengineering1834/homework/11146
这个作业的目标 学会使用PSP表格规划项目各步骤开发时间,学习Git commit规范,使用Git管理代码

一、github仓库地址:

https://github.com/smietao/smietao/tree/master/3118005337/checkPaperRepeat

二、PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 30 25
· Estimate 估计这个任务需要多少时间 15 20
Development 开发 360 460
· Analysis 需求分析 (包括学习新技术) 120 180
· Design Spec 生成设计文档 40 50
· Design Review 设计复审 20 20
· Coding Standard 代码规范 (为目前的开发制定合适的规范) 10 10
· Design 具体设计 60 60
· Coding 具体编码 150 200
· Code Review 代码复审 60 30
· Test 测试(自我测试,修改代码,提交修改) 60 60
Reporting 报告 150 200
·Test Report 测试报告 90 150
·Size Measurement 计算工作量 10 10
·Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 10 20
Total 合计 1185 1495

三、算法设计

3.1 算法思路

这次使用的是比较简单的算法——直接用jieba分词,并计算各个词的TF-IDF值(停用词表采用的是jieba自带的,TF-IDF语料库也是采用jieba自带的),再用TF-IDF值构造词向量,最后计算余弦相似度。

TF-IDF参考阮一峰老师的两篇博客:

3.2 流程图

个人项目:论文查重

四、计算模块的设计以及实现过程

4.1 项目结构体系

个人项目:论文查重

其中APP为主启动类,main方法在其中;keyword包下是分词类以及计算TF-IDF值的类;util包下是读取文本和计算余弦相似度的工具类;共计五个类。

4.2 类调用关系

App类首先调用ReadTxt类读取txt文件中的内容,将其转化为String类型的字符串。之后使用TFIDFAnalyzer类的analyze方法进行分词操作,将结果封装成List<KeyWord>集合。最后将两个List集合传入CalculateCosSim类的静态方法calculateCosineSimilarity计算余弦相似度,最后通过IO流将结果输出到指定路径的txt文件中。

4.3 算法关键

  1. jieba分词
  2. 计算关键词词频
  3. 循环找到相同的关键词
  4. 利用余弦相似度公式计算结果

五、计算模块接口部分的性能改进

for (Keyword oriKeyword : originalList) {
    for (Keyword plaKeyword : plagiarizeList) {
        if (oriKeyword.getName().equals(plaKeyword.getName())) {
            double oriTfidfvalue = oriKeyword.getTfidfvalue();
            double plaTfidfvalue = plaKeyword.getTfidfvalue();
            // 如果高频词相等,计算
            v1 += oriTfidfvalue * oriTfidfvalue;
            v2 += plaTfidfvalue * plaTfidfvalue;
            v += oriTfidfvalue * plaTfidfvalue;
            // 计算完后跳出内层循环,找下一个词
            break;
        }
    }
}

在使用foreach循环找到了高频词后通过break跳出循环,避免了多余的循环计算。

六、计算模块部分单元测试展示

6.1 单元测试框架:Junit5

6.2 单元测试结果(仅展示部分)

  1. 分词测试

    @Test
    public void testTfidfAnalyzer() {
        String content = "今天是星期天,天气晴,今天晚上我要去看电影";
        // 定义关键词个数
        int topN = 5;
        // 提取文章中的20个关键词和词频
        TFIDFAnalyzer tfidfAnalyzer = new TFIDFAnalyzer();
        List<Keyword> keywordList = tfidfAnalyzer.analyze(content, topN);
        if (keywordList != null && keywordList.size() != 0) {
            for (Keyword keyword : keywordList) {
                System.out.println("关键词为【" + keyword.getName() + "】,词频为【" + keyword.getTfidfvalue() + "】");
            }
        }
    }
    

    测试结果:

    个人项目:论文查重

  2. txt文件读取转化为String字符串测试

    @Test
    public void testTxtRead() {
        File orgFile = new File("D:/org.txt");
        // 读取txt文件中的内容 转化为String类型
        String original = ReadTxt.txt2String(orgFile).trim();
        System.out.println(original);
    }
    

    测试结果:

    个人项目:论文查重

  3. 余弦相似度计算测试:

    @Test
    public void testCalculate() {
        String original = "今天是星期天,天气晴,今天晚上我要去看电影";
        String plagiarize = "今天是周天,天气晴朗,我晚上要去看电影";
        // 定义关键词个数
        int topN = 5;
        // 提取文章中的5个关键词和词频
        TFIDFAnalyzer tfidfAnalyzer = new TFIDFAnalyzer();
        List<Keyword> originalList = tfidfAnalyzer.analyze(original, topN);
        List<Keyword> plagiarizeList = tfidfAnalyzer.analyze(plagiarize, topN);
        Double repetitiveRate = CalculateCosSim.calculateCosineSimilarity(originalList, plagiarizeList);
        System.out.println("两段文本的余弦相似度为:" + repetitiveRate);
    }
    

    测试结果:

    个人项目:论文查重

  4. 代码覆盖率

    个人项目:论文查重

七、计算模块部分异常处理说明

public class CustomException extends RuntimeException {
    
    private String message;
    
    public CustomException(String message) {
        this.message = message;
    }
    
    @Override
    public String getMessage() {
        return message;
    }
    
    public void setMessage(String message) {
        this.message = message;
    }
}

自定义运行时异常,在计算模块部分两个地方抛出:

  1. 命令行参数不是预期的三个

    int length = args.length;
    if (length != 3) {
        // 参数不是三个,说明命令入参错误
        throw new CustomException("命令行入参数量有误!");
    }
    

    个人项目:论文查重

  2. 读取的文本内容为空

    if (original.length() == 0) {
        throw new CustomException("原文文本内容为空!");
    }
    if (plagiarize.length() == 0) {
        throw new CustomException("抄袭文文本内容为空!");
    }
    

    个人项目:论文查重

八、性能分析

8.1 内存、垃圾回收、类、线程的使用情况

个人项目:论文查重

个人项目:论文查重

上一篇:乐鑫Esp32学习之旅 安信可 ESP32-Cam 摄像头开发板二次开发 C SDK编程,拍照图片通过有线串口传到上位机PC端。(附带设备端+PC端源码)


下一篇:特征工程·TFIDF提取特征