spaCy/spacy/gold/corpus.py

87 lines
2.7 KiB
Python
Raw Normal View History

import random
2020-06-06 15:28:37 +03:00
from .. import util
from .example import Example
from ..tokens import DocBin
2020-06-06 15:28:37 +03:00
class Corpus:
2020-06-22 11:22:26 +03:00
"""An annotated corpus, reading train and dev datasets from
the DocBin (.spacy) format.
2020-06-06 15:28:37 +03:00
DOCS: https://spacy.io/api/goldcorpus
"""
2020-06-22 02:11:43 +03:00
def __init__(self, train_loc, dev_loc, limit=0):
2020-06-22 11:05:12 +03:00
"""Create a Corpus.
2020-06-06 15:28:37 +03:00
train (str / Path): File or directory of training data.
dev (str / Path): File or directory of development data.
2020-06-22 11:22:26 +03:00
limit (int): Max. number of examples returned
2020-06-22 11:05:12 +03:00
RETURNS (Corpus): The newly created object.
2020-06-06 15:28:37 +03:00
"""
2020-06-22 02:11:43 +03:00
self.train_loc = train_loc
self.dev_loc = dev_loc
2020-06-22 11:22:26 +03:00
self.limit = limit
2020-06-06 15:28:37 +03:00
@staticmethod
def walk_corpus(path):
path = util.ensure_path(path)
if not path.is_dir():
return [path]
paths = [path]
locs = []
seen = set()
for path in paths:
if str(path) in seen:
continue
seen.add(str(path))
if path.parts[-1].startswith("."):
continue
elif path.is_dir():
paths.extend(path.iterdir())
elif path.parts[-1].endswith(".spacy"):
2020-06-06 15:28:37 +03:00
locs.append(path)
return locs
def make_examples(self, nlp, reference_docs):
for reference in reference_docs:
predicted = nlp.make_doc(reference.text)
yield Example(predicted, reference)
2020-06-22 11:22:26 +03:00
def read_docbin(self, vocab, locs):
""" Yield training examples as example dicts """
2020-06-06 15:28:37 +03:00
i = 0
for loc in locs:
loc = util.ensure_path(loc)
if loc.parts[-1].endswith(".spacy"):
with loc.open("rb") as file_:
doc_bin = DocBin().from_bytes(file_.read())
yield from doc_bin.get_docs(vocab)
2020-06-22 11:22:26 +03:00
i += len(doc_bin) # TODO: should we restrict to EXACTLY the limit ?
if i >= self.limit:
break
2020-06-22 02:11:43 +03:00
def count_train(self, nlp):
2020-06-06 15:28:37 +03:00
"""Returns count of words in train examples"""
n = 0
i = 0
for example in self.train_dataset(nlp):
n += len(example.predicted)
2020-06-22 11:22:26 +03:00
if i >= self.limit:
2020-06-06 15:28:37 +03:00
break
i += 1
return n
def train_dataset(self, nlp, shuffle=True):
ref_docs = self.read_docbin(nlp.vocab, self.walk_corpus(self.train_loc))
examples = self.make_examples(nlp, ref_docs)
if shuffle:
examples = list(examples)
random.shuffle(examples)
2020-06-06 15:28:37 +03:00
yield from examples
def dev_dataset(self, nlp):
2020-06-22 01:24:15 +03:00
ref_docs = self.read_docbin(nlp.vocab, self.walk_corpus(self.dev_loc))
examples = self.make_examples(nlp, ref_docs)
2020-06-06 15:28:37 +03:00
yield from examples