使用Python从文本文件中创建n个单词的(随机)示例
对于我的博士项目,我正在评估荷兰现有的所有命名实体重注册标记器。为了检查这些标记器的精确性和召回率,我想从我的语料库中随机抽取一个样本,手动注释所有命名实体。手动注释的样本将作为“金标准”,我将比较不同标记者的结果 我的文集由170本荷兰小说组成。我正在编写一个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
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()
此代码有两个问题:
谁能给我一个解决这两个问题的建议?一般来说,我对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,这很有效。还有人建议我应该用句子而不是单词,这是对的。所以现在我正在深入研究这个问题。