第一次个人编程作业

GitHub链接

首先给出gitHub链接

PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 10 7
· Estimate · 估计这个任务需要多少时间 10 7
Development 开发 860 1166
· Analysis · 需求分析 (包括学习新技术) 240 335
· Design Spec · 生成设计文档 40 2
· Design Review · 设计复审 40 2
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 0 0
· Design · 具体设计 20 12
· Coding · 具体编码 320 676
· Code Review · 代码复审 20 2
· Test · 测试(自我测试,修改代码,提交修改) 180 137
Reporting 报告 140 129
· Test Repor · 测试报告 40 75
· Size Measurement · 计算工作量 40 34
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 60 20
合计 1010 1302

计算模块接口的设计与实现过程

在面向搜索引擎编程之后,以我对几个查重算法的理解下——simhash更像是评价是否有,海明距离难以体现出抄了多少。minHash与Jaccard系数,这两个是相似的,这两个的问题在于他无法体现出每个词出现的次数,在Jaccard里一个词出现多次与出现一次的效果相同。这点在长文本非常致命。所以在考虑之后,我使用了余弦相似性。他充分运用了次数(当然这个在一些情况也是一个大问题)

余弦相似度的原理,就是将文章通过词频构建向量,计算两个向量的相似程度——即夹角。这可以用余弦值得到

因此我可以先分词(这里使用了结巴分词),然后通过Map来存词在两篇文章各自出现次数,然后处理

然而,当我初次实现时,我却遇到一个诡异的问题,文本相似度基本高达1。这是为什么呢?

在考证之后

20200916221351.png
20200916221424.png
20200916221448.png

前面三十万是A平方的合计值,我们可以看到仅“的”就提供了将近九万的值,也就是说,“我”与“的”已经影响了这边文章查重的50%以上。

这合理吗?不这不合理!

我们要解决这个问题,必须引入权重

我一开始瞄上了TdIdf算法。很可惜我没有在网上找到可以导的包。。。。但是我通过对它的想法,写了一个程序(虽然程序名字写的是tfIdf但是我用的与一开始的定义有着相当大的不同)——我对五本小说进行结巴分词,然后将词与词频以json格式存起来了。

然而关于权重,在几次测试之后发现。如果以log的形式,由于log函数的递增速度过慢,像以“我”这个词为例,他的权重会是正常词的一半,但是在平方的状况下依旧不够有效。

我使用的权重是 (出现次数最多的词的次数)/(词的出现次数+1)的平方根 。

所以在计算余弦向量时,先解析了.json文件,然后对每个词的运算引入查重。

QQ20200916231412.png

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

20200916100904.png
20200916100817.png

时间的大头是在结巴算法的初始化,另外一个是对json文件的转化。我一开始以为时间是消耗在I/O操作,所以我使用了多线程。

20200916121917.png

但就结果而言,并没有什么卵用,其实时间的消耗估计是在cpu,我确实无计可施。

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

QQ20200916234603.png

QQ20200916234914.png

测试包括了

@Test(timeout = 5000)
public void Test(){
    String[] str = {IN_PATH+"time1.txt",IN_PATH+"time2.txt",filePath+"result/ans_time.txt"};
    Main.main(str);
}

这类测超时的,也有对jieba分词,以及文本处理的测试。使用的是Junit。但是在分支覆盖率查询时视乎运行会慢很多。

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

我设计了两个异常

package Except;

public class FileIsNullExcept extends RuntimeException{

    public FileIsNullExcept(){
        super();
    }

    public FileIsNullExcept(String message){
        super(message);
    }
}

这是文件为空的异常

package Except;

public class SimilarExcept extends RuntimeException{

    public SimilarExcept(){
        super();
    }

    public SimilarExcept(String message){
        super(message);
    }
}

这是相似为1会报错

并在测试中进行了测试;

	@Test(expected = FileIsNullExcept.class)
    public void test3FileNullExcept() {
        String[] str = {filePath+"test/null.txt",IN_PATH+"time2.txt",filePath+"result/ans_time.txt"};
        Main.main(str);
    }

    @Test(expected = SimilarExcept.class)
    public void Test4SimilarExcept(){
        String[] str = {IN_PATH+"time2.txt",IN_PATH+"time2.txt",filePath+"result/ans_time.txt"};
        Main.main(str);
    }

总结

  • 这次还是有问题不够满意,比如文件读取时的编码,还有权重的算法,这是我目前能力的不足。希望下次能做的好点的吧。
  • 我这次项目的没有仔细用过设计文档,毕竟难以在一开始获得详细的全貌,以及很多其中的问题还是需要面向搜索引擎编程。但是目前看,尽早的详细思路其实可以避免后期走入大坑,下次我还是得进行详细事先计划。
posted @ 2020-09-17 00:22  sdasdxgdxc  阅读(150)  评论(0编辑  收藏  举报