当前位置: 首页 > news >正文

简答题文本自动评分

要求是这样的:

给定一段中文答案, 和标准的中文文字的答案做比对,最终得到完整的分数.

 

因为用户的答案中涉及到中文, 所以就必须使用中文分词器, 最终选定的是HanLP ,非常的方便, 资源链接如下:

https://github.com/hankcs/HanLP/tree/1.x  可以自行学习使用.

首先项目中引入HanLP的maven坐标:

<dependency><groupId>com.hankcs</groupId><artifactId>hanlp</artifactId><version>portable-1.7.7</version>
</dependency>

 

我们使用HanLP分词之后, 使用 向量余弦算法计算两个文本的相似性 ,下面就是写了一个分词的工具类:

package com.taohan.online.exam.util;import com.hankcs.hanlp.HanLP;
import com.hankcs.hanlp.seg.common.Term;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;/*** 分词工具类*/
public class HanlpUtil {/*** 判断标点符号正则表达式, 去掉标点符号*/private static Pattern PATTERN = Pattern.compile("\\pP");public static void main(String[] args) {System.out.println(cosine("天气预报说,明天会下雨,你明天早上去上班的时候记得带上伞。","你明天早上去上班的时候记得带上伞,天气预报说的可能会下雨。"));}/***  0.5543** 词向量余弦算法计算文本相似度** @return*/public static double cosine(String userAnswer, String standAnswer) {List<String> originWord = getWords(standAnswer);List<String> targetWord = getWords(userAnswer);Map<String, int[]> wordDict = new HashMap<>();for (String word : originWord) {if (!wordDict.containsKey(word)) {int[] value = new int[2];value[0] = 1;wordDict.put(word, value);} else {wordDict.get(word)[0] += 1;}}for (String word : targetWord) {if (!wordDict.containsKey(word)) {int[] value = new int[2];value[1] = 1;wordDict.put(word, value);} else {wordDict.get(word)[1] += 1;}}int dictNum = 0, originNum = 0, targetNum = 0;for (Map.Entry<String, int[]> entry : wordDict.entrySet()) {int origin = entry.getValue()[0];int des = entry.getValue()[1];originNum += origin * origin;targetNum += des * des;dictNum += origin * des;}double sqrt = Math.sqrt(originNum * targetNum);BigDecimal scale = new BigDecimal(dictNum).divide(new BigDecimal(sqrt), 4, BigDecimal.ROUND_HALF_UP).setScale(4, BigDecimal.ROUND_HALF_UP);return scale.doubleValue();}/*** 分词** @param str* @return*/public static List<String> getWords(String str) {List<String> list = new ArrayList<>();if (StringUtils.isBlank(str)) {return list;}List<Term> segment = HanLP.segment(str);for (Term term : segment) {//https://github.com/hankcs/HanLP/tree/1.xif (!PATTERN.matcher(term.word).matches()) {list.add(term.word);}}return list;}}

中文分词就解决了, 还有向量余弦算法计算文本相似度 的问题也解决了,

 

下面是一个用户答案的评分的工具类, 以及其使用的示例, 

用户输入用户的答案, 用户答案和标准答案的多个关键字进行比较, 得到关键词双向匹配得分, 再和标准答案进行两个答案的文本比较得到相似性得分, , 两个得分计算平均值, 得到最后的得分.

package com.taohan.online.exam.util;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;public class CompareUtil {public static void main(String[] args) {String userAnswer = "多态是在程序还没运行时不知道调用哪个函数,在程序执行中,根据情况动态确定,操作很灵活";String standAnswer = "多态是在程序还没运行时不知道调用函数,在程序执行,根据情况动态确定";List<String> keywords = Stream.of("多态", "程序", "函数名", "参数", "运行情况").collect(Collectors.toList());double score = getUserAnswerScore(userAnswer, standAnswer, keywords);System.out.println(score);}/*** 获取最后的得分** @param userAnswer  用户答案* @param standAnswer 标准答案* @param keywords    关键词* @return*/public static double getUserAnswerScore(String userAnswer, String standAnswer, List<String> keywords) {if (StringUtils.equals(userAnswer, standAnswer)) {return 1.0;}if (StringUtils.isBlank(userAnswer)) {return 0.0;}double textSameScore = HanlpUtil.cosine(userAnswer, standAnswer);double score = 0;if (keywords != null && keywords.size() > 0) {score = getCompareScore(keywords, userAnswer);} else {score = textSameScore;}//计算两者的平均数BigDecimal scale = new BigDecimal(textSameScore).add(new BigDecimal(score)).divide(new BigDecimal(2), 4, BigDecimal.ROUND_HALF_UP).setScale(4, BigDecimal.ROUND_HALF_UP);return scale.doubleValue();}/*** 0.4254* 获得关键词双向匹配得分** @param keywords* @param userAnswer* @return*/public static double getCompareScore(List<String> keywords, String userAnswer) {List<BigDecimal> list = new ArrayList<>();for (String keyword : keywords) {BigDecimal precent = getPrecent(userAnswer, keyword);list.add(precent);}BigDecimal sum = new BigDecimal("0");for (BigDecimal bigDecimal : list) {sum = sum.add(bigDecimal);}BigDecimal scale = sum.divide(new BigDecimal(list.size()), 4, BigDecimal.ROUND_HALF_UP).setScale(4, BigDecimal.ROUND_HALF_UP);return scale.doubleValue();}/*** 比较两个字符串的相似度** @param answer* @param oneWord* @return*/public static BigDecimal getPrecent(String answer, String oneWord) {int index = 0;if (oneWord == null || oneWord.length() < 1) {return new BigDecimal(0);}if (answer.indexOf(oneWord) != -1) {index = oneWord.length();} else {int length = oneWord.length();for (int i = 0; i < length; i++) {String a = oneWord.substring(i, length - 1);String b = oneWord.substring(i + 1, length);if (answer.indexOf(a) != -1) {index = a.length();break;}if (answer.indexOf(b) != -1) {index = b.length();break;}}}if (index == 0) {for (int i = 0; i < oneWord.length(); i++) {if (answer.contains(String.valueOf(oneWord.charAt(i)))) {index = 1;}}}BigDecimal decimal = new BigDecimal(index).divide(new BigDecimal(oneWord.length()), 2, BigDecimal.ROUND_HALF_UP).setScale(4, BigDecimal.ROUND_HALF_UP);return decimal;}}

其实就是两个工具类的事情, 很简单.

这个是别人花钱雇我写的, 为了保证原创性, 暂时不会公开出来(大概4个月后会公开). 仅供大家参考


http://www.taodudu.cc/news/show-4919094.html

相关文章:

  • [0509] StackOverflowExchange 的关系和时间线 | Godaddy DNS API 加入用户限制
  • OpenNJet,够轻更强云原生应用引擎
  • 基于自己数据微调LLama3并本地化部署
  • C++Primer Plus第五章结构编程练习2
  • Java 高级面试问题及答案 更新(一)
  • 【算法刷题day44】Leetcode:518. 零钱兑换 II、377. 组合总和 Ⅳ
  • 五角星动态评分效果
  • 微信小游戏云开发数据库
  • mysql 游戏服务器设计_网络游戏服务器数据库设计和实现.doc
  • unity数据库
  • 怎样修改游戏服务器里的数据库,修改游戏服务器中的数据库
  • echart地图修改label标签位置
  • react中label标签关联的用法
  • html中调整lable位置右移,[转载]label标签右对齐
  • label标签和input标签之间的关系
  • java label 标签_Java标签(Label)
  • CSS3学习笔记(九)——UI元素状态伪类选择器 :checked
  • 学生专用计算机如何打游戏,学生党电脑差怎么办?推荐几款低配的联机游戏,渣机也畅玩!...
  • 心理测试小游戏
  • java游戏解救人质_抖音解救人质的游戏
  • 枪战游戏html源码,html5西部牛仔枪战游戏源码
  • 使用Dart/Flutter语言开发的命令行文字RPG类型小游戏
  • 以电影为题材好玩的游戏总结
  • 基于Centos7.X的CS:GO社区服搭建
  • CS:GO 设置和优化
  • 安利一个好玩的JS编程游戏—warriorjs
  • CS和CSS的区别【吐血整理,疯狂推荐】
  • 2008游戏服务器系统下,Linux系统下玩经典游戏 CS1.5服务器架设
  • linux 搭建游戏服务器,Linux系统下玩经典游戏 CS1.5服务器架设
  • 通过「解救人质」小游戏教你学会碰撞检测
  • cocos creator实例--CocosCreator实现的 解救人质 游戏,学会碰撞检测
  • 解救人质的android游戏,一枪制敌解救人质游戏
  • mapreduce php,php mapreduce
  • hadoopStreamming 编程
  • 轻松搞定java高薪
  • 13条建议搞定程序员发展