使用Python从文本文件中创建n个单词的(随机)示例

使用Python从文本文件中创建n个单词的(随机)示例,python,text,random,nlp,named-entity-recognition,Python,Text,Random,Nlp,Named Entity Recognition,对于我的博士项目,我正在评估荷兰现有的所有命名实体重注册标记器。为了检查这些标记器的精确性和召回率,我想从我的语料库中随机抽取一个样本,手动注释所有命名实体。手动注释的样本将作为“金标准”,我将比较不同标记者的结果 我的文集由170本荷兰小说组成。我正在编写一个Python脚本,为每本小说生成一个特定数量的单词的随机样本(我将在后面用它来注释)。所有小说都将存储在同一目录中。以下脚本旨在为该目录中的每本小说生成n行的随机样本: import random import os import glo

对于我的博士项目,我正在评估荷兰现有的所有命名实体重注册标记器。为了检查这些标记器的精确性和召回率,我想从我的语料库中随机抽取一个样本,手动注释所有命名实体。手动注释的样本将作为“金标准”,我将比较不同标记者的结果

我的文集由170本荷兰小说组成。我正在编写一个Python脚本,为每本小说生成一个特定数量的单词的随机样本(我将在后面用它来注释)。所有小说都将存储在同一目录中。以下脚本旨在为该目录中的每本小说生成n行的随机样本:

import random
import os
import glob
import sys
import errno

path = '/Users/roelsmeets/Desktop/libris_corpus_clean/*.txt'
files = glob.glob(path)  

for text in files:
    try:
        with open(text, 'rt', encoding='utf-8') as f:
             # number of lines from txt file
             random_sample_input = random.sample(f.readlines(),100) 

    except IOError as exc:
    # Do not fail if a directory is found, just ignore it.
        if exc.errno != errno.EISDIR: 
            raise 


# This block of code writes the result of the previous to a new file
random_sample_output = open("randomsample", "w", encoding='utf-8') 
random_sample_input = map(lambda x: x+"\n", random_sample_input)
random_sample_output.writelines(random_sample_input)
random_sample_output.close()
此代码有两个问题:

  • 目前,我已将两本小说(.txt文件)放入目录中。但是代码只为每本小说中的一本输出一个随机样本

  • 目前,代码从每个.txt文件中随机抽取行数,但我更喜欢为每个.txt文件生成随机数的单词。理想情况下,我希望生成170.txt文件中每个文件的第一个或最后100个单词的示例。在这种情况下,样本根本不会是随机的;但到目前为止,我无法找到一种不使用随机库就创建样本的方法


  • 谁能给我一个解决这两个问题的建议?一般来说,我对Python和编程还是新手(我是一名文学学者),所以我很乐意学习不同的方法。非常感谢

    您只需将行拆分为单词,存储在某个位置,然后在读取所有文件并存储单词后,使用
    random.sample选择100。这就是我在下面代码中所做的。然而,我不太确定它是否能够处理170本小说,因为它可能会导致大量内存使用

    import random
    import os
    import glob
    import sys
    import errno
    
    path = '/Users/roelsmeets/Desktop/libris_corpus_clean/*.txt'
    files = glob.glob(path)
    words = []
    
    for text in files:
        try:
            with open(text, 'rt', encoding='utf-8') as f:
                 # number of lines from txt file
                 for line in f:
                     for word in line.split():
                         words.append(word)
    
        except IOError as exc:
        # Do not fail if a directory is found, just ignore it.
            if exc.errno != errno.EISDIR: 
                raise 
    
    random_sample_input = random.sample(words, 100)
    
    # This block of code writes the result of the previous to a new file
    random_sample_output = open("randomsample", "w", encoding='utf-8') 
    random_sample_input = map(lambda x: x+"\n", random_sample_input)
    random_sample_output.writelines(random_sample_input)
    random_sample_output.close()
    
    在上面的代码中,小说中的单词越多,在输出样本中表示的可能性就越大。这可能是也可能不是理想的行为。如果希望每本小说都有相同的思考,可以从中选择100个单词,添加到
    words
    变量中,然后在末尾从中选择100个单词。由于一次只能存储一本小说,因此它还将产生使用更少内存的副作用

    import random
    import os
    import glob
    import sys
    import errno
    
    path = '/Users/roelsmeets/Desktop/libris_corpus_clean/*.txt'
    files = glob.glob(path)
    words = []
    
    for text in files:
        try:
            novel = []
            with open(text, 'rt', encoding='utf-8') as f:
                 # number of lines from txt file
                 for line in f:
                     for word in line.split():
                         novel.append(word)
                 words.append(random.sample(novel, 100))
    
    
        except IOError as exc:
        # Do not fail if a directory is found, just ignore it.
            if exc.errno != errno.EISDIR: 
                raise 
    
    
    random_sample_input = random.sample(words, 100)
    
    # This block of code writes the result of the previous to a new file
    random_sample_output = open("randomsample", "w", encoding='utf-8') 
    random_sample_input = map(lambda x: x+"\n", random_sample_input)
    random_sample_output.writelines(random_sample_input)
    random_sample_output.close()
    
    第三个版本,这个版本将处理句子而不是单词,并保留标点符号。此外,无论大小,每本书在最后保留的句子上都有相同的“权重”。请记住,句子检测是由一种非常聪明但并非绝对正确的算法完成的

    import random
    import os
    import glob
    import sys
    import errno
    import nltk.data
    
    path = '/home/clement/Documents/randomPythonScripts/data/*.txt'
    files = glob.glob(path)
    
    sentence_detector = nltk.data.load('tokenizers/punkt/dutch.pickle')
    listOfSentences = []
    
    for text in files:
        try:
            with open(text, 'rt', encoding='utf-8') as f:
                fullText = f.read()
            listOfSentences += [x.replace("\n", " ").replace("  "," ").strip() for x in random.sample(sentence_detector.tokenize(fullText), 30)]
    
        except IOError as exc:
        # Do not fail if a directory is found, just ignore it.
            if exc.errno != errno.EISDIR:
                raise
    
    random_sample_input = random.sample(listOfSentences, 15)
    print(random_sample_input)
    
    # This block of code writes the result of the previous to a new file
    random_sample_output = open("randomsample", "w", encoding='utf-8')
    random_sample_input = map(lambda x: x+"\n", random_sample_input)
    random_sample_output.writelines(random_sample_input)
    random_sample_output.close()
    
    一些建议:

    随意选择句子,而不是单词或台词。如果输入的是语法句子,NE标记器会工作得更好。所以你需要使用分句器

    迭代文件时,
    random\u sample\u input
    只包含最后一个文件中的行。您应该移动将所选内容写入for循环内文件的代码块。然后,您可以将所选句子写入一个文件或单独的文件中。例如:

    out = open("selected-sentences.txt", "w")
    
    for text in files:
        try:
            with open(text, 'rt', encoding='utf-8') as f:
                 sentences = sentence_splitter.split(f.read())
                 for sentence in random.sample(sentences, 100):
                     print >> out, sentence
    
        except IOError as exc:
        # Do not fail if a directory is found, just ignore it.
            if exc.errno != errno.EISDIR: 
                raise 
    
    out.close()
    
    [编辑]以下是您应该如何使用NLTK分句器:

    import nltk.data
    sentence_splitter = nltk.data.load("tokenizers/punkt/dutch.pickle")
    text = "Dit is de eerste zin. Dit is de tweede zin."
    print sentence_splitter.tokenize(text)
    
    印刷品:

    ["Dit is de eerste zin.", "Dit is de tweede zin."]
    

    注意:您需要首先使用交互式控制台中的
    nltk.download()
    下载荷兰标记器。

    这解决了两个问题:

    import random
    import os
    import glob
    import sys
    import errno
    
    path = '/Users/roelsmeets/Desktop/libris_corpus_clean/*.txt'
    files = glob.glob(path)
    
    with open("randomsample", "w", encoding='utf-8') as random_sample_output:
        for text in files:
            try:
                with open(text, 'rt', encoding='utf-8') as f:
                    # number of lines from txt file
                    random_sample_input = random.sample(f.read().split(), 10)
    
            except IOError as exc:
                # Do not fail if a directory is found, just ignore it.
                if exc.errno != errno.EISDIR:
                raise
    
            # This block of code writes the result of the previous to a new file
            random_sample_input = map(lambda x: x + "\n", random_sample_input)
            random_sample_output.writelines(random_sample_input)
    

    塔克斯!这可能会对随机单词采样起作用。然而,vpekar强调,最好使用语法句子,而不是行或词,所以这就是我现在正在研究的内容。对于“句子[0],我得到了一个“语法错误:无效语法”+=CurrentSession^SyntaxError:无效语法现在我得到两个名称错误:名称“novel”和名称“words”未定义。现在我得到一个“ValueError:Sample大于population”。即使我将其转换为random.sample(ListofCentenses,50)或random.sample(ListofCentenses,10)。这很奇怪。在我的第一个版本的代码中,100行(不是句子)从来都不是这样。你有什么解释吗?我建议使用合适的分句器,因为有很多特殊情况,比如“史密斯先生”、“美国”等等。谢谢!你说的随机句子是对的。但是,当我运行您建议的代码时。我得到“NameError:name”语句\u splitter“未定义”。是否有一个模块可以从中导入句子分割器?可能使用nltk中的句子标记器?当我导入nltk.data并定义变量句子分割器=nltk.data.load(“标记器/punkt/dutch.pickle”)并随后运行代码时,我得到以下AttributeError:“PunktSentenceTokenizer”对象没有属性“split”。你知道为什么吗?应该是“标记化”,而不是“拆分”。是的,我知道了。但是现在我得到了一个“TypeError:expected string或bytes like object”关于“句子=句子分割器.标记化(f.readlines())”的问题,为什么会这样?Thanx,这很有效。还有人建议我应该用句子而不是单词,这是对的。所以现在我正在深入研究这个问题。