代码之家  ›  专栏  ›  技术社区  ›  Joel

判断一个句子是否是问句

nlp
  •  19
  • Joel  · 技术社区  · 14 年前

    例如,客户可能会搜索“how do I track my order”(注意不要打问号)。

    我猜最直接的问题应该符合特定的语法。

    非常简单的猜测方法:

    START WORDS = [who, what, when, where, why, how, is, can, does, do]
    
    isQuestion(sentence):
      sentence ends with '?'
      OR sentence starts with one of START WORDS
    

    有没有一个库能比我简单的猜测方法做得更好?我的方法有什么改进吗?

    6 回复  |  直到 13 年前
        1
  •  18
  •   Community CDub    8 年前

    另请参见: How to find out if a sentence is a question (interrogative)?

    在一个问题的句法分析中(通过像nltk这样的工具箱获得),正确的结构将采用以下形式:

    (SBARQ (WH+ (W+) ...)
           (SQ ...*
               (V+) ...*)
           (?))
    

    因此,使用任何一个可用的语法解析器,一个带有SBARQ节点的树(可选地)将成为一个指示输入是一个问题的指标。WH+节点(WHNP/WHADVP/WHADJP)包含问句干(who/what/when/where/why/how),SQ包含倒装短语。

    即。:

    (SBARQ 
      (WHNP 
        (WP What)) 
      (SQ 
        (VBZ is) 
        (NP 
          (DT the) 
          (NN question)))
      (. ?))
    

    当然,前面有很多子句会导致语法错误(这可以解决),写得很差的问题也是如此。例如,这篇文章的标题“如何找出一个句子是不是一个问题?”会有一个SBARQ,但不是SQ。

        2
  •  16
  •   Community CDub    5 年前

    你需要一种更高级的语言分析来完成这个任务。需要证据吗?可以。。。

    它们是雌鹿。

    有志者事竟成。

    到时候,我就跳!

    为什么没有。我没有五分镍币。

        3
  •  10
  •   Skarab    14 年前

    找出一个句子是否是一个问题并不是一件容易的事,因为人们提问的方式有很多种,其中很多都不遵循语法规则。因此很难找到一个好的检测规则集。在这种情况下,我会进行机器学习,并使用带注释的文本语料库训练算法(创建语料库和选择特征集可能需要一些时间)。基于机器学习的识别应该比基于规则的方法提供更好的回忆。以下是一个逐步说明:

    1. 人工创建列车数据集:获取一个带注释的文本集合(如果它是一个问题或不是一个信息)或自己创建这样一个语料库(它应该是100多个文档,许多问题不能是简单的问题)
    2. 找出最重要的特征-提取演讲的部分,5W1H(what,which,…,how),获得每个句子中动词的位置,以及其他对识别问题有用的东西
    3. 根据提取的信息,为每个特征句子(你需要正反两个例子)创建一个向量,例如。,

    4. 使用向量 train a machine learning algorithm ,例如,最大熵, SVM Wekka Knime )

        4
  •  9
  •   tchrist    14 年前

    要确定疑问句的起始词,你应该通过一个大的文本语料库寻找以一个字母结尾的句子 ? ,找出最常见的开头词。

    你没有想到的几个,包括:我、现在、过去、曾经、可能、可能、可能、可能、可能、将、将、将、应该、已经、曾经和曾经。或许也该随时而去。同时考虑IN,AT,TO,FROM,and ON,以及UNDER和OVER。这一切都取决于你所拥有的查询系统的种类,以及你希望为你的用户提供多少自然语言查询的自由度。

    同样,你应该检查你自己的所有问题,人们已经在同一个角度,找出他们的问题实际上 结束于 以帮助识别不存在的相似的。

    这应该会找到很多疑问句;祈使句也是一种可能性吗?

    维基百科上有几篇关于 question answering natural language search engines . 这两个都有你可能想要的参考资料。您也可以浏览这些PDF文件:

    START Natural Language Question Answering System 从麻省理工学院来似乎很有趣。

        5
  •  8
  •   Fred Foo    14 年前

    为了支持JohnFx的答案,情况变得更糟了。以下是明确的问题:

    • 你有什么问题吗
    • 这个答案够了吗
    • 一个问题,那是什么

    然后您会发现用户开始输入以下类型的查询:

    这是个问题吗?从句法上说,没有,但它确实值得一个很容易被称为答案的回答。(这类查询可能非常常见,具体取决于您的用户群。)

        6
  •  1
  •   AppDreamer    7 年前

    我试了一下。。。我的目标是做一些轻量级的事情,不需要额外的库,并且让每个开发人员都能够控制一些必要的元素——比如填充某些字符,只使用负缩略词作为第一个单词的位置,并允许常见的问题元素。我创建了两个函数,当你从一个angular6html页面传入一个值时,它在我的大多数情况下都做得很好。。。

    我不把“不要”作为一个开始词,因为它可以是一个陈述和一个问题一样多的次数。你不觉得吗?

    角度HTML:

              <input matInput type="text" placeholder="{{Prompt}}" [(ngModel)]="value">
    

    .ts功能:

      isQuestion(sentence: string = this.value){
        var q_elements : string[] = ["who", "what", "when", "where", "why", "how", "?"];
        var q_starters : string[] = ["which", "won't", "can't", "isn't", "aren't", "is", "do", "does", "will", "can", "is"];
        var temp = sentence.toLowerCase();
        var padChars : string[] = ["?", "-", "/"];
        var i : number = 0;
        for (i=0; i < padChars.length; i++) {
          temp = this.padChar(temp, padChars[i]);
        }
        var splitted = temp.split(" ");
        // console.log(splitted);
        if (q_starters.includes(splitted[0])) {
          // console.log('found a question with a starter');
          return true;
        } else {
          return q_elements.some(function (v) {
            return splitted.indexOf(v) >= 0;
          });
        }
      }
    
      padChar(myString : string, myChar : string) {
        var position = myString.indexOf(myChar);
        var output : string = myString;
        while(position > 0 && position < output.length) {
          if (output.charAt(position - 1) != " ") {
            output = [output.slice(0, position), " ", output.slice(position)].join('');
            position = output.indexOf(myChar, position);
          }
          if (position + 1 < output.length) {
            if (output.charAt(position + 1) != " ") {
              output = [output.slice(0, (position + 1)), " ", output.slice(position + 1)].join('');
              position = output.indexOf(myChar, position);
            }
          }
          position = output.indexOf(myChar, position + 1);
        }
        return output;
      }