Compute CTC alignment model transition matrix. Args: label_seq: tensor of shape [batch_size, max_seq_length] Returns: tensor of shape [batch_size, states, states] with a state transition matrix computed for each sequence of the batch.
(label_seq)
| 412 | |
| 413 | |
| 414 | def _ctc_state_trans(label_seq): |
| 415 | """Compute CTC alignment model transition matrix. |
| 416 | |
| 417 | Args: |
| 418 | label_seq: tensor of shape [batch_size, max_seq_length] |
| 419 | |
| 420 | Returns: |
| 421 | tensor of shape [batch_size, states, states] with a state transition matrix |
| 422 | computed for each sequence of the batch. |
| 423 | """ |
| 424 | |
| 425 | with ops.name_scope("ctc_state_trans"): |
| 426 | label_seq = ops.convert_to_tensor(label_seq, name="label_seq") |
| 427 | batch_size = _get_dim(label_seq, 0) |
| 428 | num_labels = _get_dim(label_seq, 1) |
| 429 | |
| 430 | num_label_states = num_labels + 1 |
| 431 | num_states = 2 * num_label_states |
| 432 | |
| 433 | label_states = math_ops.range(num_label_states) |
| 434 | blank_states = label_states + num_label_states |
| 435 | |
| 436 | # Start state to first label. |
| 437 | start_to_label = [[1, 0]] |
| 438 | |
| 439 | # Blank to label transitions. |
| 440 | blank_to_label = array_ops.stack([label_states[1:], blank_states[:-1]], 1) |
| 441 | |
| 442 | # Label to blank transitions. |
| 443 | label_to_blank = array_ops.stack([blank_states, label_states], 1) |
| 444 | |
| 445 | # Scatter transitions that don't depend on sequence. |
| 446 | indices = array_ops.concat([start_to_label, blank_to_label, label_to_blank], |
| 447 | 0) |
| 448 | values = array_ops.ones([_get_dim(indices, 0)]) |
| 449 | trans = array_ops.scatter_nd( |
| 450 | indices, values, shape=[num_states, num_states]) |
| 451 | trans += linalg_ops.eye(num_states) # Self-loops. |
| 452 | |
| 453 | # Label to label transitions. Disallow transitions between repeated labels |
| 454 | # with no blank state in between. |
| 455 | batch_idx = array_ops.zeros_like(label_states[2:]) |
| 456 | indices = array_ops.stack([batch_idx, label_states[2:], label_states[1:-1]], |
| 457 | 1) |
| 458 | indices = array_ops.tile( |
| 459 | array_ops.expand_dims(indices, 0), [batch_size, 1, 1]) |
| 460 | batch_idx = array_ops.expand_dims(math_ops.range(batch_size), 1) * [1, 0, 0] |
| 461 | indices += array_ops.expand_dims(batch_idx, 1) |
| 462 | repeats = math_ops.equal(label_seq[:, :-1], label_seq[:, 1:]) |
| 463 | values = 1.0 - math_ops.cast(repeats, dtypes.float32) |
| 464 | batched_shape = [batch_size, num_states, num_states] |
| 465 | label_to_label = array_ops.scatter_nd(indices, values, batched_shape) |
| 466 | |
| 467 | return array_ops.expand_dims(trans, 0) + label_to_label |
| 468 | |
| 469 | |
| 470 | def ctc_state_log_probs(seq_lengths, max_seq_length): |
no test coverage detected