Batched version of process_text(). This method uses the convert_batch_elements_to_batched_tns() method which could be much more efficient by directly returning tensors that do not require indexing - like done in _identify_entity_mentions(). Currently, performance gai
(
self,
texts: List[str],
spanss: Optional[List[List[Span]]] = None,
ner_threshold: float = 0.5,
prune_ner_types: bool = True,
max_batch_size: int = 16,
apply_class_check: bool = False,
return_special_spans: bool = True,
sort_by_tokens: bool = True
)
| 195 | return all_spans |
| 196 | |
| 197 | def process_text_batch( |
| 198 | self, |
| 199 | texts: List[str], |
| 200 | spanss: Optional[List[List[Span]]] = None, |
| 201 | ner_threshold: float = 0.5, |
| 202 | prune_ner_types: bool = True, |
| 203 | max_batch_size: int = 16, |
| 204 | apply_class_check: bool = False, |
| 205 | return_special_spans: bool = True, |
| 206 | sort_by_tokens: bool = True |
| 207 | ) -> List[Doc]: |
| 208 | """ |
| 209 | Batched version of process_text(). |
| 210 | This method uses the convert_batch_elements_to_batched_tns() method which could be much more |
| 211 | efficient by directly returning tensors that do not require indexing - like done in _identify_entity_mentions(). |
| 212 | Currently, performance gain from batching is mostly present when document texts |
| 213 | are short (such as question text). |
| 214 | TODO: add optional already "indexed into" tensors to RefinedModel.forward() and use this during inference. |
| 215 | # Note that "indexed into" tensors should not be used during multi-gpu training as it can cause issues. |
| 216 | # `sort_by_tokens` is used to batch similar length chunks together for efficiency. |
| 217 | # The current implementation means that the person name co-rereference trick will no longer work |
| 218 | # across (512 token) chunks of the same document but there is a simple fix in _identify_entity_mentions(). |
| 219 | """ |
| 220 | all_spans = [] |
| 221 | |
| 222 | docs = [] |
| 223 | if spanss is not None: |
| 224 | for i, (text, spans) in enumerate(zip(texts, spanss)): |
| 225 | doc = Doc.from_text_with_spans( |
| 226 | text, spans, self.preprocessor, backward_coref=self.backward_coref, |
| 227 | doc_id=i |
| 228 | ) |
| 229 | docs.append(doc) |
| 230 | else: |
| 231 | for i, text in enumerate(texts): |
| 232 | doc = Doc.from_text( |
| 233 | text, preprocessor=self.preprocessor, doc_id=i |
| 234 | ) |
| 235 | docs.append(doc) |
| 236 | batch_elements = [elem for doc in docs for elem in doc.to_batch_elements( |
| 237 | preprocessor=self.preprocessor, override_max_seq=self.max_seq |
| 238 | )] |
| 239 | tns: Iterable[BatchedElementsTns] = convert_batch_elements_to_batched_tns( |
| 240 | batch_elements, |
| 241 | self.preprocessor, |
| 242 | max_batch_size=max_batch_size, |
| 243 | sort_by_tokens=sort_by_tokens, |
| 244 | # TODO: currently sort_by_tokens=True means some person name co-reference can be missed. |
| 245 | # To make this equivalent to running with sort_by_tokens=False, adjust the |
| 246 | # in _identify_entity_mentions() is adjusted to keep track of names per doc and not assume batch_elements |
| 247 | # for each document are sequential. |
| 248 | ) |
| 249 | |
| 250 | self.model.eval() |
| 251 | |
| 252 | for batch_idx, batch in enumerate(tns): |
| 253 | batch_spans = self.process_tensors(batch=batch, ner_threshold=ner_threshold, |
| 254 | return_special_spans=return_special_spans) |
no test coverage detected