java实现计算ROUGE-L指标(一)

ROUGE (Recall-Oriented Understudy for Gisting Evaluation) 是用于评估自动文摘或机器翻译的一种评估方法,其中的ROUGE-L指标是基于最长公共子序列(Longest Common Subsequence,LCS)来计算的

我们做AI问答系统,需要一些量化指标来作为优化人工智能大模型的指导标准,经过调查Rouge-L的特征测量是量化指标的手段之一。

为了采用更精确的分词算法、词性还原和停用词处理,我借助一些自然语言处理的库,以下是我引入的maven依赖:

<dependency>  <groupId>edu.stanford.nlp</groupId>  <artifactId>stanford-corenlp</artifactId>  <version>3.9.2</version>  
</dependency>  
<dependency>  <groupId>edu.stanford.nlp</groupId>  <artifactId>stanford-corenlp</artifactId>  <version>3.9.2</version>  <classifier>models</classifier>  
</dependency>  
<dependency>  <groupId>junit</groupId>  <artifactId>junit</artifactId>  <version>4.12</version>  <scope>test</scope>  
</dependency>

然后是我的具体代码实现,因为词性标注和词性还原需要借助本地模型实现,为了快速落地量化指标,我暂时不使用词性标注和词性还原。

(Recall-Oriented Understudy for Gisting Evaluation) 是用于评估自动文摘或机器翻译的一种评估方法,其中的ROUGE-L指标是基于最长公共子序列(Longest Common Subsequence,LCS)来计算的。它主要关注词序列的匹配程度,不依赖于词性标注和词性还原。
因此,即使不使用词性标注和词性还原,只要确保分词正确,你仍然可以得到有效的ROUGE-L指标。

以下是我的代码具体实现:

package com.xxx.zjtest.testtest.test;import edu.stanford.nlp.ling.CoreAnnotations;
import edu.stanford.nlp.ling.CoreLabel;
import edu.stanford.nlp.pipeline.*;
import edu.stanford.nlp.util.CoreMap;import java.util.*;/**** 不使用词性标注和词性还原直接计算ROUGE-L指标本身不会产生问题。**/
public class RougeLCalculator {private static final Set<String> STOP_WORDS = new HashSet<>(Arrays.asList("的", "了", "和", "是", "就", "都", "而", "及", "与", "在")); // 中文停用词示例列表public static double calculateRougeL(String referenceText, String hypothesisText) {// 创建Stanford CoreNLP管道Properties props = new Properties();props.setProperty("annotators", "tokenize, ssplit"); //加, pos, lemma 会报错props.setProperty("ssplit.eolonly", "true");StanfordCoreNLP pipeline = new StanfordCoreNLP(props);// 处理参考答案和假设答案Annotation referenceAnnotation = new Annotation(referenceText);Annotation hypothesisAnnotation = new Annotation(hypothesisText);pipeline.annotate(referenceAnnotation);pipeline.annotate(hypothesisAnnotation);// 获取参考答案和假设答案的词性还原后的单词列表/*List<String> referenceWords = getLemmatizedWords(referenceAnnotation, STOP_WORDS);List<String> hypothesisWords = getLemmatizedWords(hypothesisAnnotation, STOP_WORDS);*/// 获取参考答案和假设答案的分词列表List<String> referenceWords = getTokenizedWords(referenceAnnotation, STOP_WORDS);List<String> hypothesisWords = getTokenizedWords(hypothesisAnnotation, STOP_WORDS);// 计算ROUGE-L指标return calculateLongestCommonSubsequence(referenceWords, hypothesisWords);}//词性标注和词性还原部分,此部分需要使用大模型,无法实现/*private static List<String> getLemmatizedWords(Annotation annotation, Set<String> stopWords) {List<String> words = new ArrayList<>();for (CoreMap sentence : annotation.get(CoreAnnotations.SentencesAnnotation.class)) {for (CoreLabel token : sentence.get(CoreAnnotations.TokensAnnotation.class)) {String word = token.word(); // 获取分词后的单词String pos = token.get(CoreAnnotations.PartOfSpeechAnnotation.class); // 获取词性标注String lemma = token.get(CoreAnnotations.LemmaAnnotation.class); // 获取词性还原后的单词if (!stopWords.contains(word) && !pos.equalsIgnoreCase("PUNCT")) { // 过滤停用词和标点符号words.add(lemma);}}}return words;}*/private static List<String> getTokenizedWords(Annotation annotation, Set<String> stopWords) {List<String> words = new ArrayList<>();for (CoreMap sentence : annotation.get(CoreAnnotations.SentencesAnnotation.class)) {for (CoreLabel token : sentence.get(CoreAnnotations.TokensAnnotation.class)) {String word = token.word(); // 获取分词后的单词if (!stopWords.contains(word)) { // 过滤停用词words.add(word);}}}return words;}//计算公共最长子序列private static double calculateLongestCommonSubsequence(List<String> referenceWords, List<String> hypothesisWords) {int[][] dp = new int[referenceWords.size() + 1][hypothesisWords.size() + 1];for (int i = 1; i <= referenceWords.size(); i++) {for (int j = 1; j <= hypothesisWords.size(); j++) {if (referenceWords.get(i - 1).equals(hypothesisWords.get(j - 1))) {dp[i][j] = dp[i - 1][j - 1] + 1;} else {dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);}}}int lcs = dp[referenceWords.size()][hypothesisWords.size()];double precision = (double) lcs / hypothesisWords.size();double recall = (double) lcs / referenceWords.size();double rougeL = 2 * precision * recall / (precision + recall);System.out.println(rougeL);return rougeL;}public static double calculateAverageRougeL(List<String> referenceTexts, List<String> hypothesisTexts) {if (referenceTexts.size() != hypothesisTexts.size()) {throw new IllegalArgumentException("参考文本列表和假设文本列表的长度必须相等");}double totalRougeL = 0;for (int i = 0; i < referenceTexts.size(); i++) {totalRougeL += calculateRougeL(referenceTexts.get(i), hypothesisTexts.get(i));}return totalRougeL / referenceTexts.size();}public static void main(String[] args) {String yTest1 = "客户专用网络的使用应注意以下几点:\n" +"\n" +"实施方案应由公司网络管理员组织制定,并与客户共同协商制定实施方案。\n" +"禁止将客户要求隔离的网络与未经客户许可的网络连通。\n" +"禁止将客户要求使用的网络与公司内部网络连通。\n" +"禁止在客户专用网络中搭建无线网络。\n" +"禁止在客户专用网络中使用笔记本电脑。\n" +"禁止在客户专用网络中未经过客户允许进行互联网访问。\n" +"禁止在客户专用网络中未按照客户要求执行设备要求。";String nTest1 = "根据已知信息,客户专用网络的注意事项有以下几点:\n" +"\n" +"禁止将客户要求隔离的网络与未经客户许可的网络连通。\n" +"禁止将客户要求使用的网络与公司内部网络连通。\n" +"禁止在客户专用网络中搭建无线网络。\n" +"禁止在客户专用网络中使用笔记本电脑。\n" +"禁止在客户专用网络中未经过客户允许进行互联网访问。\n" +"禁止在客户专用网络中未按照客户要求执行设备要求。\n" +"客户专用网络的申请与构建应由公司网络管理员组织制定,并与客户共同协商制定实施方案。\n" +"客户专用网络的规划与实施应由公司网络管理员与申请部门共同执行,如在实施过程中需要第三方参与,公司网络管理员应进行监督,并与申请部门共同验收。\n" +"若需使用客户的内部网络,必须事先获得客户批准,并严格遵守客户的网络安全规定,只能从事和业务相关的工作,不得私自查看其它计算机或客户内部网络上的任何保密信息,禁止任何令客户网络严重增加负载或容易引起网络故障的行为。\n" +"若需在客户现场访问Internet,必须事先获得客户批准,并按照客户的要求采取必要的安全措施。";String yTest2 = "禁止将公司资料、私人信息以及敏感内容存储在个人邮箱中,避免信息泄露。\n" +"及时删除接收的邮件,避免信息被他人获取。\n" +"禁止使用私人邮箱用于工作中的业务往来,避免信息泄露。\n" +"谨慎使用电子邮件,避免感染病毒,确保邮件发送保密信息。\n" +"禁止使用工作手机号码进行非工作目的的网站注册。\n" +"及时将工作手机的操作系统升级至最新版本。\n" +"工作手机信息安全管理要求,包括保密性、完整性、可用性等方面。";String nTest2="不要将公司资料、私人信息以及敏感内容存储在个人邮箱中,避免信息泄露。\n" +"及时删除接收的邮件,避免信息被他人获取。\n" +"禁止使用私人邮箱用于工作中的业务往来。\n" +"谨慎使用电子邮件,避免感染病毒,确保邮件发送保密信息。\n" +"禁止使用工作手机号码进行非工作目的的网站注册。\n" +"及时将工作手机的操作系统升级至最新版本。\n" +"遵守公司电子邮件尺寸规定,不得发送超大邮件。\n" +"收到不明电子邮件尽量不要回信,含有可疑附件时不得打开,并应立即删除该邮件。\n" +"发送电子邮件时,应认真核对收件人地址,避免误传送。\n" +"若发生电子邮件误传送时,应立即再发一封致歉信,声明发错,并请对方将已收到的邮件删除。\n" +"若邮件含有公司敏感信息,应立即向部门领导及业务安全部汇报。\n" +"当收到别人发错的电子邮件时,应立即通知提醒发件人,若该邮件含有改善敏感信息,应将邮件彻底删除。\n" +"禁止使用手机VPN进行加密。\n" +"禁止使用工作手机接收邮件。\n" +"禁止使用私人邮箱进行邮件收发。\n" +"禁止使用手机接收或发送邮件时点击或打开可疑链接或附件,避免被恶意攻击导致信息泄露。";//计算单个值//System.out.println(calculateRougeL(yTest1,nTest1));// 计算平均值List<String> referenceTexts = Arrays.asList(yTest1, yTest2);List<String> hypothesisTexts = Arrays.asList(nTest1, nTest2);double averageRougeL = calculateAverageRougeL(referenceTexts, hypothesisTexts);System.out.println("平均ROUGE-L值: " + averageRougeL);}
}
  • tokenize: 这个注解器用于将文本分解成单词或标记(tokens)。例如,对于句子"Hello world!",tokenize会将其分解为两个标记:“Hello"和"world!”。
  • ssplit: 这个注解器用于句子分割,即将文本分割成句子。它根据标点符号和其他线索来确定句子的边界。
  • ssplit.eolonly: 这是一个特定的句子分割选项。当设置为true时,它只根据行尾(end-of-line)符号来分割句子,忽略其他标点符号。这通常用于那些每行只有一个句子的文本。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/742197.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

访问学者申请记|美国首所翻译博士点

N老师出国访学的目的一方面是开拓眼界&#xff0c;另一方面也是为完成翻译方向的博士论文创造更好的条件。最终我们获得美国纽约州立大学宾汉姆顿分校的邀请函&#xff0c;该校的“翻译研究和教学项目”&#xff08;TRIP&#xff09;是美国高校设立的第一个翻译博士学位项目&am…

JavaScript进阶3之参数按值传递、call,apply,bind和new的实现、继承的多种方式

JavaScript基础 参数按值传递按值传递共享传递 call、apply、bind和new的实现this软绑定硬绑定 call的实现第一步第二步第三步 apply的实现bind的实现返回函数的模拟实现传参的模拟实现构造函数效果的模拟实现构造函数效果的优化实现 new的实现初步实现 继承的多种方式&优缺…

(学习日记)2024.03.09:UCOSIII第十一节:就绪列表

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

计算机网络 —— 运输层

运输层 5.1 运输层概述 运输层的主要任务是&#xff0c;如何为运行在不同主机上的应用进程提供直接的通信服务。运输层协议又称为端到端协议。 根据应用需求的不同&#xff0c;因特网的运输层为应用层提供了两种不同的运输协议&#xff0c;即面向连接的TCP和无连接的UDP 5.2…

金融需要多样性,量化需要C++!通过本文,你可以知道:1、为什么是C++

通过本文&#xff0c;你可以知道&#xff1a; 1、为什么是C 2、Python的用武之地 3、量化C岗位薪酬水平 C VS Python 量化交易系统开发语言主要用C&#xff0c;也有人用Python。 但是从经验看&#xff0c;用C开发的量化交易系统能够让在系统中程序运行的速度更快。 量化交易…

Maya为模型添加细分数

文章目录 方法1 通道盒操作注意 方法2 添加分段操作注意 方法3 平滑操作 方法1 通道盒 操作 选中物体&#xff0c;选择通道盒/输入/点一下模型的名字/细分数&#xff0c;分别为长宽高添加细分 这相当于修改模型的底层数据&#xff0c;不会平滑模型&#xff0c;只会进行细分 …

瑞熙贝通实验室物联网管理平台新升级|支持远程开门视频监控与电源控制以及环境监测

瑞熙贝通实验室智能物联网管控平台&#xff1a;利用“互联网与物联网技术”有机融合&#xff0c;对实验室的用电安全监测、实验室环境异常监测&#xff08;颗粒物监测、明火监测、可燃气体、烟雾监测、温湿度传感器、红外人体感应&#xff09;、实验室人员安全准入、万物互联等…

什么是全局解释器锁(GIL)?它如何影响Python的多线程性能?

什么是全局解释器锁&#xff08;GIL&#xff09;&#xff1f;它如何影响Python的多线程性能&#xff1f; 全局解释器锁&#xff08;GIL&#xff0c;Global Interpreter Lock&#xff09;是计算机程序设计语言解释器用于同步线程的工具&#xff0c;确保同一时间内仅有一个线程…

爬虫案例1

通过get请求直接获取电影信息 目标页面: https://spa6.scrape.center/在network中可以看到是通过Ajax发送的请求&#xff0c;这个请求在postman中也可以直接请求成功&#xff0c;这只是一个用来练习爬虫的&#xff0c;没有达到js逆向的过程&#xff0c;需要通过分析js 代码来获…

Excel判断CD两列在EF两列的列表中是否存在

需求 需要将CD两列的ID和NAME组合起来&#xff0c;查询EF两列的ID和NAME组合起来的列表中是否存在&#xff1f; 比如&#xff0c;判断第二行的“123456ABC”在EF的第二行到第四行中是否存在&#xff0c;若存在则显示Y&#xff0c;不存在则显示N 实现的计算公式 IF(ISNUMBER…

淘宝基于Nginx二次开发的Tengine服务器

最近在群里看到这样一张阿里云网关报错的截图&#xff0c;我保存下来看了下 看到下面有 Tengine提供技术支持&#xff0c;这个Tengine是什么东西呢&#xff1f;我搜索了下似乎是淘宝在nginx的基础上自己改的Web服务器 Tengine还支持OpenResty框架&#xff0c;该框架是基于Ngin…

SAR ADC学习笔记(5)

高精度比较器 一、基于开环运放的比较器 OP开环应用时不需要考虑频率特性(相位裕度那些) &#xff0c;不存在稳定性问题。 单级运放的时域响应 多级运放 二、Latch比较器 Latch比较器的速度 Latch比较器的噪声优化 三、高速高精度比较器 消除失调电压OFFSET OOS IOS

nRF52832——唯一 ID 与加密解密

nRF52832——唯一 ID 与加密解密 唯一 ID 概念唯一 ID 作用读取唯一 ID 唯一 ID 用于加密TEA 加密算法唯一 ID 的加密和解密 唯一 ID 概念 唯一 ID 作用 nRF52xx 微控制器提供一组 64 位的唯一 ID 号&#xff0c;这个唯一身份标识所提供的 ID 值对任意一个 nRF52xx 微控制器&…

展会邀约 | 加速科技将携重磅产品亮相SEMICON China 2024

SEMICON China 2024将于3月20日-3月22日在上海新国际博览中心隆重举行。展会期间&#xff0c;加速科技将携重磅产品高性能数模混合信号测试机ST2500EX、LCD Driver测试机Flex10K-L、高密度数模混合信号测试系统ST2500E、高性能数模混合信号测试系统ST2500A亮相此次行业盛会&…

WEB区块链开发组件 - KLineChart

当我们开发区块链的时候&#xff0c;实现K线可能大家会想到EChart&#xff0c;但是EChart做可能需要耗费大量工作量&#xff0c;实现出来的功能估计也是牵强着用。 这时候&#xff0c;我们可能网上会搜索到TradingView,可是这个组件虽然功能非常强大&#xff0c;但是还是要费事…

HDFS面试重点

文章目录 1. HDFS的架构2. HDFS的读写流程3.HDFS中&#xff0c;文件为什么以block块的方式存储&#xff1f; 1. HDFS的架构 HDFS的架构可以分为以下几个主要组件&#xff1a; NameNode&#xff08;名称节点&#xff09;&#xff1a; NameNode是HDFS的关键组件之一&#xff0c;…

Android7.1 ANR error 弹窗处理

Android7.1 ANR error 弹窗处理 问题描述解决方法 郑重声明:本人原创博文&#xff0c;都是实战&#xff0c;均经过实际项目验证出货的 转载请标明出处:攻城狮2015 Platform: Rockchip OS:Android 7.1.2 Kernel: 3.10 问题描述 有时会用到第三方apk&#xff0c;内置到系统中&…

全国车辆识别代码信息API查询接口-VIN深度解析

我们先来介绍下什么是vin码&#xff0c;以及vin码的构成结构解析&#xff0c;汽车VIN码&#xff0c;也叫车辆识别号码&#xff0c;通俗可以理解为汽车的身份证号码。 VIN码一共分四大部分&#xff1a; 1~3位&#xff0c;是世界制造厂识别代号&#xff08;WMI&#xff09;&…

DevOps本地搭建笔记(个人开发适用)

需求和背景 win11 wsl2 armbian(玩客云矿渣&#xff09;&#xff0c;构建个人cicd流水线&#xff0c;提高迭代效率。 具体步骤 基础设施准备 硬件准备&#xff1a;一台笔记本&#xff0c;用于开发和构建部署&#xff0c;一台服务器&#xff0c;用于日常服务运行。 笔记本…

Rust 并行库 crossbeam 的 Channel 示例

示例1 一个不完整的示例&#xff1a; let (tx, rx) channel::unbounded::<Task>(); let mut handlers vec![];for _ in 0..number {let rx rx.clone();let handle thread::spawn(move || {while let Some(task) rx.recv() {task.call_box();}});handlers.push(han…