【问题标题】:Split text file at sentence boundary在句子边界拆分文本文件
【发布时间】:2011-08-02 23:50:29
【问题描述】:

我必须处理一个文本文件(电子书)。我想处理它,以便每行有一个句子(“换行符分隔的文件”,是吗?)。我将如何使用 sed UNIX 实用程序来完成这项任务?它是否具有“句子边界”的符号,就像“单词边界”的符号一样(我认为 GNU 版本有)。请注意,句子可以以句号、省略号、问号或感叹号结尾,最后两个组合在一起(例如,?、!、!?、!!!!! 都是有效的“句子终止符”)。输入文件的格式设置为某些句子包含必须删除的换行符。

我想到了一个像s/...|. |[!?]+ |/\n/g 这样的脚本(未转义以便更好地阅读)。但它不会删除句子中的换行符。

在 C# 中怎么样?如果我使用像 sed 这样的正则表达式会不会快得多? (我想不是)。还有其他更快的方法吗?

无论哪种方式(sed 或 C#)都可以。谢谢。

【问题讨论】:

    标签: c# sed nlp text-segmentation


    【解决方案1】:

    Regex 是我使用了很长时间的一个不错的选择。

    一个非常适合我的正则表达式是

     string[] sentences = Regex.Split(sentence, @"(?<=['""A-Za-z0-9][\.\!\?])\s+(?=[A-Z])");
    

    但是,正则表达式效率不高。此外,虽然该逻辑适用于理想情况,但在生产环境中并不适用。

    例如,如果我的文字是,

    美国是一个美妙的民族。大多数人都觉得住在那里很开心。

    正则表达式方法将通过在每个周期拆分将其分类为 5 个句子。但我们知道,从逻辑上讲,它应该只分成两个句子。

    这就是让我寻找机器学习技术的原因,最后 SharpNLP 对我来说效果很好。

     private string mModelPath = @"C:\Users\ATS\Documents\Visual Studio 2012\Projects\Google_page_speed_json\Google_page_speed_json\bin\Release\";
     private OpenNLP.Tools.SentenceDetect.MaximumEntropySentenceDetector mSentenceDetector;
     private string[] SplitSentences(string paragraph)
        {
            if (mSentenceDetector == null)
            {
                mSentenceDetector = new OpenNLP.Tools.SentenceDetect.EnglishMaximumEntropySentenceDetector(mModelPath + "EnglishSD.nbin");
            }
    
            return mSentenceDetector.SentenceDetect(paragraph);
        }
    

    在此示例中,我使用了 SharpNLP,其中我使用了 EnglishSD.nbin - 一个用于句子检测的预训练模型。

    现在,如果我在这个方法上应用相同的输入,它会完美地将文本分成两个逻辑句子。

    您甚至可以使用 SharpNLP 项目进行标记化、POSTag、Chuck 等。

    For step by step integration of SharpNLP into your C# application, read through the detailed article I have written.会为你讲解与代码sn-ps的集成。

    谢谢

    【讨论】:

    • 您的正则表达式不会将该示例拆分为 5 个句子,它会找到两个。你试过了吗?我赞成一种看似有效的快速而肮脏的句子检测。
    【解决方案2】:

    句子拆分是一个重要的问题,机器学习算法已经针对它开发了。但是在[.\?!]+ 和大写字母[A-Z] 之间分割空格可能是一个很好的启发式方法。首先用tr 删除换行符,然后应用RE:

    tr '\r\n' ' ' | sed 's/\([.?!]\)\s\s*\([A-Z]\)/\1\n\2/g'
    

    输出应该是每行一个句子。如果发现错误,请检查输出并优化 RE。 (例如,mr. Ed 将被错误地处理。也许编译一个此类缩写的列表。)

    C# 还是 sed 更快只能通过实验来确定。

    【讨论】:

      【解决方案3】:

      你可以用这样的东西来提取句子:

      var sentences = Regex.Matches(input, @"[\w ,]+[\.!?]+")
      foreach (Match match in sentences)
      {
        Console.WriteLine(match.Value);
      }
      

      这应该匹配包含单词、空格和逗号并以(任意数量的)句点、感叹号和问号结尾的句子。

      【讨论】:

        【解决方案4】:

        你可以查看我的教程http://code.google.com/p/graph-expression/wiki/SentenceSplitting 基本思想是在每次拆分时都有拆分字符和不可能的前置/后置条件。 Tji 的简单启发式非常有效。

        【讨论】:

          【解决方案5】:

          您感兴趣的任务通常被称为“句子分割”。正如 larsmans 所说,这是一个不平凡的问题,但启发式方法通常表现得相当好,至少对于英语来说是这样。

          听起来您主要对英语感兴趣,因此已经介绍的正则表达式启发式可能足以满足您的需求。如果您想要一个更准确的解决方案(以稍微复杂一点为代价),您可以考虑使用开源 NLP 框架 LingPipe。我用 LingPipe 运气不错,我用过几次。

          有关分句的详细教程,请参阅http://alias-i.com/lingpipe/demos/tutorial/sentences/read-me.html

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-02-11
            • 1970-01-01
            • 2013-04-28
            • 2017-04-18
            • 1970-01-01
            • 1970-01-01
            • 2019-11-12
            • 2011-04-12
            相关资源
            最近更新 更多