(examples, tokenizer)
| 247 | |
| 248 | |
| 249 | def preprocess_train_function(examples, tokenizer): |
| 250 | inputs = tokenizer( |
| 251 | [q.strip() for q in examples["question"]], |
| 252 | examples["context"], |
| 253 | max_length=384, |
| 254 | truncation="only_second", |
| 255 | return_offsets_mapping=True, |
| 256 | padding="max_length", |
| 257 | ) |
| 258 | |
| 259 | offset_mapping = inputs["offset_mapping"] |
| 260 | answers = examples["answers"] |
| 261 | start_positions = [] |
| 262 | end_positions = [] |
| 263 | |
| 264 | for i, (offset, answer) in enumerate(zip(offset_mapping, answers)): |
| 265 | start_char = answer["answer_start"][0] |
| 266 | end_char = start_char + len(answer["text"][0]) |
| 267 | sequence_ids = inputs.sequence_ids(i) |
| 268 | |
| 269 | # Find the start and end of the context |
| 270 | idx = 0 |
| 271 | while sequence_ids[idx] != 1: |
| 272 | idx += 1 |
| 273 | context_start = idx |
| 274 | while sequence_ids[idx] == 1: |
| 275 | idx += 1 |
| 276 | context_end = idx - 1 |
| 277 | |
| 278 | # If the answer is not fully inside the context, label it (0, 0) |
| 279 | if offset[context_start][0] > end_char or offset[context_end][1] < start_char: |
| 280 | start_positions.append(0) |
| 281 | end_positions.append(0) |
| 282 | else: |
| 283 | # Otherwise it's the start and end token positions |
| 284 | idx = context_start |
| 285 | while idx <= context_end and offset[idx][0] <= start_char: |
| 286 | idx += 1 |
| 287 | start_positions.append(idx - 1) |
| 288 | |
| 289 | idx = context_end |
| 290 | while idx >= context_start and offset[idx][1] >= end_char: |
| 291 | idx -= 1 |
| 292 | end_positions.append(idx + 1) |
| 293 | |
| 294 | inputs["start_positions"] = start_positions |
| 295 | inputs["end_positions"] = end_positions |
| 296 | return inputs |
| 297 | |
| 298 | |
| 299 | def compute_metrics(start_logits, end_logits, features, examples): |
no outgoing calls
no test coverage detected