From 4f9c84c1f23c2fa2c11c116a0850e4a20c07caef Mon Sep 17 00:00:00 2001 From: Dirk Groeneveld Date: Tue, 9 Apr 2019 13:09:51 -0700 Subject: [PATCH 1/4] Makes this work on GPUs --- neuralcoref/neuralcoref.pyx | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/neuralcoref/neuralcoref.pyx b/neuralcoref/neuralcoref.pyx index 7270715..b41b9dd 100644 --- a/neuralcoref/neuralcoref.pyx +++ b/neuralcoref/neuralcoref.pyx @@ -892,16 +892,8 @@ cdef class NeuralCoref(object): return self.get_word_embedding(sent.doc[i]) def get_average_embedding(self, Span span): - cdef int i - cdef int n = 0 - embed_arr = numpy.zeros(self.static_vectors.shape[1], dtype='float32') - for token in span: - if token.lower not in PUNCTS: - n += 1 - embed_vector = self.get_word_embedding(token, tuned=False) - embed_arr = embed_arr + embed_vector - embed_arr = numpy.divide(embed_arr, float(max(n, 1))) - return embed_arr + tokens = [token for token in span if token.lower not in PUNCTS] + return sum(self.get_word_embedding(token, tuned=False) for token in tokens) / float(max(len(tokens), 1)) def get_mention_embeddings(self, Span span, doc_embedding): ''' Create a mention embedding with span (averaged) and word (single) embeddings ''' From a305b6d632cc4c93553c77141021cf8cd4b5ac4f Mon Sep 17 00:00:00 2001 From: Dirk Groeneveld Date: Tue, 9 Apr 2019 15:27:53 -0700 Subject: [PATCH 2/4] Further fixes for GPU prediction --- neuralcoref/neuralcoref.pyx | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/neuralcoref/neuralcoref.pyx b/neuralcoref/neuralcoref.pyx index b41b9dd..97859e1 100644 --- a/neuralcoref/neuralcoref.pyx +++ b/neuralcoref/neuralcoref.pyx @@ -20,6 +20,8 @@ import array from libc.stdint cimport uint16_t, uint32_t, uint64_t, uintptr_t, int32_t import numpy +import cupy +from thinc.neural.util import get_array_module from cymem.cymem cimport Pool from srsly import json_dumps, read_json @@ -574,9 +576,10 @@ cdef class NeuralCoref(object): for key, words in conv_dict.items(): norm_k = simple_normalize(key) norm_w = list(simple_normalize(w) for w in words) - embed_vector = numpy.zeros(self.static_vectors.shape[1], dtype='float32') - for hash_w in norm_w: - embed_vector += self.tuned_vectors[hash_w] if hash_w in self.tuned_vectors else self.get_static(hash_w) + embed_vector = sum( + self.tuned_vectors[hash_w] if hash_w in self.tuned_vectors else self.get_static(hash_w) + for hash_w in norm_w + ) self.conv_dict.add(key=norm_k, vector=embed_vector/max(len(norm_w), 1)) def __call__(self, doc, greedyness=None, max_dist=None, max_dist_match=None, @@ -639,7 +642,7 @@ cdef class NeuralCoref(object): Doc doc uint64_t i, ant_idx, men_idx, b_idx, n_mentions, n_pairs uint64_t [::1] p_ant, p_men, best_ant - float [::1] embed, feats, doc_embed, mention_embed, best_score + float [::1] embed, feats, mention_embed, best_score float [:, ::1] s_inp, p_inp float [:, ::1] s_score, p_score Pool mem @@ -649,6 +652,8 @@ cdef class NeuralCoref(object): # clock_gettime(CLOCK_REALTIME, &ts) # timing0 = ts.tv_sec + (ts.tv_nsec / 1000000000.) + xp = get_array_module(self.static_vectors.data) + annotations = [] # if debug: print("Extract mentions") for doc in docs: @@ -717,8 +722,7 @@ cdef class NeuralCoref(object): # if debug: print("Build single features and pair features arrays") # ''' Build single features and pair features arrays ''' doc_c = doc.c - doc_embedding = numpy.zeros(SIZE_EMBEDDING, dtype='float32') # self.embeds.get_average_embedding(doc.c, 0, doc.length + 1, self.hashes.puncts) - doc_embed = doc_embedding + doc_embedding = xp.zeros(SIZE_EMBEDDING, dtype='float32') # self.embeds.get_average_embedding(doc.c, 0, doc.length + 1, self.hashes.puncts) for i in range(n_mentions): s_inp_arr[i, :SGNL_FEATS_0] = self.get_mention_embeddings(mentions[i], doc_embedding) # Set embeddings s_inp_arr[i, SGNL_FEATS_0 + c[i].mention_type] = 1 # 01_MentionType @@ -760,11 +764,11 @@ cdef class NeuralCoref(object): best_ant_ar = numpy.empty((n_mentions), dtype=numpy.uint64) best_score = best_score_ar best_ant = best_ant_ar - s_score = self.model[0](s_inp_arr) + s_score = cupy.asnumpy(self.model[0](xp.asarray(s_inp_arr))) for i in range(n_mentions): best_score[i] = s_score[i, 0] - 50 * (greedyness - 0.5) best_ant[i] = i - p_score = self.model[1](p_inp_arr) + p_score = cupy.asnumpy(self.model[1](xp.asarray(p_inp_arr))) for i in range(n_pairs): ant_idx = p_ant[i] men_idx = p_men[i] @@ -814,8 +818,8 @@ cdef class NeuralCoref(object): scores_dict[mention] = {mention: score} # pair scores for i in range(n_pairs): - antecedent = mentions[p_ant[i]] - mention = mentions[p_men[i]] + antecedent = mentions[int(p_ant[i])] + mention = mentions[int(p_men[i])] score = p_score[i, 0] if mention in scores_dict: scores_dict[mention][antecedent] = score @@ -899,8 +903,10 @@ cdef class NeuralCoref(object): ''' Create a mention embedding with span (averaged) and word (single) embeddings ''' doc = span.doc sent = span.sent - embeddings = numpy.zeros((EMBED_13, ), dtype='float32') - embeddings[ :EMBED_01] = self.get_average_embedding(span) + span_embeddings = self.get_average_embedding(span) + xp = get_array_module(span_embeddings) + embeddings = xp.zeros((EMBED_13, ), dtype='float32') + embeddings[ :EMBED_01] = span_embeddings embeddings[EMBED_01:EMBED_02] = self.get_average_embedding(doc[max(span.start-5, sent.start):span.start]) embeddings[EMBED_02:EMBED_03] = self.get_average_embedding(doc[span.end:min(span.end + 5, sent.end)]) embeddings[EMBED_03:EMBED_04] = self.get_average_embedding(sent) From de5f93ba7dc21da0e52c968117f908f32a16b0dc Mon Sep 17 00:00:00 2001 From: Dirk Groeneveld Date: Tue, 9 Apr 2019 16:03:42 -0700 Subject: [PATCH 3/4] Makes the cupy dependency optional --- neuralcoref/neuralcoref.pyx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/neuralcoref/neuralcoref.pyx b/neuralcoref/neuralcoref.pyx index 97859e1..4a44cb2 100644 --- a/neuralcoref/neuralcoref.pyx +++ b/neuralcoref/neuralcoref.pyx @@ -20,7 +20,12 @@ import array from libc.stdint cimport uint16_t, uint32_t, uint64_t, uintptr_t, int32_t import numpy -import cupy +try: + import cupy + to_numpy = cupy.asnumpy +except ModuleNotFoundError: + to_numpy = lambda x: x + from thinc.neural.util import get_array_module from cymem.cymem cimport Pool from srsly import json_dumps, read_json @@ -764,11 +769,11 @@ cdef class NeuralCoref(object): best_ant_ar = numpy.empty((n_mentions), dtype=numpy.uint64) best_score = best_score_ar best_ant = best_ant_ar - s_score = cupy.asnumpy(self.model[0](xp.asarray(s_inp_arr))) + s_score = to_numpy(self.model[0](xp.asarray(s_inp_arr))) for i in range(n_mentions): best_score[i] = s_score[i, 0] - 50 * (greedyness - 0.5) best_ant[i] = i - p_score = cupy.asnumpy(self.model[1](xp.asarray(p_inp_arr))) + p_score = to_numpy(self.model[1](xp.asarray(p_inp_arr))) for i in range(n_pairs): ant_idx = p_ant[i] men_idx = p_men[i] From 457c10d7c9828967fbbc9b2d68284c80c78a9adb Mon Sep 17 00:00:00 2001 From: Dirk Groeneveld Date: Mon, 22 Apr 2019 10:41:38 -0700 Subject: [PATCH 4/4] One more fix. This should have been part of the original set of fixes. --- neuralcoref/neuralcoref.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neuralcoref/neuralcoref.pyx b/neuralcoref/neuralcoref.pyx index 4a44cb2..03bd217 100644 --- a/neuralcoref/neuralcoref.pyx +++ b/neuralcoref/neuralcoref.pyx @@ -729,7 +729,7 @@ cdef class NeuralCoref(object): doc_c = doc.c doc_embedding = xp.zeros(SIZE_EMBEDDING, dtype='float32') # self.embeds.get_average_embedding(doc.c, 0, doc.length + 1, self.hashes.puncts) for i in range(n_mentions): - s_inp_arr[i, :SGNL_FEATS_0] = self.get_mention_embeddings(mentions[i], doc_embedding) # Set embeddings + s_inp_arr[i, :SGNL_FEATS_0] = to_numpy(self.get_mention_embeddings(mentions[i], doc_embedding)) # Set embeddings s_inp_arr[i, SGNL_FEATS_0 + c[i].mention_type] = 1 # 01_MentionType b_idx, val = index_distance(c[i].span_end - c[i].span_start - 1) # 02_MentionLength s_inp_arr[i, SGNL_FEATS_1 + b_idx] = 1