Python 在函数中使用关键字参数使n-gram的生成成为可选的

Python 在函数中使用关键字参数使n-gram的生成成为可选的,python,function,nlp,keyword-argument,Python,Function,Nlp,Keyword Argument,我的xml文件的外观示例: <?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="folia.xsl"?> <FoLiA xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://ilk.uvt.nl/folia" xml:id="untitled" generator="libfolia-v0.10">

我的xml文件的外观示例:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="folia.xsl"?>
<FoLiA xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://ilk.uvt.nl/folia" xml:id="untitled" generator="libfolia-v0.10">
  <metadata type="native">
    <annotations>
      <token-annotation annotator="ucto" annotatortype="auto" datetime="2017-04-17T14:50:04" set="tokconfig-nl"/>
      <pos-annotation annotator="frog-mbpos-1.0" annotatortype="auto" datetime="2017-04-17T14:50:04" set="http://ilk.uvt.nl/folia/sets/frog-mbpos-cgn"/>
      <lemma-annotation annotator="frog-mblem-1.1" annotatortype="auto" datetime="2017-04-17T14:50:04" set="http://ilk.uvt.nl/folia/sets/frog-mblem-nl"/>
      <chunking-annotation annotator="frog-chunker-1.0" annotatortype="auto" datetime="2017-04-17T14:50:04" set="http://ilk.uvt.nl/folia/sets/frog-chunker-nl"/>
      <entity-annotation annotator="frog-mwu-1.0" annotatortype="auto" datetime="2017-04-17T14:50:04" set="http://ilk.uvt.nl/folia/sets/frog-mwu-nl"/>
      <entity-annotation annotator="frog-ner-1.0" annotatortype="auto" datetime="2017-04-17T14:50:04" set="http://ilk.uvt.nl/folia/sets/frog-ner-nl"/>
      <morphological-annotation annotator="frog-mbma-1.0" annotatortype="auto" datetime="2017-04-17T14:50:04" set="http://ilk.uvt.nl/folia/sets/frog-mbma-nl"/>
      <dependency-annotation annotator="frog-depparse-1.0" annotatortype="auto" set="http://ilk.uvt.nl/folia/sets/frog-depparse-nl"/>
    </annotations>
  </metadata>
  <text xml:id="untitled.text">
    <p xml:id="untitled.p.1">
      <s xml:id="untitled.p.1.s.1">
        <w xml:id="untitled.p.1.s.1.w.1" class="WORD">
          <t>De</t>
          <pos class="LID(bep,stan,rest)" confidence="0.999701" head="LID">
            <feat class="bep" subset="lwtype"/>
            <feat class="stan" subset="naamval"/>
            <feat class="rest" subset="npagr"/>
          </pos>
          <lemma class="de"/>
          <morphology>
            <morpheme>
              <t offset="0">de</t>
            </morpheme>
          </morphology>
        </w>
  • 您的搜索会忽略文档默认名称空间,因此它永远不会找到匹配的标记

  • 你的正则表达式真糟糕-

    "[^0-9] "                   # not-a-digit, followed by space
    "|"                         # OR
    "[^(\.|\,|\?|\:|\;|\!)]"    # bad syntax, but I think you mean not one of .,?:;!
    
    它将接受任何后跟空格的标点符号(非数字),或任何数字或其他字符或空格(非标点符号)!基本上,它唯一不匹配的是“完全由标点符号组成的字符串”

    我猜您真正想要的是“一个至少包含一个字母且没有非字母字符的字符串”,但请随意更正

  • 您的代码不包括
    ngrams()
    FreqDist()
    ,因此我无法测试它

  • 对于gram,count…来说,
    的缩进看起来不正确-我认为应该再缩进一级

  • 您有许多不必要的重复代码

  • 试试这个:

    # import re
    import xml.etree.ElementTree as ET
    
    FOLIA_NAMESPACE = {
        'default': 'http://ilk.uvt.nl/folia',
        'xlink':   'http://www.w3.org/1999/xlink'
    }
    
    def is_word(s):
        return s.isalpha()
        # as a regex:
        # return re.match("[A-Za-z]+$", s) is not None
    
    def load_words(folia_xml_file, is_word=is_word, namespace=FOLIA_NAMESPACE):
        root = ET.parse(folia_xml_file).getroot()
        tokens = root.findall(".//default:w/default:t", namespace)
        return [t.text for t in tokens if is_word(t.text)]
    
    def make_ngram_vectors(words, n_values=[1,2,3]):
        vectors = {}
        for n in n_values:
            grams = ngrams(words, n)
            fdist = FreqDist(grams)
            total = sum(count for gram,count in fdist.items())
            for gram,count in fdist.items():
                key = "w{}+{}".format(n, " ".join(gram))
                vectors[key] = count / total
        return vectors
    
    def main():
        words = load_words("romanfragment_frogged.xml")
        vectors = make_ngram_vectors(words, [1])
        print(vectors)
    
    if __name__ == "__main__":
        main()
    
    编辑: 如果查看xml文件顶部的
    标记,您将看到
    xmlns=
    (定义文档默认名称空间的链接,即哪些标记可用)和
    xmlns:xlink=
    (另一个xlink名称空间,它定义了
    xlink:href
    xlink:show
    -请参见)

    ElementTree喜欢内联扩展名称空间,使您的标记看起来像
    {http://ilk.uvt.nl/folia}w
    。通过传递名称空间dict,我们可以使用更可读的格式,比如
    default:w

    要获得与原始函数相同的输入/输出格式,可以使用如下包装函数:

    def word_ngrams(folia_xml_file, unigrams=True, bigrams=True, trigrams=True):
        # condense parameters into n_values
        n_values = []
        if unigrams:
            n_values.append(1)
        if bigrams:
            n_values.append(2)
        if trigrams:
            n_values.append(3)
        words = load_words(folia_xml_file)
        return make_ngram_vectors(words, n_values)
    
  • 您的搜索会忽略文档默认名称空间,因此它永远不会找到匹配的标记

  • 你的正则表达式真糟糕-

    "[^0-9] "                   # not-a-digit, followed by space
    "|"                         # OR
    "[^(\.|\,|\?|\:|\;|\!)]"    # bad syntax, but I think you mean not one of .,?:;!
    
    它将接受任何后跟空格的标点符号(非数字),或任何数字或其他字符或空格(非标点符号)!基本上,它唯一不匹配的是“完全由标点符号组成的字符串”

    我猜您真正想要的是“一个至少包含一个字母且没有非字母字符的字符串”,但请随意更正

  • 您的代码不包括
    ngrams()
    FreqDist()
    ,因此我无法测试它

  • 对于gram,count…来说,
    的缩进看起来不正确-我认为应该再缩进一级

  • 您有许多不必要的重复代码

  • 试试这个:

    # import re
    import xml.etree.ElementTree as ET
    
    FOLIA_NAMESPACE = {
        'default': 'http://ilk.uvt.nl/folia',
        'xlink':   'http://www.w3.org/1999/xlink'
    }
    
    def is_word(s):
        return s.isalpha()
        # as a regex:
        # return re.match("[A-Za-z]+$", s) is not None
    
    def load_words(folia_xml_file, is_word=is_word, namespace=FOLIA_NAMESPACE):
        root = ET.parse(folia_xml_file).getroot()
        tokens = root.findall(".//default:w/default:t", namespace)
        return [t.text for t in tokens if is_word(t.text)]
    
    def make_ngram_vectors(words, n_values=[1,2,3]):
        vectors = {}
        for n in n_values:
            grams = ngrams(words, n)
            fdist = FreqDist(grams)
            total = sum(count for gram,count in fdist.items())
            for gram,count in fdist.items():
                key = "w{}+{}".format(n, " ".join(gram))
                vectors[key] = count / total
        return vectors
    
    def main():
        words = load_words("romanfragment_frogged.xml")
        vectors = make_ngram_vectors(words, [1])
        print(vectors)
    
    if __name__ == "__main__":
        main()
    
    编辑: 如果查看xml文件顶部的
    标记,您将看到
    xmlns=
    (定义文档默认名称空间的链接,即哪些标记可用)和
    xmlns:xlink=
    (另一个xlink名称空间,它定义了
    xlink:href
    xlink:show
    -请参见)

    ElementTree喜欢内联扩展名称空间,使您的标记看起来像
    {http://ilk.uvt.nl/folia}w
    。通过传递名称空间dict,我们可以使用更可读的格式,比如
    default:w

    要获得与原始函数相同的输入/输出格式,可以使用如下包装函数:

    def word_ngrams(folia_xml_file, unigrams=True, bigrams=True, trigrams=True):
        # condense parameters into n_values
        n_values = []
        if unigrams:
            n_values.append(1)
        if bigrams:
            n_values.append(2)
        if trigrams:
            n_values.append(3)
        words = load_words(folia_xml_file)
        return make_ngram_vectors(words, n_values)
    

    此代码的单字符段需要缩进,这将清除您的逻辑。@robertlayton,识别错误是我在这里键入代码时产生的。我修好了,我的问题依然存在。或者你的意思是什么?@HughBothwell谢谢你的编辑,但这也是我在此处键入代码时犯的错误。是否可以获取一个简短的sample.xml文件进行解析?“青蛙”文本到底是什么——谷歌搜索毫无帮助?@HughBothwell是的,我刚刚添加了一个示例。Frog是荷兰人的NLP工具。因此,当我通过Frog传递文本时,它会被标记、解析、标记等。这段代码的单字符段需要缩进,这将清除您的逻辑。@robertlayton,识别错误是我在这里键入代码时出现的。我修好了,我的问题依然存在。或者你的意思是什么?@HughBothwell谢谢你的编辑,但这也是我在此处键入代码时犯的错误。是否可以获取一个简短的sample.xml文件进行解析?“青蛙”文本到底是什么——谷歌搜索毫无帮助?@HughBothwell是的,我刚刚添加了一个示例。Frog是荷兰人的NLP工具。因此,当我通过Frog传递文本时,它会被标记、解析、标记等。非常感谢您的帮助!事实上,我想要所有的单词,但不要数字和标点符号。我是编程新手,所以我不完全理解你的代码。我有几个问题。1.folia名称空间到底是什么,尤其是x-link?2.该函数需要适合特征提取系统,因此单词n-gram的向量是训练分类器的一个特征。我想不可能把你的4个函数合并成一个大函数?我太感谢你了。现在一切都清楚多了!我还有一个问题。我正在做一个单元测试,非常感谢你的帮助!事实上,我想要所有的单词,但不要数字和标点符号。我是编程新手,所以我不完全理解你的代码。我有几个问题。1.folia名称空间到底是什么,尤其是x-link?2.该函数需要适合特征提取系统,因此单词n-gram的向量是训练分类器的一个特征。我想不可能把你的4个函数合并成一个大函数?我太感谢你了。现在一切都清楚多了!我还有一个问题。我正在试着做一个单元测试