如果我运行以下代码:
from nltk.corpus import wordnet
for ss in wordnet.all_synsets():
if ' - ' in ss.definition():
print(ss, ss.definition())
我得到一个定义列表,如下所示:
Synset('abstemious.a.01') sparing in consumption of especially food and drink; - John Galsworthy
Synset('ascetic.s.02') practicing great self-denial; - William James
Synset('dead-on.s.01') accurate and to the point; ; - Peter S.Prescott
Synset('used_to.s.01') in the habit; ; ; - Henry David Thoreau
Synset('predaceous.s.02') living by or given to victimizing others for personal gain; ; - Peter S. Prescott; - W.E.Swinton
Synset('passive.a.01') lacking in energy or will; - George Meredith
Synset('resistless.s.02') offering no resistance; ; - Theodore Roosevelt
Synset('alcoholic.s.02') addicted to alcohol; - Carl Van Doren
Synset('reductive.s.01') characterized by or causing diminution or curtailment; - R.H.Rovere
Synset('mounted.s.02') decorated with applied ornamentation; often used in combination; - F.V.W.Mason
Synset('coordinated.s.02') being dexterous in the use of more than one set of muscle movements; - Mary McCarthy
Synset('light-fingered.s.01') having nimble fingers literally or figuratively; especially for stealing or picking pockets; - Harry Hansen; - Time
Synset('bumbling.s.01') lacking physical movement skills, especially with the hands; ; ; ; - Mary H. Vorse
Synset('uninfluenced.s.01') not influenced or affected; - V.L.Parrington
我担心这些作者(如 - Theodore Roosevelt
)可能不应该出现在定义中?我认为这些是 ss.examples()
列表中最后一个示例的作者,因为它们不在双引号内,所以没有被解析为示例的一部分。
6条答案
按热度按时间rqdpfwrv1#
我认为这些是
ss.examples()
列表中最后一个示例的作者,因为它们不在双引号内,所以没有被解析为示例的一部分。是的,你是对的。在原始的WNDB format数据中,"gloss"紧跟在
|
字符后面。一个gloss可能包含定义和/或示例,但没有指定它们是如何分隔的。这是你列表上的第一个(你可能需要滚动到右侧查看gloss):这里是解析它的代码:
nltk/nltk/corpus/reader/wordnet.py
第1436行至第1441行
| | # 从gloss中解析出定义和示例 |
| | columns_str, gloss=data_file_line.strip().split("|") |
| | definition=re.sub(r"["].?["]", "", gloss).strip() |
| | examples=re.findall(r'"([^"])"', gloss) |
| | forexampleinexamples: |
| | synset._examples.append(example) |
这当然可以改进。
dced5bon2#
前言
我将把这篇文章分成多个评论,以便更好地组织我的想法。对于大量的文本转储,我提前道歉。所有标记为“Breakdown”的部分都详细解释了它们前面的正则表达式,为了简洁起见,可以跳过它们。我认为它们仍然很重要,以便我的逻辑和推理更容易被检查。谢谢阅读。<3
这个问题实际上是:#2265 的延续。
假设
虽然没有明确定义,但我相信我们可以对gloss的结构做出一些假设,并根据这些假设定义新的正则表达式。
|
(分隔gloss的开始);
(分隔gloss的部分);
's 也可以出现在示例/引用的中间,当它们这样做时,不应该被视为分隔符;
's 也可以出现在额外注解的中间,当它们这样做时,不应该被视为分隔符(可选,请参阅下面的“从gloss中提取额外注解”)"
's 包裹,除非示例是一个引用"
's 包裹,然后立即跟一个破折号(可选:一个空格),以及来源的名字,如:"quoted_text"- origin_name
或:"quoted_text"-origin_name
origin_name
可以是任何长度的字符串,可能包含空白,但 应该由分隔符终止(
和)
包裹他们让你和我出丑
我经常说 应该是因为WordNet 3.0的gloss部分偶尔不完美,会给这些假设带来问题。WordNet 3.1解决了大部分问题,但我的测试还远未完成。不幸的是,update to WordNet 3.1 似乎已经被无限期推迟了。一个解决方案可能是手动更新WordNet 3.0的gloss部分,并将纠正推送到nltk_data ,这希望不会引发与WordNet 3.1更新相同的问题。我会在nltk_data中开始一个new issue ,看看它能走多远。
除此之外,我相信我们仍然可以改进正在进行的解析工作,尤其是对于引用,尽管它最终可能会变成一种交换一组问题为另一组问题的情况,直到数据正确为止。
dgsult0t3#
提出的解决方案:
提取所有gloss部分,直到只剩下定义
关键概念是,给定正确格式的输入,我们可以删除一切可以明显识别的内容,直到剩下的gloss部分必须是定义。
分隔符和查找周围内容
这些是以下正则表达式中常见的部分,以确保在尝试捕获的任何内容两侧都有匹配的分隔符。
从文件行中提取gloss
我们需要从文件行中提取gloss部分并进行一些设置以准备解析。通过在
|
上分割并去除空格,我们已经去除了开头和结尾的分隔符。我们将在开头和结尾添加新的分隔符,以便lookarounds能够正确匹配。从gloss中提取例子/引述
捕获并提取文本中正确分隔且符合假设条件的例子或引述的所有内容。捕获的文本包括 Package
"
's,可以从例子中剥离并保留在引述中。分解
第一个主要部分是
"[^"\n]+?"
,它将匹配任何用"
's正确 Package 的内容。接下来是一个非捕获组,这样后续的标记就可以单独量化而不被捕获。在这个非捕获组中,我们有-.+?
来匹配破折号和一个或多个字符(origin_name
)。由于并非所有的例子都是引述,所以-
和origin_name
是可选的,用*?
表示。从gloss中提取额外的注解(可选)
捕获并提取文本中正确分隔且符合假设条件的其他注解的所有内容。捕获的文本包括括号。
分解
虽然不是非常易读,因为括号是特殊字符,必须转义或放入字符集中,但表达式本身很简单。该表达式匹配所有用括号正确 Package 的内容,其中没有另一个括号在外部 Package 括号之间。有些定义以一组匹配的括号开始,以不同的一组匹配的括号结束,但中间也有完全位于括号之外的内容,例如WordNet 3.0的第334行上的
'crocketed'
:如果正则表达式中的否定字符集不包括打开/关闭括号,那么对这个定义的解释将错误地将其视为其他注解。
可选?
额外注解部分被标记为“可选”,因为我不确定如何处理gloss的部分。到目前为止,我所知道的
Synset
类的结构没有处理这些额外注解的结构。原始的WNDB format文档只提到了定义和例子。在我看来,这些用括号包裹的部分不适合放在定义中,而更适合放在例子中。值得注意:
;
's 不能出现在额外注解的中间,那么这一部分就是可选的,它们可以作为定义提取出来。;
's 可以出现在额外注解的中间,那么这一部分就不是可选的,它们必须作为附加步骤提取出来并追加。从gloss中删除多余的分隔符
捕获所有多余的分隔符序列。
分解
匹配所有情况,其中一个或多个分隔符紧跟在另一个分隔符之后。
+
量词是贪婪的,以尽可能一次捕获尽可能多的多余分隔符。将除定义外的所有其他内容从gloss中提取出来作为定义
捕获并提取文本中正确分隔的所有内容作为定义。由于我们在分隔符之间匹配任何内容而没有任何额外限制,因此我们必须确保文本格式正确(没有多余的分隔符,每个可能的分隔符都应该是一个分隔符)。
分解
这是所有正则表达式中最简单的一个,它匹配分隔符之间的所有内容。
rta7y2nd4#
将所有部件组合在一起
现在我们已经处理了我们的假设和表达式,我们可以设计一个解决方案。我已经准备了一个示例实现。在这个例子中,我还假设
;
不能出现在其他注解中,并且其他注解应该被视为定义,使得单独提取其他注解变得不再必要。需要注意的是:
■
分隔,以避免混淆。实现
输入
输出
t3irkdon5#
感谢你提供的精彩分析、示例列表和建议的解决方案。如果NLTK的wordnet模块继续进行维护,我认为你的解决方案会很有用。然而,如果NLTK转向基于WN-LMF的wordnets,那么在这里的努力可以应用到WNDB到LMF转换脚本中,特别是关于提取示例的部分。
我还有一些建议:
使用
str.partition()
代替str.split()
,以避免在gloss中出现|
字符时出现ValueError。如果一个例子中有两组引号,这种方法将无法正常工作,因为它只会获取第一个引号的开始和最后一个引号的结束,例如(虚构的例子):
但是,这些问题可能甚至不会出现在数据中,而且不太可能出现新的WNDB来源来挑战系统的健壮性,所以不值得投入太多精力。最好检测剩余的问题并为它们编写特殊情况。
dgiusagp6#
我已经考虑了这个问题更久。我不确定我们是否应该尝试提取多个定义。从 WNDB docs 中(强调):
每个同义词集包含一个解释。解释用竖线(|)表示,后面跟着一个文本字符串,直到行尾。解释可能包含定义、一个或多个示例句子,或者两者都有。
此外,有时候有多个定义,但这些倾向于被组合成一个大的定义,例如在更新后的 Open English WordNet 中,所以也许我们应该遵循先例。
如果我们只是说示例是直到第一个清晰的示例或字符串结束之前的所有内容,哪个先到就是哪个,那么处理括号等就容易多了。我只在 PWN 3.0 中看到一个
;
在括号内发生,而且它后面没有跟随"
:当
;
实际上并不分隔定义而是列表中的项目时,这也很有帮助。例如(缩写):data.noun:01725240 ... | extinct marine reptiles: plesiosaurs; nothosaurs
一旦我们确定定义在哪里结束,我们就可以允许其他类型的分隔符在示例之间进行一些变化:
也就是说,在示例中,字符
;
、:
、,
、.
和 `` (空格)都用于分隔单个示例。还有两个特殊情况,其中一个结束引号紧接着是一个单词字符,有不同的解决方法:
data.noun:04203889 ... | the commodities purchased from stores; "she loaded her shopping into the car"women carrying home shopping didn't give me a second glance"
data.verb:01148961 ... | take sides for or against; "Who are you widing with?"; "I"m siding against the current candidate"
一些其他有趣的示例:
or
作为示例分隔符,句号结尾:data.noun:05677340 ... | an intuitive awareness; "he has a feel for animals" or "it's easy when you get the feel of it";
data.verb:00781000 ... | continue talking; "I know it's hard," he continued, "but there is no choice"; "carry on--pretend we are not in the room"
e.g.
或as in e.g.
之前的例子:data.adj:00347707 ... | incapable of being changed or moved or undone; e.g. "frozen prices"; "living on fixed incomes"
data.noun:06469597 ... | a summary list; as in e.g. "a news roundup"
这些涉及到格式错误的gloss字符串的长尾巴,因此尝试将模式泛化为处理它们需要花费大量的工作,收益却很少。此外,一个标准(我在另一个项目中有这个标准,但可能与NLTK无关)是底层数据保持不变,所以我必须接受一些精度损失来识别示例。