首页 > 其他分享 >个人项目

个人项目

时间:2023-09-20 18:26:32浏览次数:36  
标签:BigInteger word String 个人 项目 topicName new 分词

这个作业属于哪个课程 计算2114
这个作业要求在哪里 个人项目
这个作业的目标 1.在github上实现代码的运行 2.对于文本相似度算法的理解 3.遍历代码并对其做出优化

需求

题目:论文查重

描述如下:

设计一个论文查重算法,给出一个原文文件和一个在这份原文上经过了增删改的抄袭版论文的文件,在答案文件中输出其重复率。

原文示例:今天是星期天,天气晴,今天晚上我要去看电影。
抄袭版示例:今天是周天,天气晴朗,我晚上要去看电影。
要求输入输出采用文件输入输出,规范如下:

从命令行参数给出:论文原文的文件的绝对路径。
从命令行参数给出:抄袭版论文的文件的绝对路径。
从命令行参数给出:输出的答案文件的绝对路径。

Github仓库链接

Github链接

PSP表格

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

运行环境

SimHash计算原理

1.分词:对给定的一段文本进行分词,产生n个特征词,并赋予每个特征词一个权重。
2.Hash:通过hash函数对每一个词向量进行映射,产生一个n位二进制串。
3.加权:经过前面的计算已经得到了每个词向量的Hash串和该词向量对应的权重,第三步计算权重向量W=hash*weight。
4.合并:对于一个文本,计算出了文本分词之后每一个特征词的权重向量,在合并这个阶段,把文本所有词向量的权重向量相累加,得到一个新的权重向量。
5.降维:对于前面合并后得到的文本的权重向量,大于0的位置1,小于等于0的位置0,就可以得到该文本的SimHash值。

SimHash算法步骤如下:

1.将一个 f 维的向量 V 初始化为 0 ;f 位的二进制数 S 初始化为 0;
2.对每一个特征用传统的 Hash 算法对该特征产生一个 f 位的签名 b。对 i=1 到 f :如果b 的第 i 位为 1 ,则 V 的第 i 个元素加上该特征的权重;否则,V 的第 i 个元素减去该特征的权重;
3.如果 V 的第 i 个元素大于 0 ,则 S 的第 i 位为 1,否则为 0 ;
4.输出 S 作为签名;

SimHash算法原理图如下:

文本相似度的计算

JAVA通过SimHash计算

一.新增依赖包

package com.b2c.aiyou.bbs.common.utils.hanlp;

import com.hankcs.hanlp.seg.common.Term;
import com.hankcs.hanlp.tokenizer.StandardTokenizer;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;

import java.math.BigInteger;
import java.util.*;

二.过滤特殊字符

/**
 * Description:[过滤特殊字符]
 *
 */
private String clearSpecialCharacters(String topicName) {

    // 将内容转换为小写
    topicName = StringUtils.lowerCase(topicName);

    // 过来HTML标签
    topicName = Jsoup.clean(topicName, Whitelist.none());

    // 过滤特殊字符
    String[] strings = {" ", "\n", "\r", "\t", "\\r", "\\n", "\\t", " ", "&", "<", ">", """, "&qpos;"};
    for (String string : strings) {
        topicName = topicName.replaceAll(string, "");
    }

    return topicName;
}

三.计算单个分词的Hash值

/**
 * Description:[计算单个分词的hash值]
 *
 */
private BigInteger getWordHash(String word) {

    if (StringUtils.isEmpty(word)) {

        // 如果分词为null,则默认hash为0
        return new BigInteger("0");
    } else {

        // 分词补位,如果过短会导致Hash算法失败
        while (word.length() < SimHashUtil.WORD_MIN_LENGTH) {
            word = word + word.charAt(0);
        }

        // 分词位运算
        char[] wordArray = word.toCharArray();
        BigInteger x = BigInteger.valueOf(wordArray[0] << 7);
        BigInteger m = new BigInteger("1000003");

        // 初始桶pow运算
        BigInteger mask = new BigInteger("2").pow(this.hashCount).subtract(new BigInteger("1"));

        for (char item : wordArray) {
            BigInteger temp = BigInteger.valueOf(item);
            x = x.multiply(m).xor(temp).and(mask);
        }

        x = x.xor(new BigInteger(String.valueOf(word.length())));

        if (x.equals(ILLEGAL_X)) {

            x = new BigInteger("-2");
        }

        return x;
    }
}

四.分词计算向量

/**
 * Description:[分词计算向量]
 *
 */
private BigInteger simHash() {

    // 清除特殊字符
    this.topicName = this.clearSpecialCharacters(this.topicName);
    int[] hashArray = new int[this.hashCount];

    // 对内容进行分词处理
    List<Term> terms = StandardTokenizer.segment(this.topicName);

    // 配置词性权重
    Map<String, Integer> weightMap = new HashMap<>(16, 0.75F);
    weightMap.put("n", 1);
    // 设置停用词
    Map<String, String> stopMap = new HashMap<>(16, 0.75F);
    stopMap.put("w", "");
    // 设置超频词上线
    Integer overCount = 5;

    // 设置分词统计量
    Map<String, Integer> wordMap = new HashMap<>(16, 0.75F);

    for (Term term : terms) {
        // 获取分词字符串
        String word = term.word;
        // 获取分词词性
        String nature = term.nature.toString();

        // 过滤超频词
        if (wordMap.containsKey(word)) {

            Integer count = wordMap.get(word);
            if (count > overCount) {
                continue;
            } else {
                wordMap.put(word, count + 1);
            }
        } else {
            wordMap.put(word, 1);
        }

        // 过滤停用词
        if (stopMap.containsKey(nature)) {
            continue;
        }

        // 计算单个分词的Hash值
        BigInteger wordHash = this.getWordHash(word);

        for (int i = 0; i < this.hashCount; i++) {

            // 向量位移
            BigInteger bitMask = new BigInteger("1").shiftLeft(i);

            // 对每个分词hash后的列进行判断,例如:1000...1,则数组的第一位和末尾一位加1,中间的62位减一,也就是,逢1加1,逢0减1,一直到把所有的分词hash列全部判断完

            // 设置初始权重
            Integer weight = 1;
            if (weightMap.containsKey(nature)) {

                weight = weightMap.get(nature);
            }
            // 计算所有分词的向量
            if (wordHash.and(bitMask).signum() != 0) {
                hashArray[i] += weight;
            } else {
                hashArray[i] -= weight;
            }

        }
    }

    // 生成指纹
    BigInteger fingerPrint = new BigInteger("0");
    for (int i = 0; i < this.hashCount; i++) {

        if (hashArray[i] >= 0) {
            fingerPrint = fingerPrint.add(new BigInteger("1").shiftLeft(i));
        }
    }

    return fingerPrint;
}

五.获取文本内容的海明距离

/**
 * Description:[获取文本内容的海明距离]
 *
 */
private int getHammingDistance(SimHashUtil simHashUtil) {

    // 求差集
    BigInteger subtract = new BigInteger("1").shiftLeft(this.hashCount).subtract(new BigInteger("1"));

    // 求异或
    BigInteger xor = this.bigSimHash.xor(simHashUtil.bigSimHash).and(subtract);

    int total = 0;
    while (xor.signum() != 0) {
        total += 1;
        xor = xor.and(xor.subtract(new BigInteger("1")));
    }

    return total;
}

六.获取文本内容的相似度

/**
 * Description:[获取文件内容的相似度]
 *
 */
public Double getSimilar(SimHashUtil simHashUtil) {

    // 获取海明距离
    Double hammingDistance = (double) this.getHammingDistance(simHashUtil);

    // 求得海明距离百分比
    Double scale = (1 - hammingDistance / this.hashCount) * 100;

    Double formatScale = Double.parseDouble(String.format("%.2f", scale));

    return formatScale;
}

异常处理

try {
// 读取原文文件和抄袭版论文文件的内容
String originalTitle = readFileContent(originalTitlePath);
String copyingTitle = readFileContent(copyingTitlePath);

// 计算重复率
double similarity = calculateSimilarity(originalTitle,copyingTitle);

// 将结果写入输出结果文件
writeResult(outputTitlePath, similarity);

// 输出重复率
System.out.println("检测完成,重复率为: " + String.format("%.2f", similarity));

} catch (IOException e) {
System.out.println("发生错误:" + e.getMessage());
e.printStackTrace();
}

测试

public static void main(String[] args) {
    // 准备测试文件内容数据
    List<String> titleList = new ArrayList<>();
    titleList.add("今天是星期天,天气晴,今天晚上我要去看电影。");
    titleList.add("今天是周天,天气晴朗,我晚上要去看电影。");


    // 原始文件内容数据
    String originalTitle = "今天是星期天,天气晴,今天晚上我要去看电影。";

    Map<String, Double> simHashMap = new HashMap<>(16, 0.75F);

    System.out.println("======================================");
    long startTime = System.currentTimeMillis();
    System.out.println("原始文件:" + originalTitle);

    // 计算相似度
    titleList.forEach(title -> {
        SimHashUtil mySimHash_1 = new SimHashUtil(title, 64);
        SimHashUtil mySimHash_2 = new SimHashUtil(originalTitle, 64);

        Double similar = mySimHash_1.getSimilar(mySimHash_2);

        simHashMap.put(title, similar);
    });

    // 打印测试结果到控制台
    /* simHashMap.forEach((title, similarity) -> {
        System.out.println("文件:"+title+"-----------相似度:"+similarity);
    });*/

    // 按相文本内容排序输出控制台
    Set<String> titleSet = simHashMap.keySet();
    Object[] titleArrays = titleSet.toArray();
    Arrays.sort(titleArrays, Collections.reverseOrder());

    System.out.println("-------------------------------------");
    for (Object title : titleArrays) {
        System.out.println("文本:" + title + "-----------相似度:" + simHashMap.get(title));
    }

    // 求得运算时长(单位:毫秒)
    long endTime = System.currentTimeMillis();
    long totalTime = endTime - startTime;
    System.out.println("\n本次运算总耗时" + totalTime + "毫秒");

    System.out.println("======================================");
}

接口设计与类名

类名 实现方法
main main方法
SimHash类 getWordHash,BigInteger simHash,BigInteger simHash,getSimilar

标签:BigInteger,word,String,个人,项目,topicName,new,分词
From: https://www.cnblogs.com/yet4U/p/17717664.html

相关文章

  • Springboot 的 maven项目利用 maven插件构建 docker 镜像(免 DockerFile编写)
    Springboot的maven项目利用maven插件构建docker镜像(免DockerFile编写)本小节目的是springboot项目maven插件构建容器实验步骤:1.本地创建springboot项目,写业务逻辑代码2.提交代码到远程git仓库3.在linux环境拉取远程git仓库代码,构建镜像4.把构建完成的镜像推送......
  • IDEA 本地启动项目时候提示:错误:无法加载主类StartMain
    这也许是IDEA的bug.最好的办法就是清理IDEA项目缓存。具体步骤如下:一、检查使用包版本是否正确 二、清除缓存重启 ......
  • 2023年9月天津/济南/深圳CSPM-3国标项目管理中级认证报名
    CSPM-3中级项目管理专业人员评价,是中国标准化协会(全国项目管理标准化技术委员会秘书处),面向社会开展项目管理专业人员能力的等级证书。旨在构建多层次从业人员培养培训体系,建立健全人才职业能力评价和激励机制的要求,培养我国项目管理领域复合型人才。  【证书含金量】 ·竞聘优先......
  • 2023年9月西安/成都/广东软考中级系统集成项目管理工程师招生
    系统集成项目管理工程师是全国计算机技术与软件专业技术资格(水平)考试(简称软考)项目之一,是由国家人力资源和社会保障部、工业和信息化部共同组织的国家级考试,既属于国家职业资格考试,又是职称资格考试。 系统集成项目管理工程师,属于软考三个级别中的“中级”。 考试合格者将颁发由中......
  • Vue-cli创建项目
    1.单页面应用:spa-以后Vue的项目就只有一个:XX.html页面-当定义了很多组件,不可能都写在:XX.html中吧2.单文件组件:xx.vue-https://v2.cn.vuejs.org/v2/guide/single-file-components.html-一个组件一个文件一个组件中有的东西-1.html内容:以后html都放在te......
  • HNU_个人项目_中小学数学卷子自动生成程序_简要分析何梁雨代码
    一、前言感谢老师安排的这一次互评,以及我的结对编程伙伴何梁雨。在互评中我学到了不一样的编程思路,更清晰的感受到了自己编程水平哪一部分存在缺陷,并向这个方向学习改正。二、测试与评价1.测试程序运行(1)界面整洁简单,流程清晰。动作转折的地方经常会有一长串横杠隔开,让......
  • 湖南大学结对编程个人项目互评
    1.简介本博客用于湖南大学结对编程项目中对王明扬同学个人项目的互评工作。个人项目的功能是实现一个中小学数学试卷自动生成程序,基于命令行进行操作。2.代码2.1项目结构项目由多个包组成,分别执行不同的功能:2.1.1controller:接收用户的输入,调用service层进行相应的逻辑......
  • 【个人项目互评】————中小学生题目生成程序
    在完成个人项目的建设后,我和搭档互相交换了代码进行分析。在阅读过程中,看到了她代码的优势,也同时看到了自己代码的不足。再次写下这一次的项目分析;一、题目要求   二、测试与分析功能完成情况: 在输入正确的账户名以及密码后,能够获得当前用户年级信息以及后续操作步骤......
  • Vue动态组件、插槽、vue项目
    一、动态组件1、动态组件#<component:is="who"></component>#component标签的is属性等于组件名字,这里就会显示这个组件<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title>......
  • Avalonia开发(二)项目结构解析
    一、前言在Avalonia开发(一)环境搭建文章中介绍了Avalonia的介绍、开发环境的搭建、项目创建,以及项目FirstAvaloniaApp项目结构的介绍。本篇文章将介绍各平台的项目介绍。二、Desktop项目结构FirstAvaloniaApp.Desktop项目中默认生成的只有两个文件:Program.cs和app.manifest(程......