25

我正在分析一个包含大量人类可读字符串的大型公共数据集,这些字符串显然是由一些常规(在形式语言理论意义上)语法生成的。

逐个查看这些字符串的集合以查看模式并不难;不幸的是,这些独特的字符串中约有 24,000 个被分为 33 个类别和 1714 个子类别,因此手动执行此操作有些痛苦。

基本上,我正在寻找一种现有的算法(最好使用现有的参考实现)来获取任意字符串列表,并尝试推断出一些最小(对于最小的合理定义)跨正则表达式集,这些正则表达式可用于生成它们(即从该语法生成​​的语言的有限字符串集合中推断出常规语法)。

我考虑过重复贪婪的最长公共子串消除,但这只是到目前为止,因为它不会折叠除了完全匹配之外的任何东西,所以不会检测到,比如说,在特定位置的不同数字字符串的常见模式语法。

蛮力强制任何不属于公共子字符串消除的东西是可能的,但在计算上可能不可行。(此外,我已经考虑过了,子字符串消除可能存在“阶段排序”和/或“局部最小值”问题,因为您可能会进行贪婪的子字符串匹配,最终迫使最终语法压缩得更少/最小,即使它最初似乎是最好的减少)。

4

2 回答 2

23

是的,事实证明这确实存在;所需要的是学术上称为DFA 学习算法的算法,其示例包括:

  • Angluin 的 L*
  • L*(在列中添加反例)
  • 卡恩斯/瓦齐拉尼
  • 里维斯特 / Schapire
  • 荷兰*
  • 常规正负推断 (RPNI)
  • 德乐特2
  • Biermann & Feldman 算法
  • Biermann & Feldman 算法(使用 SAT 求解)

上面的源码是libalf,一个开源的 C++ 自动机学习算法框架;在这本教科书中至少可以找到其中一些算法的描述。在 MATLAB 的gittoolbox中也有语法推理算法(包括 DFA 学习)的实现。

由于这个问题之前已经提出并且过去没有得到令人满意的回答,我正在评估这些算法并将更新更多关于它们有用性的信息,除非在该领域具有更多专业知识的人首先这样做(更可取)。

注意:我现在接受我自己的答案,但如果有人可以提供一个更好的答案,我会很乐意接受。

进一步说明:我决定采用使用自定义代码的路线,因为使用通用算法对于我正在使用的数据来说有点矫枉过正。我把这个答案留在这里,以防其他人需要它,如果我评估这些,我会更新。

于 2013-03-20T09:31:25.143 回答
0

我唯一能建议的就是稍微玩一下Nltk(Python 的自然语言工具包),看看它是否至少可以识别重复出现的模式。

您可能会研究的另一件事是MALLET(用于统计自然语言处理、文档分类、聚类、主题建模、信息提取等的基于 Java 的包)。

Perl 有一个叫做LinkParser的东西,但它似乎需要你提供实际语法的表示(另一方面,它带有大量不同的模型,所以它可能会被硬塞到帮助你对样本进行排序)。

Gate可能允许您从语料库中的记录子集创建示例,并可能从这些记录中对语法进行逆向工程。

最后,查看CRAN 存储库以获取特定于文本的包

于 2013-03-20T13:41:30.750 回答