mirror of
https://github.com/explosion/spaCy.git
synced 2025-07-03 19:33:19 +03:00
Fix refactored parser
This commit is contained in:
parent
3e3771c010
commit
f6cdafc00e
|
@ -15,11 +15,11 @@ cdef struct SizesC:
|
||||||
|
|
||||||
|
|
||||||
cdef struct WeightsC:
|
cdef struct WeightsC:
|
||||||
float* feat_weights
|
const float* feat_weights
|
||||||
float* feat_bias
|
const float* feat_bias
|
||||||
float* hidden_bias
|
const float* hidden_bias
|
||||||
float* hidden_weights
|
const float* hidden_weights
|
||||||
float* vectors
|
const float* vectors
|
||||||
|
|
||||||
|
|
||||||
cdef struct ActivationsC:
|
cdef struct ActivationsC:
|
||||||
|
@ -33,7 +33,9 @@ cdef struct ActivationsC:
|
||||||
int _max_size
|
int _max_size
|
||||||
|
|
||||||
|
|
||||||
cdef WeightsC get_c_weights(model)
|
cdef WeightsC get_c_weights(model) except *
|
||||||
|
|
||||||
|
cdef SizesC get_c_sizes(model, int batch_size) except *
|
||||||
|
|
||||||
cdef void resize_activations(ActivationsC* A, SizesC n) nogil
|
cdef void resize_activations(ActivationsC* A, SizesC n) nogil
|
||||||
|
|
||||||
|
|
|
@ -37,29 +37,56 @@ from ..errors import Errors, TempErrors
|
||||||
from .. import util
|
from .. import util
|
||||||
from .stateclass cimport StateClass
|
from .stateclass cimport StateClass
|
||||||
from .transition_system cimport Transition
|
from .transition_system cimport Transition
|
||||||
from . import _beam_utils, nonproj
|
from . import nonproj
|
||||||
|
|
||||||
|
|
||||||
cdef WeightsC get_c_weights(model):
|
cdef WeightsC get_c_weights(model) except *:
|
||||||
cdef WeightsC output
|
cdef WeightsC output
|
||||||
|
cdef precompute_hiddens state2vec = model.state2vec
|
||||||
|
output.feat_weights = state2vec.get_feat_weights()
|
||||||
|
output.feat_bias = <const float*>state2vec.bias.data
|
||||||
|
cdef np.ndarray vec2scores_W = model.vec2scores.W
|
||||||
|
cdef np.ndarray vec2scores_b = model.vec2scores.b
|
||||||
|
output.hidden_weights = <const float*>vec2scores_W.data
|
||||||
|
output.hidden_bias = <const float*>vec2scores_b.data
|
||||||
|
cdef np.ndarray tokvecs = model.tokvecs
|
||||||
|
output.vectors = <float*>tokvecs.data
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
cdef SizesC get_c_sizes(model, int batch_size) except *:
|
||||||
|
cdef SizesC output
|
||||||
|
output.states = batch_size
|
||||||
|
output.classes = model.nO
|
||||||
|
output.hiddens = model.nH
|
||||||
|
output.pieces = model.nP
|
||||||
|
output.feats = model.nF
|
||||||
|
output.embed_width = model.nI
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
cdef void resize_activations(ActivationsC* A, SizesC n) nogil:
|
cdef void resize_activations(ActivationsC* A, SizesC n) nogil:
|
||||||
if n.states < A._max_size:
|
if n.states <= A._max_size:
|
||||||
A._curr_size = n.states
|
A._curr_size = n.states
|
||||||
return
|
return
|
||||||
if A._max_size == 0:
|
if A._max_size == 0:
|
||||||
A.token_ids = <int*>calloc(n.states * n.feats, sizeof(A.token_ids[0]))
|
A.token_ids = <int*>calloc(n.states * n.feats, sizeof(A.token_ids[0]))
|
||||||
A.vectors = <float*>calloc(n.states * n.hiddens, sizeof(A.hiddens[0]))
|
A.vectors = <float*>calloc(n.states * n.hiddens, sizeof(A.hiddens[0]))
|
||||||
A.scores = <float*>calloc(n.states * n.classes, sizeof(A.scores[0]))
|
A.scores = <float*>calloc(n.states * n.classes, sizeof(A.scores[0]))
|
||||||
A.unmaxed = <float*>calloc(n.states * n.hiddens, sizeof(A.unmaxed[0]))
|
A.unmaxed = <float*>calloc(n.states * n.hiddens * n.feats, sizeof(A.unmaxed[0]))
|
||||||
A.is_valid = <int*>calloc(n.states * n.classes, sizeof(A.is_valid[0]))
|
A.is_valid = <int*>calloc(n.states * n.classes, sizeof(A.is_valid[0]))
|
||||||
|
A._max_size = n.states
|
||||||
else:
|
else:
|
||||||
A.token_ids = <int*>realloc(A.token_ids, n.states * n.feats * sizeof(A.token_ids[0]))
|
A.token_ids = <int*>realloc(A.token_ids,
|
||||||
A.vectors = <float*>realloc(A.token_ids, n.states * n.embed_width * sizeof(A.vectors[0]))
|
n.states * n.feats * sizeof(A.token_ids[0]))
|
||||||
A.scores = <float*>realloc(A.scores, n.states * n.classes * sizeof(A.scores[0]))
|
A.vectors = <float*>realloc(A.vectors,
|
||||||
A.unmaxed = <float*>realloc(A.unmaxed, n.states * n.hiddens * sizeof(A.unmaxed[0]))
|
n.states * n.embed_width * sizeof(A.vectors[0]))
|
||||||
A.is_valid = <int*>realloc(A.is_valid, n.states * n.classes * sizeof(A.is_valid[0]))
|
A.scores = <float*>realloc(A.scores,
|
||||||
|
n.states * n.classes * sizeof(A.scores[0]))
|
||||||
|
A.unmaxed = <float*>realloc(A.unmaxed,
|
||||||
|
n.states * n.hiddens * n.feats * sizeof(A.unmaxed[0]))
|
||||||
|
A.is_valid = <int*>realloc(A.is_valid,
|
||||||
|
n.states * n.classes * sizeof(A.is_valid[0]))
|
||||||
A._max_size = n.states
|
A._max_size = n.states
|
||||||
A._curr_size = n.states
|
A._curr_size = n.states
|
||||||
|
|
||||||
|
@ -165,8 +192,28 @@ class ParserModel(Model):
|
||||||
Model.__init__(self)
|
Model.__init__(self)
|
||||||
self._layers = [tok2vec, lower_model, upper_model]
|
self._layers = [tok2vec, lower_model, upper_model]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def nO(self):
|
||||||
|
return self._layers[-1].nO
|
||||||
|
|
||||||
|
@property
|
||||||
|
def nI(self):
|
||||||
|
return self._layers[1].nI
|
||||||
|
|
||||||
|
@property
|
||||||
|
def nH(self):
|
||||||
|
return self._layers[1].nO
|
||||||
|
|
||||||
|
@property
|
||||||
|
def nF(self):
|
||||||
|
return self._layers[1].nF
|
||||||
|
|
||||||
|
@property
|
||||||
|
def nP(self):
|
||||||
|
return self._layers[1].nP
|
||||||
|
|
||||||
def begin_update(self, docs, drop=0.):
|
def begin_update(self, docs, drop=0.):
|
||||||
step_model = ParserStepModel(docs, self.layers, drop=drop)
|
step_model = ParserStepModel(docs, self._layers, drop=drop)
|
||||||
def finish_parser_update(golds, sgd=None):
|
def finish_parser_update(golds, sgd=None):
|
||||||
step_model.make_updates(sgd)
|
step_model.make_updates(sgd)
|
||||||
return None
|
return None
|
||||||
|
@ -202,7 +249,7 @@ class ParserStepModel(Model):
|
||||||
|
|
||||||
def backprop_parser_step(d_scores, sgd=None):
|
def backprop_parser_step(d_scores, sgd=None):
|
||||||
d_vector = bp_dropout(get_d_vector(d_scores, sgd=sgd))
|
d_vector = bp_dropout(get_d_vector(d_scores, sgd=sgd))
|
||||||
if isinstance(self.model[0].ops, CupyOps) \
|
if isinstance(self.ops, CupyOps) \
|
||||||
and not isinstance(token_ids, self.state2vec.ops.xp.ndarray):
|
and not isinstance(token_ids, self.state2vec.ops.xp.ndarray):
|
||||||
# Move token_ids and d_vector to GPU, asynchronously
|
# Move token_ids and d_vector to GPU, asynchronously
|
||||||
self.backprops.append((
|
self.backprops.append((
|
||||||
|
@ -217,7 +264,7 @@ class ParserStepModel(Model):
|
||||||
|
|
||||||
def get_token_ids(self, states):
|
def get_token_ids(self, states):
|
||||||
cdef StateClass state
|
cdef StateClass state
|
||||||
cdef int n_tokens = self.nr_feature
|
cdef int n_tokens = self.state2vec.nF
|
||||||
cdef np.ndarray ids = numpy.zeros((len(states), n_tokens),
|
cdef np.ndarray ids = numpy.zeros((len(states), n_tokens),
|
||||||
dtype='i', order='C')
|
dtype='i', order='C')
|
||||||
c_ids = <int*>ids.data
|
c_ids = <int*>ids.data
|
||||||
|
@ -263,7 +310,7 @@ cdef class precompute_hiddens:
|
||||||
we can do all our hard maths up front, packed into large multiplications,
|
we can do all our hard maths up front, packed into large multiplications,
|
||||||
and do the hard-to-program parsing on the CPU.
|
and do the hard-to-program parsing on the CPU.
|
||||||
"""
|
"""
|
||||||
cdef int nF, nO, nP
|
cdef readonly int nF, nO, nP
|
||||||
cdef bint _is_synchronized
|
cdef bint _is_synchronized
|
||||||
cdef public object ops
|
cdef public object ops
|
||||||
cdef np.ndarray _features
|
cdef np.ndarray _features
|
||||||
|
|
|
@ -31,7 +31,7 @@ from thinc cimport openblas
|
||||||
|
|
||||||
from ._parser_model cimport resize_activations, predict_states, arg_max_if_valid
|
from ._parser_model cimport resize_activations, predict_states, arg_max_if_valid
|
||||||
from ._parser_model cimport WeightsC, ActivationsC, SizesC, cpu_log_loss
|
from ._parser_model cimport WeightsC, ActivationsC, SizesC, cpu_log_loss
|
||||||
from ._parser_model cimport get_c_weights
|
from ._parser_model cimport get_c_weights, get_c_sizes
|
||||||
from ._parser_model import ParserModel
|
from ._parser_model import ParserModel
|
||||||
from .._ml import zero_init, PrecomputableAffine, Tok2Vec, flatten
|
from .._ml import zero_init, PrecomputableAffine, Tok2Vec, flatten
|
||||||
from .._ml import link_vectors_to_models, create_default_optimizer
|
from .._ml import link_vectors_to_models, create_default_optimizer
|
||||||
|
@ -43,7 +43,7 @@ from .. import util
|
||||||
from .stateclass cimport StateClass
|
from .stateclass cimport StateClass
|
||||||
from ._state cimport StateC
|
from ._state cimport StateC
|
||||||
from .transition_system cimport Transition
|
from .transition_system cimport Transition
|
||||||
from . import _beam_utils, nonproj
|
from . import nonproj
|
||||||
|
|
||||||
|
|
||||||
cdef class Parser:
|
cdef class Parser:
|
||||||
|
@ -182,8 +182,9 @@ cdef class Parser:
|
||||||
beam_width = self.cfg.get('beam_width', 1)
|
beam_width = self.cfg.get('beam_width', 1)
|
||||||
if beam_density is None:
|
if beam_density is None:
|
||||||
beam_density = self.cfg.get('beam_density', 0.0)
|
beam_density = self.cfg.get('beam_density', 0.0)
|
||||||
states, tokvecs = self.predict([doc])
|
states = self.predict([doc])
|
||||||
self.set_annotations([doc], states, tensors=tokvecs)
|
#beam_width=beam_width, beam_density=beam_density)
|
||||||
|
self.set_annotations([doc], states, tensors=None)
|
||||||
return doc
|
return doc
|
||||||
|
|
||||||
def pipe(self, docs, int batch_size=256, int n_threads=2,
|
def pipe(self, docs, int batch_size=256, int n_threads=2,
|
||||||
|
@ -217,13 +218,14 @@ cdef class Parser:
|
||||||
if isinstance(docs, Doc):
|
if isinstance(docs, Doc):
|
||||||
docs = [docs]
|
docs = [docs]
|
||||||
|
|
||||||
cdef SizesC sizes
|
|
||||||
cdef vector[StateC*] states
|
cdef vector[StateC*] states
|
||||||
cdef StateClass state
|
cdef StateClass state
|
||||||
state_objs = self.moves.init_batch(docs)
|
state_objs = self.moves.init_batch(docs)
|
||||||
for state in state_objs:
|
for state in state_objs:
|
||||||
states.push_back(state.c)
|
states.push_back(state.c)
|
||||||
cdef WeightsC weights = get_c_weights(self.model)
|
model = self.model(docs)
|
||||||
|
cdef WeightsC weights = get_c_weights(model)
|
||||||
|
cdef SizesC sizes = get_c_sizes(self.model, len(state_objs))
|
||||||
with nogil:
|
with nogil:
|
||||||
self._parseC(&states[0],
|
self._parseC(&states[0],
|
||||||
weights, sizes)
|
weights, sizes)
|
||||||
|
@ -234,6 +236,7 @@ cdef class Parser:
|
||||||
cdef int i, j
|
cdef int i, j
|
||||||
cdef vector[StateC*] unfinished
|
cdef vector[StateC*] unfinished
|
||||||
cdef ActivationsC activations
|
cdef ActivationsC activations
|
||||||
|
memset(&activations, 0, sizeof(activations))
|
||||||
while sizes.states >= 1:
|
while sizes.states >= 1:
|
||||||
predict_states(&activations,
|
predict_states(&activations,
|
||||||
states, &weights, sizes)
|
states, &weights, sizes)
|
||||||
|
@ -248,7 +251,7 @@ cdef class Parser:
|
||||||
sizes.states = unfinished.size()
|
sizes.states = unfinished.size()
|
||||||
unfinished.clear()
|
unfinished.clear()
|
||||||
|
|
||||||
def set_annotations(self, docs, states):
|
def set_annotations(self, docs, states, tensors=None):
|
||||||
cdef StateClass state
|
cdef StateClass state
|
||||||
cdef Doc doc
|
cdef Doc doc
|
||||||
for i, (state, doc) in enumerate(zip(states, docs)):
|
for i, (state, doc) in enumerate(zip(states, docs)):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user