Circularly moves dims left or right. Effectively identical to: ```python numpy.transpose(x, numpy.roll(numpy.arange(len(x.shape)), shift)) ``` When `validate_args=False` additional graph-runtime checks are performed. These checks entail moving data from to GPU to CPU. Example: `
(x, shift, name="rotate_transpose")
| 581 | |
| 582 | |
| 583 | def rotate_transpose(x, shift, name="rotate_transpose"): |
| 584 | """Circularly moves dims left or right. |
| 585 | |
| 586 | Effectively identical to: |
| 587 | |
| 588 | ```python |
| 589 | numpy.transpose(x, numpy.roll(numpy.arange(len(x.shape)), shift)) |
| 590 | ``` |
| 591 | |
| 592 | When `validate_args=False` additional graph-runtime checks are |
| 593 | performed. These checks entail moving data from to GPU to CPU. |
| 594 | |
| 595 | Example: |
| 596 | |
| 597 | ```python |
| 598 | x = tf.random.normal([1, 2, 3, 4]) # Tensor of shape [1, 2, 3, 4]. |
| 599 | rotate_transpose(x, -1).shape == [2, 3, 4, 1] |
| 600 | rotate_transpose(x, -2).shape == [3, 4, 1, 2] |
| 601 | rotate_transpose(x, 1).shape == [4, 1, 2, 3] |
| 602 | rotate_transpose(x, 2).shape == [3, 4, 1, 2] |
| 603 | rotate_transpose(x, 7).shape == rotate_transpose(x, 3).shape # [2, 3, 4, 1] |
| 604 | rotate_transpose(x, -7).shape == rotate_transpose(x, -3).shape # [4, 1, 2, 3] |
| 605 | ``` |
| 606 | |
| 607 | Args: |
| 608 | x: `Tensor`. |
| 609 | shift: `Tensor`. Number of dimensions to transpose left (shift<0) or |
| 610 | transpose right (shift>0). |
| 611 | name: Python `str`. The name to give this op. |
| 612 | |
| 613 | Returns: |
| 614 | rotated_x: Input `Tensor` with dimensions circularly rotated by shift. |
| 615 | |
| 616 | Raises: |
| 617 | TypeError: if shift is not integer type. |
| 618 | """ |
| 619 | with ops.name_scope(name, values=[x, shift]): |
| 620 | x = ops.convert_to_tensor(x, name="x") |
| 621 | shift = ops.convert_to_tensor(shift, name="shift") |
| 622 | # We do not assign back to preserve constant-ness. |
| 623 | check_ops.assert_integer(shift) |
| 624 | shift_value_static = tensor_util.constant_value(shift) |
| 625 | ndims = x.get_shape().ndims |
| 626 | if ndims is not None and shift_value_static is not None: |
| 627 | if ndims < 2: |
| 628 | return x |
| 629 | shift_value_static = np.sign(shift_value_static) * ( |
| 630 | abs(shift_value_static) % ndims) |
| 631 | if shift_value_static == 0: |
| 632 | return x |
| 633 | perm = np.roll(np.arange(ndims), shift_value_static) |
| 634 | return array_ops.transpose(x, perm=perm) |
| 635 | else: |
| 636 | # Consider if we always had a positive shift, and some specified |
| 637 | # direction. |
| 638 | # When shifting left we want the new array: |
| 639 | # last(x, n-shift) + first(x, shift) |
| 640 | # and if shifting right then we want: |