mirror of
https://github.com/explosion/spaCy.git
synced 2024-12-25 09:26:27 +03:00
* Prepare for new models to be plugged in by using Example class
This commit is contained in:
parent
75aeccc064
commit
9282a8e72c
3
setup.py
3
setup.py
|
@ -151,7 +151,8 @@ MOD_NAMES = ['spacy.parts_of_speech', 'spacy.strings',
|
|||
'spacy.lexeme', 'spacy.vocab', 'spacy.tokens', 'spacy.spans',
|
||||
'spacy.morphology',
|
||||
'spacy.syntax.stateclass',
|
||||
'spacy._ml', 'spacy.tokenizer', 'spacy.en.attrs',
|
||||
'spacy._ml', 'spacy._theano',
|
||||
'spacy.tokenizer', 'spacy.en.attrs',
|
||||
'spacy.en.pos', 'spacy.syntax.parser',
|
||||
'spacy.syntax.transition_system',
|
||||
'spacy.syntax.arc_eager',
|
||||
|
|
|
@ -14,9 +14,14 @@ from .tokens cimport Tokens
|
|||
|
||||
cdef int arg_max(const weight_t* scores, const int n_classes) nogil
|
||||
|
||||
cdef int arg_max_if_true(const weight_t* scores, const int* is_valid, int n_classes) nogil
|
||||
|
||||
cdef int arg_max_if_zero(const weight_t* scores, const int* costs, int n_classes) nogil
|
||||
|
||||
|
||||
cdef class Model:
|
||||
cdef int n_classes
|
||||
cdef int n_feats
|
||||
|
||||
cdef const weight_t* score(self, atom_t* context) except NULL
|
||||
cdef int set_scores(self, weight_t* scores, atom_t* context) except -1
|
||||
|
|
|
@ -24,7 +24,7 @@ cdef int arg_max(const weight_t* scores, const int n_classes) nogil:
|
|||
return best
|
||||
|
||||
|
||||
cdef int arg_max_if_true(const weight_t* scores, const bint* is_valid,
|
||||
cdef int arg_max_if_true(const weight_t* scores, const int* is_valid,
|
||||
const int n_classes) nogil:
|
||||
cdef int i
|
||||
cdef int best = 0
|
||||
|
@ -54,21 +54,25 @@ cdef class Model:
|
|||
model_loc = path.join(model_loc, 'model')
|
||||
self.n_classes = n_classes
|
||||
self._extractor = Extractor(templates)
|
||||
self.n_feats = self._extractor.n_templ
|
||||
self._model = LinearModel(n_classes, self._extractor.n_templ)
|
||||
self.model_loc = model_loc
|
||||
if self.model_loc and path.exists(self.model_loc):
|
||||
self._model.load(self.model_loc, freq_thresh=0)
|
||||
|
||||
def predict(self, Example eg):
|
||||
self.set_scores(eg.scores, eg.atoms)
|
||||
eg.guess = arg_max_if_true(eg.scores, eg.is_valid, self.n_classes)
|
||||
self.set_scores(<weight_t*>eg.scores.data, <atom_t*>eg.atoms.data)
|
||||
eg.guess = arg_max_if_true(<weight_t*>eg.scores.data, <int*>eg.is_valid.data,
|
||||
self.n_classes)
|
||||
|
||||
def train(self, Example eg):
|
||||
self.set_scores(eg.scores, eg.atoms)
|
||||
eg.guess = arg_max_if_true(eg.scores, eg.is_valid, self.n_classes)
|
||||
eg.best = arg_max_if_zero(eg.scores, eg.costs, self.n_classes)
|
||||
self.set_scores(<weight_t*>eg.scores.data, <atom_t*>eg.atoms.data)
|
||||
eg.guess = arg_max_if_true(<weight_t*>eg.scores.data,
|
||||
<int*>eg.is_valid.data, self.n_classes)
|
||||
eg.best = arg_max_if_zero(<weight_t*>eg.scores.data, <int*>eg.costs.data,
|
||||
self.n_classes)
|
||||
eg.cost = eg.costs[eg.guess]
|
||||
self.update(eg.atoms, eg.guess, eg.best, eg.cost)
|
||||
self.update(<atom_t*>eg.atoms.data, eg.guess, eg.best, eg.cost)
|
||||
|
||||
cdef const weight_t* score(self, atom_t* context) except NULL:
|
||||
cdef int n_feats
|
||||
|
|
|
@ -1,44 +1,44 @@
|
|||
from thinc.example cimport Example
|
||||
from thinc.api cimport Example
|
||||
from thinc.typedefs cimport weight_t
|
||||
|
||||
from ._ml cimport arg_max_if_true
|
||||
from ._ml cimport arg_max_if_zero
|
||||
|
||||
import numpy
|
||||
from os import path
|
||||
|
||||
|
||||
cdef class TheanoModel(Model):
|
||||
def __init__(self, n_classes, input_layer, train_func, predict_func, model_loc=None):
|
||||
def __init__(self, n_classes, input_spec, train_func, predict_func, model_loc=None):
|
||||
if model_loc is not None and path.isdir(model_loc):
|
||||
model_loc = path.join(model_loc, 'model')
|
||||
self.n_classes = n_classes
|
||||
|
||||
tables = []
|
||||
lengths = []
|
||||
for window_size, n_dims, vocab_size in input_structure:
|
||||
tables.append(EmbeddingTable(n_dims, vocab_size, initializer))
|
||||
lengths.append(window_size)
|
||||
|
||||
self.input_layer = InputLayer(lengths, tables)
|
||||
|
||||
self.eta = 0.001
|
||||
self.mu = 0.9
|
||||
self.t = 1
|
||||
initializer = lambda: 0.2 * numpy.random.uniform(-1.0, 1.0)
|
||||
self.input_layer = InputLayer(input_spec, initializer)
|
||||
self.train_func = train_func
|
||||
self.predict_func = predict_func
|
||||
|
||||
self.n_classes = n_classes
|
||||
self.n_feats = len(self.input_layer)
|
||||
self.model_loc = model_loc
|
||||
if self.model_loc and path.exists(self.model_loc):
|
||||
self._model.load(self.model_loc, freq_thresh=0)
|
||||
|
||||
def train(self, Instance eg):
|
||||
pass
|
||||
|
||||
def predict(self, Instance eg):
|
||||
|
||||
cdef const weight_t* score(self, atom_t* context) except NULL:
|
||||
self.set_scores(self._scores, context)
|
||||
return self._scores
|
||||
|
||||
cdef int set_scores(self, weight_t* scores, atom_t* context) except -1:
|
||||
# TODO f(context) --> Values
|
||||
self._input_layer.fill(self._x, self._values, use_avg=False)
|
||||
theano_scores = self._predict(self._x)
|
||||
|
||||
def predict(self, Example eg):
|
||||
self.input_layer.fill(eg.embeddings, eg.atoms)
|
||||
theano_scores = self.predict_func(eg.embeddings)
|
||||
cdef int i
|
||||
for i in range(self.n_classes):
|
||||
output[i] = theano_scores[i]
|
||||
eg.scores[i] = theano_scores[i]
|
||||
eg.guess = arg_max_if_true(<weight_t*>eg.scores.data, <int*>eg.is_valid.data,
|
||||
self.n_classes)
|
||||
|
||||
cdef int update(self, atom_t* context, class_t guess, class_t gold, int cost) except -1:
|
||||
# TODO f(context) --> Values
|
||||
self._input_layer.fill(self._x, self._values, use_avg=False)
|
||||
|
||||
def train(self, Example eg):
|
||||
self.predict(eg)
|
||||
update, t, eta, mu = self.train_func(eg.embeddings, eg.scores, eg.costs)
|
||||
self.input_layer.update(eg.atoms, update, self.t, self.eta, self.mu)
|
||||
eg.best = arg_max_if_zero(<weight_t*>eg.scores.data, <int*>eg.costs.data,
|
||||
self.n_classes)
|
||||
eg.cost = eg.costs[eg.guess]
|
||||
self.t += 1
|
||||
|
|
|
@ -68,11 +68,11 @@ cdef class Parser:
|
|||
cdef StateClass stcls = StateClass.init(tokens.data, tokens.length)
|
||||
self.moves.initialize_state(stcls)
|
||||
|
||||
cdef Example eg = Example(self.model.n_classes, CONTEXT_SIZE)
|
||||
cdef Example eg = Example(self.model.n_classes, CONTEXT_SIZE, self.model.n_feats)
|
||||
while not stcls.is_final():
|
||||
eg.wipe()
|
||||
fill_context(eg.atoms, stcls)
|
||||
self.moves.set_valid(eg.is_valid, stcls)
|
||||
fill_context(<atom_t*>eg.atoms.data, stcls)
|
||||
self.moves.set_valid(<bint*>eg.is_valid.data, stcls)
|
||||
|
||||
self.model.predict(eg)
|
||||
|
||||
|
@ -84,12 +84,12 @@ cdef class Parser:
|
|||
self.moves.preprocess_gold(gold)
|
||||
cdef StateClass stcls = StateClass.init(tokens.data, tokens.length)
|
||||
self.moves.initialize_state(stcls)
|
||||
cdef Example eg = Example(self.model.n_classes, CONTEXT_SIZE)
|
||||
cdef Example eg = Example(self.model.n_classes, CONTEXT_SIZE, self.model.n_feats)
|
||||
cdef int cost = 0
|
||||
while not stcls.is_final():
|
||||
eg.wipe()
|
||||
fill_context(eg.atoms, stcls)
|
||||
self.moves.set_costs(eg.is_valid, eg.costs, stcls, gold)
|
||||
fill_context(<atom_t*>eg.atoms.data, stcls)
|
||||
self.moves.set_costs(<bint*>eg.is_valid.data, <int*>eg.costs.data, stcls, gold)
|
||||
|
||||
self.model.train(eg)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user