计算机是否可以通过用户提供的示例“学习”正则表达式?
澄清:
- 我不是想学正则表达式。
- 我想创建一个程序,该程序从用户交互提供的示例中“学习”正则表达式,也许可以通过从文本中选择部分或选择开始或结束标记来实现。
可能吗?我可以使用Google提供的算法,关键字等吗?
编辑:谢谢您的答案,但我对提供此功能的工具不感兴趣。我正在寻找理论信息,例如论文,教程,源代码,算法名称,因此我可以为自己创建一些东西。
计算机是否可以通过用户提供的示例“学习”正则表达式?
澄清:
可能吗?我可以使用Google提供的算法,关键字等吗?
编辑:谢谢您的答案,但我对提供此功能的工具不感兴趣。我正在寻找理论信息,例如论文,教程,源代码,算法名称,因此我可以为自己创建一些东西。
Answers:
《计算学习理论入门》一书包含了一种学习有限自动机的算法。由于每种常规语言都等效于有限的自动机,因此可以通过程序学习一些正则表达式。Kearns和Valiant展示了一些不可能学习有限自动机的情况。一个相关的问题是学习隐马尔可夫模型,这是可以描述字符序列的概率自动机。注意,编程语言中使用的大多数现代“正则表达式”实际上比正则语言要强,因此有时更难学习。
是的,有可能,我们可以从示例中生成正则表达式(文本->所需的提取)。这是一个工作正常的在线工具:http : //regex.inginf.units.it/
Regex Generator ++在线工具使用GP搜索算法从提供的示例中生成正则表达式。GP算法由多目标适应性驱动,从而导致更高的性能和更简单的解决方案结构(Occam的Razor)。该工具是的里雅斯特大学机器学习实验室(的里雅斯特大学)的演示应用程序。请在此处查看视频教程。
这是一个研究项目,因此您可以在此处阅读有关使用的算法的信息。
看哪!:-)
仅当所提供的示例很好地说明了问题时,才可以从示例中找到有意义的正则表达式/解决方案。考虑以下描述提取任务的示例,我们正在寻找特定的商品代码;示例为文本/提取对:
"The product code is 467-345A" -> "467-345A"
"The item 789-345B is broken" -> "789-345B"
一个(人类)家伙看着示例,可能会说:“项目代码是\ d ++-345 [AB]之类的东西”
当项目代码更宽松,但我们没有提供其他示例时,我们没有证明可以很好地理解问题。将人工生成的解决方案\ d ++-345 [AB]应用于以下文本时,它将失败:
"On the back of the item there is a code: 966-347Z"
为了更好地描述什么是匹配项,什么不是所需的匹配项,您必须提供其他示例:--ie:
"My phone is +39-128-3905 , and the phone product id is 966-347Z" -> "966-347Z"
电话号码不是产品ID,这可能是重要的证明。
没有任何计算机程序能够仅基于有效匹配列表来生成有意义的正则表达式。让我告诉你为什么。
假设您提供示例111111和999999,则计算机应生成:
(111111|999999)
(\d)\1{5}
[19]{6}
\d{6}
\b\d{6}\b
(?<!\d)\d{6}(?!\d)
如您所见,可以通过多种方式将示例概括为正则表达式。计算机构建可预测的正则表达式的唯一方法是要求您列出所有可能的匹配项。然后,它可以生成与这些匹配完全匹配的搜索模式。
如果您不想列出所有可能的匹配项,则需要更高级别的描述。这正是正则表达式旨在提供的。无需提供一长串的6位数字,您只需告诉程序匹配“任意六位数字”即可。在正则表达式语法中,它变为\ d {6}。
提供与正则表达式一样灵活的高级描述的任何方法,也将与正则表达式一样复杂。RegexBuddy之类的所有工具都可以使创建和测试高级描述变得更加容易。RegexBuddy允许您使用简单的英语构建块,而不是直接使用简洁的正则表达式语法。但是,它无法为您创建高级描述,因为它无法神奇地知道何时应该归纳您的示例,何时不应该将其归纳。
当然可以创建一个使用示例文本以及用户提供的准则来生成正则表达式的工具。设计此类工具的难点在于,它如何向用户请求所需的指导信息,而不会使该工具比正则表达式本身更难于学习,并且不将该工具限制于普通的正则表达式作业或简单的正则表达式。
是的,这肯定是“可能的”。这是伪代码:
string MakeRegexFromExamples(<listOfPosExamples>, <listOfNegExamples>)
{
if HasIntersection(<listOfPosExamples>, <listOfNegExamples>)
return <IntersectionError>
string regex = "";
foreach(string example in <listOfPosExamples>)
{
if(regex != "")
{
regex += "|";
}
regex += DoRegexEscaping(example);
}
regex = "^(" + regex + ")$";
// Ignore <listOfNegExamples>; they're excluded by definition
return regex;
}
问题是有无数的正则表达式将匹配示例列表。这段代码提供了集合中最简单/最愚蠢的正则表达式,基本上匹配了肯定示例列表中的所有内容(没有其他,包括任何否定示例)。
我想真正的挑战是找到与所有示例匹配的最短的正则表达式,但是即使那样,用户也必须提供非常好的输入以确保结果表达式是“正确的”。
我相信这个词是“归纳法”。您想归纳规则的语法。
我认为有限的示例集(正面或负面)是不可能的。但是,如果我没记错的话,可以咨询Oracle。(基本上,您必须让该程序向用户询问是/否问题,直到它满足为止。)
您可能想稍微玩一下这个站点,它很酷,听起来像您在说的一样:http : //txt2re.com
@Yuval是正确的。您正在研究计算学习理论或“归纳推理”。
这个问题比您想象的要复杂,因为“学习”的定义很简单。一个常见的定义是,学习者可以在需要时吐出答案,但最终必须要么吐出答案,要么总是吐出相同的答案。这假定输入的数量是无限的,并且绝对不会保证程序何时才能做出决定。此外,您无法确定何时做出决定,因为稍后它可能仍会输出一些不同的内容。
通过这个定义,我非常确定常规语言是可以学习的。根据其他定义,没有那么多...
我在Google和CiteSeer上进行了一些研究,发现了以下技术/论文:
同样,Dana Angluin的“从查询和反例中学习常规集”似乎很有希望,但是我找不到PS或PDF版本,只能找到引用和研讨会论文。
即使从理论上来说,这似乎也是一个棘手的问题。
如果一个人学习正则表达式是可能的,那么从根本上来说程序是可能的。但是,该程序将需要正确编程才能学习。幸运的是,这是一个相当有限的逻辑空间,因此它不会像教导程序能够看到对象或类似对象那样复杂。