mirror of
https://github.com/explosion/spaCy.git
synced 2025-06-06 14:13:11 +03:00
Tmp GPU code
This commit is contained in:
parent
e420e5a809
commit
6782eedf9b
|
@ -26,6 +26,15 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
from thinc.neural import Model
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
import cupy
|
||||||
|
from thinc.neural.ops import CupyOps
|
||||||
|
except:
|
||||||
|
cupy = None
|
||||||
|
|
||||||
|
|
||||||
def read_conllx(loc, n=0):
|
def read_conllx(loc, n=0):
|
||||||
with io.open(loc, 'r', encoding='utf8') as file_:
|
with io.open(loc, 'r', encoding='utf8') as file_:
|
||||||
|
@ -88,6 +97,8 @@ def organize_data(vocab, train_sents):
|
||||||
|
|
||||||
|
|
||||||
def main(lang_name, train_loc, dev_loc, model_dir, clusters_loc=None):
|
def main(lang_name, train_loc, dev_loc, model_dir, clusters_loc=None):
|
||||||
|
if cupy is not None:
|
||||||
|
Model.ops = CupyOps()
|
||||||
LangClass = spacy.util.get_lang_class(lang_name)
|
LangClass = spacy.util.get_lang_class(lang_name)
|
||||||
train_sents = list(read_conllx(train_loc))
|
train_sents = list(read_conllx(train_loc))
|
||||||
dev_sents = list(read_conllx(dev_loc))
|
dev_sents = list(read_conllx(dev_loc))
|
||||||
|
@ -163,7 +174,7 @@ def main(lang_name, train_loc, dev_loc, model_dir, clusters_loc=None):
|
||||||
print('%d:\t%.3f\t%.3f\t%.3f' % (itn, nn_loss[-1], scorer.uas, scorer.tags_acc))
|
print('%d:\t%.3f\t%.3f\t%.3f' % (itn, nn_loss[-1], scorer.uas, scorer.tags_acc))
|
||||||
nn_loss.append(0.)
|
nn_loss.append(0.)
|
||||||
trainer.each_epoch.append(track_progress)
|
trainer.each_epoch.append(track_progress)
|
||||||
trainer.batch_size = 12
|
trainer.batch_size = 24
|
||||||
trainer.nb_epoch = 10
|
trainer.nb_epoch = 10
|
||||||
for docs, golds in trainer.iterate(Xs, ys):
|
for docs, golds in trainer.iterate(Xs, ys):
|
||||||
docs = [Doc(vocab, words=[w.text for w in doc]) for doc in docs]
|
docs = [Doc(vocab, words=[w.text for w in doc]) for doc in docs]
|
||||||
|
|
|
@ -3,6 +3,7 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
from thinc.api import chain, layerize, with_getitem
|
from thinc.api import chain, layerize, with_getitem
|
||||||
from thinc.neural import Model, Softmax
|
from thinc.neural import Model, Softmax
|
||||||
|
import numpy
|
||||||
|
|
||||||
from .syntax.parser cimport Parser
|
from .syntax.parser cimport Parser
|
||||||
#from .syntax.beam_parser cimport BeamParser
|
#from .syntax.beam_parser cimport BeamParser
|
||||||
|
@ -39,16 +40,15 @@ class TokenVectorEncoder(object):
|
||||||
def update(self, docs, golds, drop=0., sgd=None):
|
def update(self, docs, golds, drop=0., sgd=None):
|
||||||
scores, finish_update = self.tagger.begin_update(docs, drop=drop)
|
scores, finish_update = self.tagger.begin_update(docs, drop=drop)
|
||||||
losses = scores.copy()
|
losses = scores.copy()
|
||||||
loss = 0.0
|
|
||||||
idx = 0
|
idx = 0
|
||||||
for i, gold in enumerate(golds):
|
for i, gold in enumerate(golds):
|
||||||
|
ids = numpy.zeros((len(gold),), dtype='i')
|
||||||
|
start = idx
|
||||||
for j, tag in enumerate(gold.tags):
|
for j, tag in enumerate(gold.tags):
|
||||||
tag_id = docs[0].vocab.morphology.tag_names.index(tag)
|
ids[j] = docs[0].vocab.morphology.tag_names.index(tag)
|
||||||
losses[idx, tag_id] -= 1.0
|
|
||||||
loss += 1-scores[idx, tag_id]
|
|
||||||
idx += 1
|
idx += 1
|
||||||
|
self.tagger.ops.xp.scatter_add(losses[start:idx], ids, -1.0)
|
||||||
finish_update(losses, sgd)
|
finish_update(losses, sgd)
|
||||||
return loss
|
|
||||||
|
|
||||||
|
|
||||||
cdef class EntityRecognizer(Parser):
|
cdef class EntityRecognizer(Parser):
|
||||||
|
|
|
@ -201,7 +201,7 @@ cdef class Parser:
|
||||||
costs = self.model.ops.allocate((len(docs), nr_class), dtype='f')
|
costs = self.model.ops.allocate((len(docs), nr_class), dtype='f')
|
||||||
gradients = self.model.ops.allocate((len(docs), nr_class), dtype='f')
|
gradients = self.model.ops.allocate((len(docs), nr_class), dtype='f')
|
||||||
is_valid = self.model.ops.allocate((len(docs), nr_class), dtype='i')
|
is_valid = self.model.ops.allocate((len(docs), nr_class), dtype='i')
|
||||||
attr_names = self.model.ops.allocate((2,), dtype='i')
|
attr_names = numpy.zeros((2,), dtype='i')
|
||||||
attr_names[0] = TAG
|
attr_names[0] = TAG
|
||||||
attr_names[1] = DEP
|
attr_names[1] = DEP
|
||||||
|
|
||||||
|
@ -228,10 +228,14 @@ cdef class Parser:
|
||||||
scores, finish_update = self._begin_update(states, tokvecs)
|
scores, finish_update = self._begin_update(states, tokvecs)
|
||||||
token_ids, batch_token_grads = finish_update(golds, sgd=sgd, losses=losses,
|
token_ids, batch_token_grads = finish_update(golds, sgd=sgd, losses=losses,
|
||||||
force_gold=False)
|
force_gold=False)
|
||||||
for i, tok_ids in enumerate(token_ids):
|
if hasattr(self.model.ops.xp, 'scatter_add'):
|
||||||
for j, tok_i in enumerate(tok_ids):
|
for i, tok_ids in enumerate(token_ids):
|
||||||
if tok_i >= 0:
|
self.model.ops.xp.scatter_add(d_tokens[i],
|
||||||
d_tokens[i][tok_i] += batch_token_grads[i, j]
|
tok_ids, batch_token_grads[i])
|
||||||
|
else:
|
||||||
|
for i, tok_ids in enumerate(token_ids):
|
||||||
|
self.model.ops.xp.add.at(d_tokens[i],
|
||||||
|
tok_ids, batch_token_grads[i])
|
||||||
|
|
||||||
self._transition_batch(states, scores)
|
self._transition_batch(states, scores)
|
||||||
|
|
||||||
|
@ -244,7 +248,7 @@ cdef class Parser:
|
||||||
|
|
||||||
def _begin_update(self, states, tokvecs, drop=0.):
|
def _begin_update(self, states, tokvecs, drop=0.):
|
||||||
nr_class = self.moves.n_moves
|
nr_class = self.moves.n_moves
|
||||||
attr_names = self.model.ops.allocate((2,), dtype='i')
|
attr_names = numpy.zeros((2,), dtype='i')
|
||||||
attr_names[0] = TAG
|
attr_names[0] = TAG
|
||||||
attr_names[1] = DEP
|
attr_names[1] = DEP
|
||||||
|
|
||||||
|
@ -284,28 +288,38 @@ cdef class Parser:
|
||||||
nF=1, nB=0, nS=2, nL=2, nR=2):
|
nF=1, nB=0, nS=2, nL=2, nR=2):
|
||||||
n_tokens = states[0].nr_context_tokens(nF, nB, nS, nL, nR)
|
n_tokens = states[0].nr_context_tokens(nF, nB, nS, nL, nR)
|
||||||
vector_length = all_tokvecs[0].shape[1]
|
vector_length = all_tokvecs[0].shape[1]
|
||||||
tokens = self.model.ops.allocate((len(states), n_tokens), dtype='int32')
|
cpu_tokens = numpy.zeros((len(states), n_tokens), dtype='int32')
|
||||||
features = self.model.ops.allocate((len(states), n_tokens, attr_names.shape[0]), dtype='uint64')
|
features = numpy.zeros((len(states), n_tokens, attr_names.shape[0]), dtype='uint64')
|
||||||
tokvecs = self.model.ops.allocate((len(states), n_tokens, vector_length), dtype='f')
|
tokvecs = self.model.ops.allocate((len(states), n_tokens, vector_length), dtype='f')
|
||||||
for i, state in enumerate(states):
|
for i, state in enumerate(states):
|
||||||
state.set_context_tokens(tokens[i], nF, nB, nS, nL, nR)
|
state.set_context_tokens(cpu_tokens[i], nF, nB, nS, nL, nR)
|
||||||
state.set_attributes(features[i], tokens[i], attr_names)
|
#state.set_attributes(features[i], tokens[i], attr_names)
|
||||||
state.set_token_vectors(tokvecs[i], all_tokvecs[i], tokens[i])
|
gpu_tokens = self.model.ops.xp.array(cpu_tokens)
|
||||||
return (tokens, features, tokvecs)
|
for i in range(len(states)):
|
||||||
|
tokvecs[i] = all_tokvecs[i][gpu_tokens[i]]
|
||||||
|
tokvecs *= (gpu_tokens >= 0).reshape((gpu_tokens.shape[0], gpu_tokens.shape[1], 1))
|
||||||
|
return (gpu_tokens, self.model.ops.asarray(features), tokvecs)
|
||||||
|
|
||||||
def _validate_batch(self, int[:, ::1] is_valid, states):
|
def _validate_batch(self, is_valid, states):
|
||||||
cdef StateClass state
|
cdef StateClass state
|
||||||
cdef int i
|
cdef int i
|
||||||
|
cdef int[:, :] is_valid_cpu = is_valid.get()
|
||||||
for i, state in enumerate(states):
|
for i, state in enumerate(states):
|
||||||
self.moves.set_valid(&is_valid[i, 0], state.c)
|
self.moves.set_valid(&is_valid_cpu[i, 0], state.c)
|
||||||
|
is_valid.set(numpy.asarray(is_valid_cpu))
|
||||||
|
|
||||||
def _cost_batch(self, weight_t[:, ::1] costs, int[:, ::1] is_valid,
|
def _cost_batch(self, costs, is_valid,
|
||||||
states, golds):
|
states, golds):
|
||||||
cdef int i
|
cdef int i
|
||||||
cdef StateClass state
|
cdef StateClass state
|
||||||
cdef GoldParse gold
|
cdef GoldParse gold
|
||||||
|
cdef int[:, :] is_valid_cpu = is_valid.get()
|
||||||
|
cdef weight_t[:, :] costs_cpu = costs.get()
|
||||||
|
|
||||||
for i, (state, gold) in enumerate(zip(states, golds)):
|
for i, (state, gold) in enumerate(zip(states, golds)):
|
||||||
self.moves.set_costs(&is_valid[i, 0], &costs[i, 0], state, gold)
|
self.moves.set_costs(&is_valid_cpu[i, 0], &costs_cpu[i, 0], state, gold)
|
||||||
|
is_valid.set(numpy.asarray(is_valid_cpu))
|
||||||
|
costs.set(numpy.asarray(costs_cpu))
|
||||||
|
|
||||||
def _transition_batch(self, states, scores):
|
def _transition_batch(self, states, scores):
|
||||||
cdef StateClass state
|
cdef StateClass state
|
||||||
|
|
|
@ -76,8 +76,8 @@ cdef class StateClass:
|
||||||
else:
|
else:
|
||||||
vals[i] = 0
|
vals[i] = 0
|
||||||
|
|
||||||
def set_token_vectors(self, float[:, :] tokvecs,
|
def set_token_vectors(self, tokvecs,
|
||||||
float[:, :] all_tokvecs, int[:] indices):
|
all_tokvecs, int[:] indices):
|
||||||
for i in range(indices.shape[0]):
|
for i in range(indices.shape[0]):
|
||||||
if indices[i] >= 0:
|
if indices[i] >= 0:
|
||||||
tokvecs[i] = all_tokvecs[indices[i]]
|
tokvecs[i] = all_tokvecs[indices[i]]
|
||||||
|
|
|
@ -32,7 +32,7 @@ cdef class Doc:
|
||||||
cdef public object _vector
|
cdef public object _vector
|
||||||
cdef public object _vector_norm
|
cdef public object _vector_norm
|
||||||
|
|
||||||
cdef public np.ndarray tensor
|
cdef public object tensor
|
||||||
cdef public object user_data
|
cdef public object user_data
|
||||||
|
|
||||||
cdef TokenC* c
|
cdef TokenC* c
|
||||||
|
|
Loading…
Reference in New Issue
Block a user