java - 斯坦福 CoreNLP 找到句子的同质部分
问题描述
我正在尝试基于斯坦福 CoreNLP 构建句子简化算法。我想做的简化之一 - 将句子同质部分的句子转换为几个句子。例如
我爱我的妈妈、爸爸和姐姐。-> 我爱我的妈妈。我爱我的爸爸。我爱我的妹妹。
首先,我为输入句子字符串构建语义图
final Sentence parsed = new Sentence(sentence);
final SemanticGraph dependencies = parsed.dependencyGraph();
这句话的依赖图是
-> love/VBP (root)
-> I/PRP (nsubj)
-> mom/NN (dobj)
-> my/PRP$ (nmod:poss)
-> ,/, (punct)
-> dad/NN (conj:and)
-> and/CC (cc)
-> sister/NN (conj:and)
-> dad/NN (dobj)
-> sister/NN (dobj)
然后我dobj
在图中找到了边nsubj
for (SemanticGraphEdge edge : dependencies.edgeListSorted()) {
if (edge.getRelation().getShortName().startsWith("dobj")) {
modifiers.add(edge);
} else if (edge.getRelation().getShortName().startsWith("nsubj")) {
subj = edge;
}
}
所以现在我有 3 个边缘和modifiers
单词。现在我的问题是如何将语义图拆分为 3 个单独的图。当然,幼稚的解决方案只是基于主体和州长/依赖于边缘构建句子,但我知道这是一个坏主意,不适用于更复杂的示例。nsubj
I
dobj
for (final SemanticGraphEdge edge : modifiers) {
SemanticGraph semanticGraph = dependencies.makeSoftCopy();
final IndexedWord governor = edge.getGovernor();
final IndexedWord dependent = edge.getDependent();
final String governorTag = governor.backingLabel().tag().toLowerCase();
if (governorTag.startsWith("vb")) {
StringBuilder b = new StringBuilder(subj.getDependent().word());
b.append(" ")
.append(governor.word())
.append(" ")
.append(dependent.word())
.append(". ");
System.out.println(b);
}
}
谁能给我一些建议?也许我错过了 coreNLP 文档中有用的东西?谢谢。
解决方案
感谢@JosepValls 的好主意。这里有一些代码示例,我如何简化具有 3 个或更多同质单词的句子。
首先,我为案例定义了几个正则表达式
jj(optional) nn, jj(optional) nn, jj(optional) nn and jj(optional) nn
jj(optional) nn, jj(optional) nn, jj(optional) nn , jj(optional) nn ...
jj , jj , jj
jj , jj and jj
vb nn(optional) , vb nn(optional) , vb nn(optional)
and so on
正则表达式是
Pattern nounAdjPattern = Pattern.compile("(((jj)\\s(nn)|(jj)|(nn))\\s((cc)|,)\\s){2,}((jj)\\s(nn)|(jj)|(nn))");
Pattern verbPatter = Pattern.compile("((vb\\snn|vb)\\s((cc)|,)\\s){2,}((vb\\snn)|vb)");
这些模式将用于定义输入句子是否具有同质单词列表以及查找边界。之后,我根据原始句子中的单词创建 POSes 列表
final Sentence parsed = new Sentence(sentence);
final List<String> words = parsed.words();
List<String> pos = parsed.posTags().stream()
.map(tag -> tag.length() < 2 ? tag.toLowerCase() : tag.substring(0, 2).toLowerCase())
.collect(Collectors.toList());
将此 POS 结构与正则表达式匹配 - 将列表连接到字符串
String posString = pos.stream().collect(Collectors.joining(" "));
如果句子不匹配任何正则表达式 - 让我们返回相同的字符串,否则 - 让我们简化它。
if (!matcher.find()) {
return new SimplificationResult(Collections.singleton(sentence));
}
return new SimplificationResult(simplify(posString, matcher, words));
在简化方法中,我正在寻找同质部分的边界并从单词列表 3 部分中提取 - 开头和结尾,不会改变和同质部分,这将被派生为部分。在将同质部分推导出来之后 - 我构建了几个简化的句子,如开头+片段+结尾。
private Set<String> simplify(String posString, Matcher matcher, List<String> words) {
String startPOS = posString.substring(0, matcher.start());
String endPPOS = posString.substring(matcher.end());
int wordsBeforeCnt = StringUtils.isEmpty(startPOS) ? 0 : startPOS.trim().split("\\s+").length;
int wordsAfterCnt = StringUtils.isEmpty(endPPOS) ? 0 : endPPOS.trim().split("\\s+").length;
String wordsBefore = words.subList(0, wordsBeforeCnt)
.stream()
.collect(Collectors.joining(" "));
String wordsAfter = words.subList(words.size() - wordsAfterCnt, words.size())
.stream()
.collect(Collectors.joining(" "));
List<String> homogeneousPart = words.subList(wordsBeforeCnt, words.size() - wordsAfterCnt);
Set<String> splitWords = new HashSet<>(Arrays.asList(",", "and"));
Set<String> simplifiedSentences = new HashSet<>();
StringBuilder sb = new StringBuilder(wordsBefore);
for (int i = 0; i < homogeneousPart.size(); i++) {
String part = homogeneousPart.get(i);
if (!splitWords.contains(part)) {
sb.append(" ").append(part);
if (i == homogeneousPart.size() - 1) {
sb.append(" ").append(wordsAfter).append(" ");
simplifiedSentences.add(sb.toString());
}
} else {
sb.append(" ").append(wordsAfter).append(" ");
simplifiedSentences.add(sb.toString());
sb = new StringBuilder(wordsBefore);
}
}
return simplifiedSentences;
所以例如句子
I love and kiss and adore my beautiful mom, clever dad and sister.
如果我们使用上面的 2 个正则表达式,将被简化为 9 个句子
I adore my clever dad .
I love my clever dad .
I love my sister .
I kiss my sister .
I kiss my clever dad .
I adore my sister .
I love my beautiful mom .
I adore my beautiful mom .
I kiss my beautiful mom .
这些代码仅适用于 3 个或更多同质词,因为 2 个词有很多异常。例如
Cat eats mouse, dog eats meat.
不能以这种方式简化句子。
推荐阅读
- python - python - 如何在python函数内的多个新创建的数据帧中返回一个非空数据帧?
- node.js - 在 React 中使用 npm 包时出现问题 - 说“TypeError:require is not a function”
- node.js - 如何创建应排除无关 dto 属性的单元测试?
- r - geom_segment 箭头设置 - 头部与线的宽度相同
- node.js - 将节点 js 网站托管到 Azure。默认路径/不工作
- android-studio - 通过选定的应用程序过滤 logcat *并*在 Android Studio 中添加自定义过滤器
- java - Reactor - 如何避免递归?
- python-3.x - yaml 转储没有引号的 python 字典
- python - 使用字典的值过滤数据框
- python - 如何从我从 Python 中的 GitHub 职位开放 API 以 .json 格式获得的列表中确定给定技术的职位数量?