18

可以使用 Java 进行文本简化的最佳工具是什么?

以下是文本简化的示例:

John, who was the CEO of a company, played golf.
                       ↓
John played golf. John was the CEO of a company.
4

4 回答 4

34

我认为您的问题是将复杂或复合句子转换为简单句子的任务。基于文献句型,一个简单的句子是由一个独立的从句构成的。复合复合句由至少两个从句构成。此外,从句必须有主语和动词。
因此,您的任务是将句子拆分为构成句子的子句。

来自斯坦福 CoreNLP 的依赖解析是将复合句和复杂句拆分为简单句的完美工具。您可以在线尝试演示
从您的示例句子中,我们将获得斯坦福类型依赖 (SD)表示法的解析结果,如下所示:

nsubj(CEO-6, John-1)
nsubj(played-11, John-1)
cop(CEO-6, was-4)
det(CEO-6, the-5)
rcmod(John-1, CEO-6)
det(company-9, a-8)
prep_of(CEO-6, company-9)
root(ROOT-0, played-11)
dobj(played-11, golf-12)

子句可以从关系(在 SD 中)中识别出哪个类别是主题,例如nsubjnsubjpass。参见Stanford Dependency Manual
基本子句可以从head作为动词部分和从属作为主语部分提取。从上面的 SD 中,有两个基本条款,即

  • 约翰首席执行官
  • 约翰出场

获得基本从句后,您可以添加另一个部分,使您的从句成为一个完整而有意义的句子。为此,请查阅斯坦福依赖手册

顺便说一句,您的问题可能与从句子中找到有意义的子句有关


回复第三条评论:

一旦你得到了一对主语和动词,即nsubj(CEO-6, John-1),获取所有与该依赖项有链接的依赖项,除了属于主题的任何依赖项,然后从这些依赖项中提取唯一的单词。

基于示例,nsubj(CEO-6, John-1)如果你从 开始遍历John-1,你会得到nsubj(played-11, John-1),但你应该忽略它,因为它的类别是主题。

下一步是从CEO-6零件遍历。你会得到

cop(CEO-6, was-4)
det(CEO-6, the-5)
rcmod(John-1, CEO-6)
prep_of(CEO-6, company-9)

从上面的结果中,你得到了新的依赖项来遍历(即找到另一个was-4, the-5, company-9在头或依赖项中的依赖项)。
现在你的依赖是

cop(CEO-6, was-4)
det(CEO-6, the-5)
rcmod(John-1, CEO-6)
prep_of(CEO-6, company-9)
det(company-9, a-8)

在这一步中,您已经完成了对链接到的所有依赖项的遍历nsubj(CEO-6, John-1)。接下来,从所有的 head 和dependent 中提取单词,然后根据附加到这些单词的数字按升序排列单词。这个数字表示原句中的词序。

John was the CEO a company

我们的新句子缺少一个部分,即of。这部分隐藏在prep_of(CEO-6, company-9). 如果您阅读Stanford Dependency Manual ,则SD有两种,折叠式和非折叠式。请阅读它们以了解为什么这of是隐藏的以及如何获得该隐藏部分的词序。

用同样的方法,你会得到第二句话

John played golf

于 2012-03-07T17:51:34.713 回答
7

我认为可以为这种情况的基本案例设计一个非常简单的算法,而现实世界的案例可能太多了,这样的方法会变得不守规矩:)

仍然我认为我应该大声思考并编写我的方法,并且可能添加一些 python 代码。我的基本想法是从第一原理中得出一个解决方案,主要是通过明确公开我们的模型来了解实际发生的情况。在我们手动和从 SCRATCH 做一个之前,不要依赖其他理论、模型、库。


目标:给定一个句子,从中提取子句。

示例:公司首席执行官约翰打高尔夫球。

预期产出:约翰是公司的首席执行官。约翰打高尔夫球。


这是我在这里发生的事情的模型,以模型假设的形式写出来:(公理?)

MA1。简单的句子可以通过插入子句来扩展。MA2。子句是对一个或多个实体的限定/修改(附加信息)。MA3。要插入子句,我们在要扩展的实体旁边放一个逗号(提供更多信息)并附加子句,我将其称为扩展 - 并在扩展结束时放置另一个逗号。

给定这个模型,该算法至少可以直接解决简单的情况。

  1. DETECT:给定一个句子,通过在句子中查找一对逗号来检测它是否有扩展子句。
  2. EXTRACT:如果找到两个逗号,生成两个句子: 2.1 EXTRACT-BASE:基句:删除两个逗号之间的所有内容,得到基句。2.2 EXTRACT-EXTENSION:扩展句:取扩展句中的所有内容,用它前面的单词替换“谁”。那是你的第二句话。
  3. PRINT:实际上你应该先打印扩展句,因为基本句依赖于它。

嗯,这就是我们的算法。是的,这听起来像一个黑客。这是。但是我现在正在学习的是,如果您在一个程序中使用技巧,那就是一种 hack,如果它可以处理更多的东西,那就是一种技术。

因此,让我们将情况扩大和复杂一点。

复合案例:示例 2。公司首席执行官约翰与首席财务官拉姆一起打高尔夫球。

在我写这篇文章的时候,我注意到我省略了 CFO 的“谁是”这个词!这给我们带来了一个复杂的情况,即我们的算法将失败。在去那里之前,让我创建一个更简单的 2 版本,它将起作用。

示例 3. 公司首席执行官约翰与首席财务官拉姆一起打高尔夫球。

示例 4. 公司首席执行官约翰与首席财务官拉姆一起打高尔夫球。

等等我们还没有完成!

示例 5。当时担任 CEO 的 John 和担任 CFO 的 Ram 玩高尔夫,这是一款引人入胜的游戏。

为此,我需要扩展我的模型假设:

MA4。可以同样扩展多个实体,但不应引起混淆,因为扩展子句出现在被通知的实体旁边。(例如帐户 3)

MA5。'who was' 短语可以省略,因为它可以被听众推断出来。(例如帐户 4)

MA6。一些实体是人,它们将使用“谁”进行扩展,而一些实体是事物,使用“哪个”进行扩展。这些扩展头中的任何一个都可以省略。

现在我们如何在我们的算法中处理这些复杂性?

尝试这个:

  1. SPLIT-SENTENCE-INTO-BASE-AND-EXTENSIONS:如果句子包含逗号,则查找以下逗号,并将其间的任何内容提取到扩展句中。继续,直到您找不到更多的结束逗号或开始逗号。此时,您应该有带有基本句子和一个或多个扩展句子的列表。

  2. PROCESS_EXTENSIONS:对于每个扩展,如果它有'who is'或'which is',在扩展词条前用名称替换它。如果扩展名没有“谁是”或“哪个是”,则放置前导词 and 和 an is。

  3. PRINT:首先是所有扩展句,然后是基本句。

不可怕。

当我在接下来的几天里有时间时,我将添加一个 python 实现。

谢谢

拉维·安纳斯瓦米

于 2013-01-11T22:34:42.333 回答
4

在一般情况下,您不太可能使用任何已知算法来解决这个问题——这正在进入强大的人工智能领域。即使是人类也无法很好地解析语法!

请注意,关于您简化的程度以及您愿意做出的假设,这个问题非常模糊。您可以进一步举例说明:

约翰被假定为一个存在的名字。约翰的种族不详。约翰过去曾打过高尔夫球。假定高尔夫是指称为高尔夫的球类运动,但约翰所玩的高尔夫的变体是未知的。在过去的某个时候,约翰是一家公司的首席执行官。CEO 被认为是指公司上下文中的“首席执行官”,但没有具体说明。公司不详。

万一教训不明显:你越是试图确定单词的确切含义,你开始打开的蠕虫罐头就越多……需要类似人类的判断和解释水平才能知道何时该停止。

您也许可以使用各种基于 Java 的 NLP 工具解决一些更简单的情况:请参阅Is there a good natural language processing library

于 2012-03-07T06:39:07.283 回答
1

我相信AlchemyApi是您最好的选择。尽管如此,您仍然需要做很多工作才能完全满足您的需求,并且大多数评论员已经告诉您,您很可能不会获得 100% 的质量结果。

于 2012-03-07T13:40:32.767 回答