From ba1bf8ae727a4a5ea7fb4207fa12f5acc319972b Mon Sep 17 00:00:00 2001 From: Paul O'Leary McCann Date: Wed, 6 Jul 2022 18:40:05 +0900 Subject: [PATCH 01/10] First take at dimension inference This follows the pattern used in the Biaffine Parser, which uses an init function to get the size only after the tok2vec is available. This works at first, but serialization fails with an error. --- spacy/ml/models/coref.py | 74 +++++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 20 deletions(-) diff --git a/spacy/ml/models/coref.py b/spacy/ml/models/coref.py index 660ef68c544..4967e7f23f8 100644 --- a/spacy/ml/models/coref.py +++ b/spacy/ml/models/coref.py @@ -1,6 +1,6 @@ from typing import List, Tuple -from thinc.api import Model, chain +from thinc.api import Model, chain, get_width from thinc.api import PyTorchWrapper, ArgsKwargs from thinc.types import Floats2d from thinc.util import torch, xp2torch, torch2xp @@ -25,12 +25,48 @@ def build_wl_coref_model( tok2vec_size: int = 768, # tok2vec size ): # TODO add model return types - # dim = tok2vec.maybe_get_dim("n0") + + nI = None with Model.define_operators({">>": chain}): - coref_clusterer = PyTorchWrapper( + coref_clusterer = Model( + "coref_clusterer", + forward=coref_forward, + init=coref_init, + dims={"nI": nI}, + attrs={ + "distance_embedding_size": distance_embedding_size, + "hidden_size": hidden_size, + "depth": depth, + "dropout": dropout, + "antecedent_limit": antecedent_limit, + "antecedent_batch_size": antecedent_batch_size, + }, + ) + + coref_model = tok2vec >> coref_clusterer + return coref_model + + +def coref_init(model: Model, X=None, Y=None): + if model.layers: + return + + if X is not None and model.has_dim("nI") is None: + model.set_dim("nI", get_width(X)) + + hidden_size = model.attrs["hidden_size"] + depth = model.attrs["depth"] + dropout = model.attrs["dropout"] + antecedent_limit = model.attrs["antecedent_limit"] + antecedent_batch_size = model.attrs["antecedent_batch_size"] + distance_embedding_size = model.attrs["distance_embedding_size"] + + PyTorchWrapper = registry.get("layers", "PyTorchWrapper.v2") + model._layers = [ + PyTorchWrapper( CorefClusterer( - tok2vec_size, + model.get_dim("nI"), distance_embedding_size, hidden_size, depth, @@ -41,13 +77,15 @@ def build_wl_coref_model( convert_inputs=convert_coref_clusterer_inputs, convert_outputs=convert_coref_clusterer_outputs, ) - coref_model = tok2vec >> coref_clusterer - return coref_model + # TODO maybe we need mixed precision and grad scaling? + ] -def convert_coref_clusterer_inputs( - model: Model, X: List[Floats2d], is_train: bool -): +def coref_forward(model: Model, X, is_train: bool): + return model.layers[0](X, is_train) + + +def convert_coref_clusterer_inputs(model: Model, X: List[Floats2d], is_train: bool): # The input here is List[Floats2d], one for each doc # just use the first # TODO real batching @@ -55,7 +93,7 @@ def convert_coref_clusterer_inputs( word_features = xp2torch(X, requires_grad=is_train) # TODO fix or remove type annotations - def backprop(args: ArgsKwargs): #-> List[Floats2d]: + def backprop(args: ArgsKwargs): # -> List[Floats2d]: # convert to xp and wrap in list gradients = torch2xp(args.args[0]) return [gradients] @@ -63,9 +101,7 @@ def backprop(args: ArgsKwargs): #-> List[Floats2d]: return ArgsKwargs(args=(word_features,), kwargs={}), backprop -def convert_coref_clusterer_outputs( - model: Model, inputs_outputs, is_train: bool -): +def convert_coref_clusterer_outputs(model: Model, inputs_outputs, is_train: bool): _, outputs = inputs_outputs scores, indices = outputs @@ -115,9 +151,7 @@ def __init__( self.pw = DistancePairwiseEncoder(dist_emb_size, dropout) pair_emb = dim * 3 + self.pw.shape - self.a_scorer = AnaphoricityScorer( - pair_emb, hidden_size, n_layers, dropout - ) + self.a_scorer = AnaphoricityScorer(pair_emb, hidden_size, n_layers, dropout) self.lstm = torch.nn.LSTM( input_size=dim, hidden_size=dim, @@ -156,10 +190,10 @@ def forward(self, word_features: torch.Tensor) -> Tuple[torch.Tensor, torch.Tens a_scores_lst: List[torch.Tensor] = [] for i in range(0, len(words), batch_size): - pw_batch = pw[i:i + batch_size] - words_batch = words[i:i + batch_size] - top_indices_batch = top_indices[i:i + batch_size] - top_rough_scores_batch = top_rough_scores[i:i + batch_size] + pw_batch = pw[i : i + batch_size] + words_batch = words[i : i + batch_size] + top_indices_batch = top_indices[i : i + batch_size] + top_rough_scores_batch = top_rough_scores[i : i + batch_size] # a_scores_batch [batch_size, n_ants] a_scores_batch = self.a_scorer( From bd17c38b745771de7589a48646c0951df1c30a8d Mon Sep 17 00:00:00 2001 From: Paul O'Leary McCann Date: Wed, 6 Jul 2022 18:58:22 +0900 Subject: [PATCH 02/10] It works! Was missing the serialization-related code from biaffine. --- spacy/ml/models/coref.py | 5 ++-- spacy/pipeline/coref.py | 57 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/spacy/ml/models/coref.py b/spacy/ml/models/coref.py index 4967e7f23f8..377f0223645 100644 --- a/spacy/ml/models/coref.py +++ b/spacy/ml/models/coref.py @@ -44,8 +44,9 @@ def build_wl_coref_model( }, ) - coref_model = tok2vec >> coref_clusterer - return coref_model + model = tok2vec >> coref_clusterer + model.set_ref("coref_clusterer", coref_clusterer) + return model def coref_init(model: Model, X=None, Y=None): diff --git a/spacy/pipeline/coref.py b/spacy/pipeline/coref.py index cd07f80e8f1..ef74a83a411 100644 --- a/spacy/pipeline/coref.py +++ b/spacy/pipeline/coref.py @@ -6,6 +6,7 @@ from thinc.api import set_dropout_rate, to_categorical from itertools import islice from statistics import mean +import srsly from .trainable_pipe import TrainablePipe from ..language import Language @@ -13,7 +14,7 @@ from ..errors import Errors from ..tokens import Doc from ..vocab import Vocab -from ..util import registry +from ..util import registry, from_disk, from_bytes from ..ml.models.coref_util import ( create_gold_scores, @@ -316,3 +317,57 @@ def initialize( assert len(X) > 0, Errors.E923.format(name=self.name) self.model.initialize(X=X, Y=Y) + + # Store the input dimensionality. nI and nO are not stored explicitly + # for PyTorch models. This makes it tricky to reconstruct the model + # during deserialization. So, besides storing the labels, we also + # store the number of inputs. + coref_clusterer = self.model.get_ref("coref_clusterer") + self.cfg["nI"] = coref_clusterer.get_dim("nI") + + def from_bytes(self, bytes_data, *, exclude=tuple()): + deserializers = { + "cfg": lambda b: self.cfg.update(srsly.json_loads(b)), + "vocab": lambda b: self.vocab.from_bytes(b, exclude=exclude), + } + from_bytes(bytes_data, deserializers, exclude) + + self._initialize_from_disk() + + model_deserializers = { + "model": lambda b: self.model.from_bytes(b), + } + from_bytes(bytes_data, model_deserializers, exclude) + + return self + + def from_disk(self, path, exclude=tuple()): + def load_model(p): + try: + with open(p, "rb") as mfile: + self.model.from_bytes(mfile.read()) + except AttributeError: + raise ValueError(Errors.E149) from None + + deserializers = { + "cfg": lambda p: self.cfg.update(srsly.read_json(p)), + "vocab": lambda p: self.vocab.from_disk(p, exclude=exclude), + } + from_disk(path, deserializers, exclude) + + self._initialize_from_disk() + + model_deserializers = { + "model": load_model, + } + from_disk(path, model_deserializers, exclude) + + return self + + def _initialize_from_disk(self): + # The PyTorch model is constructed lazily, so we need to + # explicitly initialize the model before deserialization. + model = self.model.get_ref("coref_clusterer") + if model.has_dim("nI") is None: + model.set_dim("nI", self.cfg["nI"]) + self.model.initialize() From f67c1735c554be4afafeffbeb10613309d4cb4d0 Mon Sep 17 00:00:00 2001 From: Paul O'Leary McCann Date: Wed, 6 Jul 2022 18:58:57 +0900 Subject: [PATCH 03/10] Remove tok2vec_size from coref --- spacy/ml/models/coref.py | 1 - spacy/pipeline/coref.py | 1 - 2 files changed, 2 deletions(-) diff --git a/spacy/ml/models/coref.py b/spacy/ml/models/coref.py index 377f0223645..2b38beef783 100644 --- a/spacy/ml/models/coref.py +++ b/spacy/ml/models/coref.py @@ -22,7 +22,6 @@ def build_wl_coref_model( # pairs to keep per mention after rough scoring antecedent_limit: int = 50, antecedent_batch_size: int = 512, - tok2vec_size: int = 768, # tok2vec size ): # TODO add model return types diff --git a/spacy/pipeline/coref.py b/spacy/pipeline/coref.py index ef74a83a411..6685b112e29 100644 --- a/spacy/pipeline/coref.py +++ b/spacy/pipeline/coref.py @@ -31,7 +31,6 @@ default_config = """ [model] @architectures = "spacy.Coref.v1" -tok2vec_size = 768 distance_embedding_size = 20 hidden_size = 1024 depth = 1 From b59b924e497ac0674d897e08ee99541ff62d7335 Mon Sep 17 00:00:00 2001 From: Paul O'Leary McCann Date: Wed, 6 Jul 2022 19:22:19 +0900 Subject: [PATCH 04/10] Use normal PyTorchWrapper in coref --- spacy/ml/models/coref.py | 1 - 1 file changed, 1 deletion(-) diff --git a/spacy/ml/models/coref.py b/spacy/ml/models/coref.py index 2b38beef783..7ad493ac0ac 100644 --- a/spacy/ml/models/coref.py +++ b/spacy/ml/models/coref.py @@ -62,7 +62,6 @@ def coref_init(model: Model, X=None, Y=None): antecedent_batch_size = model.attrs["antecedent_batch_size"] distance_embedding_size = model.attrs["distance_embedding_size"] - PyTorchWrapper = registry.get("layers", "PyTorchWrapper.v2") model._layers = [ PyTorchWrapper( CorefClusterer( From b0800ea855957da1f26e0c8fa4dbf581f79cf121 Mon Sep 17 00:00:00 2001 From: Paul O'Leary McCann Date: Wed, 6 Jul 2022 19:22:37 +0900 Subject: [PATCH 05/10] Do dimension inference in span predictor --- spacy/ml/models/span_predictor.py | 50 ++++++++++++++++++++++++----- spacy/pipeline/span_predictor.py | 52 +++++++++++++++++++++++++++++-- 2 files changed, 92 insertions(+), 10 deletions(-) diff --git a/spacy/ml/models/span_predictor.py b/spacy/ml/models/span_predictor.py index d44e632bdc7..55a966c1dea 100644 --- a/spacy/ml/models/span_predictor.py +++ b/spacy/ml/models/span_predictor.py @@ -13,7 +13,6 @@ @registry.architectures("spacy.SpanPredictor.v1") def build_span_predictor( tok2vec: Model[List[Doc], List[Floats2d]], - tok2vec_size: int = 768, hidden_size: int = 1024, distance_embedding_size: int = 64, conv_channels: int = 4, @@ -24,23 +23,58 @@ def build_span_predictor( # TODO add model return types with Model.define_operators({">>": chain, "&": tuplify}): - span_predictor = PyTorchWrapper( + span_predictor = Model( + "span_predictor", + forward=span_predictor_forward, + init=span_predictor_init, + dims={"nI": nI}, + attrs={ + "distance_embedding_size": distance_embedding_size, + "hidden_size": hidden_size, + "conv_channels": conv_channels, + "window_size": window_size, + "max_distance": max_distance, + "prefix": prefix, + }, + ) + head_info = build_get_head_metadata(prefix) + model = (tok2vec & head_info) >> span_predictor + model.set_ref("span_predictor", span_predictor) + + return model + +def span_predictor_init(model: Model, X=None, Y=None): + if model.layers: + return + + if X is not None and model.has_dim("nI") is None: + model.set_dim("nI", get_width(X)) + + hidden_size = model.attrs["hidden_size"] + distance_embedding_size = model.attrs["distance_embedding_size"] + conv_channels = model.attrs["conv_channels"] + window_size = model.attrs["window_size"] + max_distance = model.attrs["max_distance"] + prefix = model.attrs["prefix"] + + model._layers = [ + PyTorchWrapper( SpanPredictor( - tok2vec_size, + model.get_dim("nI"), hidden_size, distance_embedding_size, conv_channels, window_size, max_distance, + prefix, ), convert_inputs=convert_span_predictor_inputs, ) - # TODO use proper parameter for prefix - head_info = build_get_head_metadata(prefix) - model = (tok2vec & head_info) >> span_predictor - - return model + # TODO maybe we need mixed precision and grad scaling? + ] +def span_predictor_forward(model: Model, X, is_train: bool): + return model.layers[0](X, is_train) def convert_span_predictor_inputs( model: Model, X: Tuple[List[Floats2d], Tuple[List[Ints1d], List[Ints1d]]], is_train: bool diff --git a/spacy/pipeline/span_predictor.py b/spacy/pipeline/span_predictor.py index d7e96a4b294..eed6ce9f812 100644 --- a/spacy/pipeline/span_predictor.py +++ b/spacy/pipeline/span_predictor.py @@ -5,6 +5,7 @@ from thinc.api import Model, Config, Optimizer, CategoricalCrossentropy from thinc.api import set_dropout_rate, to_categorical from itertools import islice +import srsly from .trainable_pipe import TrainablePipe from ..language import Language @@ -13,7 +14,7 @@ from ..scorer import Scorer, doc2clusters from ..tokens import Doc from ..vocab import Vocab -from ..util import registry +from ..util import registry, from_bytes, from_disk from ..ml.models.coref_util import ( MentionClusters, @@ -23,7 +24,6 @@ default_span_predictor_config = """ [model] @architectures = "spacy.SpanPredictor.v1" -tok2vec_size = 768 hidden_size = 1024 distance_embedding_size = 64 conv_channels = 4 @@ -274,3 +274,51 @@ def initialize( assert len(X) > 0, Errors.E923.format(name=self.name) self.model.initialize(X=X, Y=Y) + + + def from_bytes(self, bytes_data, *, exclude=tuple()): + deserializers = { + "cfg": lambda b: self.cfg.update(srsly.json_loads(b)), + "vocab": lambda b: self.vocab.from_bytes(b, exclude=exclude), + } + from_bytes(bytes_data, deserializers, exclude) + + self._initialize_from_disk() + + model_deserializers = { + "model": lambda b: self.model.from_bytes(b), + } + from_bytes(bytes_data, model_deserializers, exclude) + + return self + + def from_disk(self, path, exclude=tuple()): + def load_model(p): + try: + with open(p, "rb") as mfile: + self.model.from_bytes(mfile.read()) + except AttributeError: + raise ValueError(Errors.E149) from None + + deserializers = { + "cfg": lambda p: self.cfg.update(srsly.read_json(p)), + "vocab": lambda p: self.vocab.from_disk(p, exclude=exclude), + } + from_disk(path, deserializers, exclude) + + self._initialize_from_disk() + + model_deserializers = { + "model": load_model, + } + from_disk(path, model_deserializers, exclude) + + return self + + def _initialize_from_disk(self): + # The PyTorch model is constructed lazily, so we need to + # explicitly initialize the model before deserialization. + model = self.model.get_ref("span_predictor") + if model.has_dim("nI") is None: + model.set_dim("nI", self.cfg["nI"]) + self.model.initialize() From da81a90d64dbb156ba3abafcf7aaa6ff8d126e81 Mon Sep 17 00:00:00 2001 From: Paul O'Leary McCann Date: Wed, 6 Jul 2022 19:29:27 +0900 Subject: [PATCH 06/10] Span predictor leftovers --- spacy/ml/models/span_predictor.py | 7 +++---- spacy/pipeline/span_predictor.py | 6 ++++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/spacy/ml/models/span_predictor.py b/spacy/ml/models/span_predictor.py index 55a966c1dea..4e394ed7826 100644 --- a/spacy/ml/models/span_predictor.py +++ b/spacy/ml/models/span_predictor.py @@ -1,6 +1,6 @@ from typing import List, Tuple -from thinc.api import Model, chain, tuplify +from thinc.api import Model, chain, tuplify, get_width from thinc.api import PyTorchWrapper, ArgsKwargs from thinc.types import Floats2d, Ints1d from thinc.util import torch, xp2torch, torch2xp @@ -22,6 +22,8 @@ def build_span_predictor( ): # TODO add model return types + nI = None + with Model.define_operators({">>": chain, "&": tuplify}): span_predictor = Model( "span_predictor", @@ -34,7 +36,6 @@ def build_span_predictor( "conv_channels": conv_channels, "window_size": window_size, "max_distance": max_distance, - "prefix": prefix, }, ) head_info = build_get_head_metadata(prefix) @@ -55,7 +56,6 @@ def span_predictor_init(model: Model, X=None, Y=None): conv_channels = model.attrs["conv_channels"] window_size = model.attrs["window_size"] max_distance = model.attrs["max_distance"] - prefix = model.attrs["prefix"] model._layers = [ PyTorchWrapper( @@ -66,7 +66,6 @@ def span_predictor_init(model: Model, X=None, Y=None): conv_channels, window_size, max_distance, - prefix, ), convert_inputs=convert_span_predictor_inputs, ) diff --git a/spacy/pipeline/span_predictor.py b/spacy/pipeline/span_predictor.py index eed6ce9f812..b5f25cd8168 100644 --- a/spacy/pipeline/span_predictor.py +++ b/spacy/pipeline/span_predictor.py @@ -275,6 +275,12 @@ def initialize( assert len(X) > 0, Errors.E923.format(name=self.name) self.model.initialize(X=X, Y=Y) + # Store the input dimensionality. nI and nO are not stored explicitly + # for PyTorch models. This makes it tricky to reconstruct the model + # during deserialization. So, besides storing the labels, we also + # store the number of inputs. + span_predictor = self.model.get_ref("span_predictor") + self.cfg["nI"] = span_predictor.get_dim("nI") def from_bytes(self, bytes_data, *, exclude=tuple()): deserializers = { From baeb35f31be3c42720482ea5f9e0ee068524c5a0 Mon Sep 17 00:00:00 2001 From: Paul O'Leary McCann Date: Mon, 11 Jul 2022 20:03:29 +0900 Subject: [PATCH 07/10] Add type annotations for internal models --- spacy/ml/models/coref.py | 5 +++-- spacy/ml/models/span_predictor.py | 9 +++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/spacy/ml/models/coref.py b/spacy/ml/models/coref.py index a69c6673eaf..8befeaef384 100644 --- a/spacy/ml/models/coref.py +++ b/spacy/ml/models/coref.py @@ -22,11 +22,11 @@ def build_wl_coref_model( # pairs to keep per mention after rough scoring antecedent_limit: int = 50, antecedent_batch_size: int = 512, - nI = None + nI=None, ) -> Model[List[Doc], Tuple[Floats2d, Ints2d]]: with Model.define_operators({">>": chain}): - coref_clusterer = Model( + coref_clusterer: Model[List[Floats2d], Tuple[Floats2d, Ints2d]] = Model( "coref_clusterer", forward=coref_forward, init=coref_init, @@ -81,6 +81,7 @@ def coref_init(model: Model, X=None, Y=None): def coref_forward(model: Model, X, is_train: bool): return model.layers[0](X, is_train) + def convert_coref_clusterer_inputs(model: Model, X: List[Floats2d], is_train: bool): # The input here is List[Floats2d], one for each doc # just use the first diff --git a/spacy/ml/models/span_predictor.py b/spacy/ml/models/span_predictor.py index ca76e5a4a95..8a93dcf8e34 100644 --- a/spacy/ml/models/span_predictor.py +++ b/spacy/ml/models/span_predictor.py @@ -25,7 +25,7 @@ def build_span_predictor( nI = None with Model.define_operators({">>": chain, "&": tuplify}): - span_predictor = Model( + span_predictor: Model[List[Floats2d], List[Floats2d]] = Model( "span_predictor", forward=span_predictor_forward, init=span_predictor_init, @@ -44,6 +44,7 @@ def build_span_predictor( return model + def span_predictor_init(model: Model, X=None, Y=None): if model.layers: return @@ -72,9 +73,11 @@ def span_predictor_init(model: Model, X=None, Y=None): # TODO maybe we need mixed precision and grad scaling? ] + def span_predictor_forward(model: Model, X, is_train: bool): return model.layers[0](X, is_train) + def convert_span_predictor_inputs( model: Model, X: Tuple[List[Floats2d], Tuple[List[Ints1d], List[Ints1d]]], @@ -95,7 +98,9 @@ def backprop(args: ArgsKwargs) -> Tuple[List[Floats2d], None]: else: head_ids_tensor = xp2torch(head_ids[0], requires_grad=False) - argskwargs = ArgsKwargs(args=(sent_ids_tensor, word_features, head_ids_tensor), kwargs={}) + argskwargs = ArgsKwargs( + args=(sent_ids_tensor, word_features, head_ids_tensor), kwargs={} + ) return argskwargs, backprop From f9c82e249c8fd8e74114c95140b67e6557c39e08 Mon Sep 17 00:00:00 2001 From: Paul O'Leary McCann Date: Mon, 11 Jul 2022 20:14:36 +0900 Subject: [PATCH 08/10] Update error number This was changed by merge --- spacy/pipeline/coref.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spacy/pipeline/coref.py b/spacy/pipeline/coref.py index 40ff92fcbb9..2532a9fbf0b 100644 --- a/spacy/pipeline/coref.py +++ b/spacy/pipeline/coref.py @@ -289,7 +289,7 @@ def get_loss( span = example.predicted.char_span(start_char, end_char) if span is None: # TODO log more details - raise IndexError(Errors.E1043) + raise IndexError(Errors.E1044) cc.append((span.start, span.end)) clusters.append(cc) From 1baa334b8a49c8dd7b821af5ba3dc6fae6be02de Mon Sep 17 00:00:00 2001 From: Paul O'Leary McCann Date: Tue, 12 Jul 2022 14:07:40 +0900 Subject: [PATCH 09/10] Make get_clusters_from_doc return spans in order There's no guarantee about the order in which SpanGroup keys will come out, so access them in sorted order when doing comparisons. --- spacy/ml/models/coref_util.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spacy/ml/models/coref_util.py b/spacy/ml/models/coref_util.py index 1a6bc636499..e374360097c 100644 --- a/spacy/ml/models/coref_util.py +++ b/spacy/ml/models/coref_util.py @@ -147,7 +147,9 @@ def get_clusters_from_doc(doc) -> List[List[Tuple[int, int]]]: ints are char spans, to be tokenization independent. """ out = [] - for key, val in doc.spans.items(): + keys = sorted(list(doc.spans.keys())) + for key in keys: + val = doc.spans[key] cluster = [] for span in val: From 07e8556cc342236e1d1f6f733dab943ce88fbb80 Mon Sep 17 00:00:00 2001 From: Paul O'Leary McCann Date: Tue, 12 Jul 2022 14:08:35 +0900 Subject: [PATCH 10/10] Remove config from coref tests This was necessary when the tok2vec_size option was necessary. --- spacy/tests/pipeline/test_coref.py | 15 ++++++--------- spacy/tests/pipeline/test_span_predictor.py | 10 ++++------ 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/spacy/tests/pipeline/test_coref.py b/spacy/tests/pipeline/test_coref.py index 3e297ddcdf1..b29c4243d6e 100644 --- a/spacy/tests/pipeline/test_coref.py +++ b/spacy/tests/pipeline/test_coref.py @@ -36,9 +36,6 @@ # fmt: on -CONFIG = {"model": {"@architectures": "spacy.Coref.v1", "tok2vec_size": 64}} - - @pytest.fixture def nlp(): return English() @@ -67,7 +64,7 @@ def test_not_initialized(nlp): @pytest.mark.skipif(not has_torch, reason="Torch not available") def test_initialized(nlp): - nlp.add_pipe("coref", config=CONFIG) + nlp.add_pipe("coref") nlp.initialize() assert nlp.pipe_names == ["coref"] text = "She gave me her pen." @@ -79,7 +76,7 @@ def test_initialized(nlp): @pytest.mark.skipif(not has_torch, reason="Torch not available") def test_initialized_short(nlp): - nlp.add_pipe("coref", config=CONFIG) + nlp.add_pipe("coref") nlp.initialize() assert nlp.pipe_names == ["coref"] text = "Hi there" @@ -89,7 +86,7 @@ def test_initialized_short(nlp): @pytest.mark.skipif(not has_torch, reason="Torch not available") def test_coref_serialization(nlp): # Test that the coref component can be serialized - nlp.add_pipe("coref", last=True, config=CONFIG) + nlp.add_pipe("coref", last=True) nlp.initialize() assert nlp.pipe_names == ["coref"] text = "She gave me her pen." @@ -111,7 +108,7 @@ def test_overfitting_IO(nlp): for text, annot in TRAIN_DATA: train_examples.append(Example.from_dict(nlp.make_doc(text), annot)) - nlp.add_pipe("coref", config=CONFIG) + nlp.add_pipe("coref") optimizer = nlp.initialize() test_text = TRAIN_DATA[0][0] doc = nlp(test_text) @@ -166,7 +163,7 @@ def test_tokenization_mismatch(nlp): train_examples.append(eg) - nlp.add_pipe("coref", config=CONFIG) + nlp.add_pipe("coref") optimizer = nlp.initialize() test_text = TRAIN_DATA[0][0] doc = nlp(test_text) @@ -228,7 +225,7 @@ def test_whitespace_mismatch(nlp): eg.predicted = nlp.make_doc(" " + text) train_examples.append(eg) - nlp.add_pipe("coref", config=CONFIG) + nlp.add_pipe("coref") optimizer = nlp.initialize() test_text = TRAIN_DATA[0][0] doc = nlp(test_text) diff --git a/spacy/tests/pipeline/test_span_predictor.py b/spacy/tests/pipeline/test_span_predictor.py index 8a6c62011ad..8083783cd66 100644 --- a/spacy/tests/pipeline/test_span_predictor.py +++ b/spacy/tests/pipeline/test_span_predictor.py @@ -44,8 +44,6 @@ ] # fmt: on -CONFIG = {"model": {"@architectures": "spacy.SpanPredictor.v1", "tok2vec_size": 64}} - @pytest.fixture def nlp(): @@ -76,7 +74,7 @@ def test_not_initialized(nlp): @pytest.mark.skipif(not has_torch, reason="Torch not available") def test_span_predictor_serialization(nlp): # Test that the span predictor component can be serialized - nlp.add_pipe("span_predictor", last=True, config=CONFIG) + nlp.add_pipe("span_predictor", last=True) nlp.initialize() assert nlp.pipe_names == ["span_predictor"] text = "She gave me her pen." @@ -109,7 +107,7 @@ def test_overfitting_IO(nlp): pred.spans[key] = [pred[span.start : span.end] for span in spans] train_examples.append(eg) - nlp.add_pipe("span_predictor", config=CONFIG) + nlp.add_pipe("span_predictor") optimizer = nlp.initialize() test_text = TRAIN_DATA[0][0] doc = nlp(test_text) @@ -173,7 +171,7 @@ def test_tokenization_mismatch(nlp): train_examples.append(eg) - nlp.add_pipe("span_predictor", config=CONFIG) + nlp.add_pipe("span_predictor") optimizer = nlp.initialize() test_text = TRAIN_DATA[0][0] doc = nlp(test_text) @@ -218,7 +216,7 @@ def test_whitespace_mismatch(nlp): eg.predicted = nlp.make_doc(" " + text) train_examples.append(eg) - nlp.add_pipe("span_predictor", config=CONFIG) + nlp.add_pipe("span_predictor") optimizer = nlp.initialize() test_text = TRAIN_DATA[0][0] doc = nlp(test_text)