diff --git a/keras/src/backend/jax/numpy.py b/keras/src/backend/jax/numpy.py index 95e71d77c72..ea7a725bdf0 100644 --- a/keras/src/backend/jax/numpy.py +++ b/keras/src/backend/jax/numpy.py @@ -19,11 +19,13 @@ def rot90(array, k=1, axes=(0, 1)): """Rotate an array by 90 degrees in the specified plane.""" if array.ndim < 2: raise ValueError( - f"Input array must have at least 2 dimensions. Received: array.ndim={array.ndim}" + f"Input array must have at least 2 dimensions. " + f"Received: array.ndim={array.ndim}" ) if len(axes) != 2 or axes[0] == axes[1]: raise ValueError( - f"Invalid axes: {axes}. Axes must be a tuple of two different dimensions." + f"Invalid axes: {axes}. Axes must be a tuple of " + "two different dimensions." ) return jnp.rot90(array, k=k, axes=axes) diff --git a/keras/src/backend/numpy/numpy.py b/keras/src/backend/numpy/numpy.py index afe2061417b..73e17f0184a 100644 --- a/keras/src/backend/numpy/numpy.py +++ b/keras/src/backend/numpy/numpy.py @@ -12,11 +12,13 @@ def rot90(array, k=1, axes=(0, 1)): """Rotate an array by 90 degrees in the specified plane.""" if array.ndim < 2: raise ValueError( - f"Input array must have at least 2 dimensions. Received: array.ndim={array.ndim}" + "Input array must have at least 2 dimensions. " + f"Received: array.ndim={array.ndim}" ) if len(axes) != 2 or axes[0] == axes[1]: raise ValueError( - f"Invalid axes: {axes}. Axes must be a tuple of two different dimensions." + f"Invalid axes: {axes}. Axes must be a tuple " + "of two different dimensions." ) return np.rot90(array, k=k, axes=axes) diff --git a/keras/src/backend/openvino/core.py b/keras/src/backend/openvino/core.py index 1d50c815382..4daf2a61bbb 100644 --- a/keras/src/backend/openvino/core.py +++ b/keras/src/backend/openvino/core.py @@ -242,9 +242,9 @@ def __getitem__(self, indices): def __len__(self): ov_output = self.output ov_shape = ov_output.get_partial_shape() - assert ov_shape.rank.is_static and ov_shape.rank.get_length() > 0, ( - "rank must be static and greater than zero" - ) + assert ( + ov_shape.rank.is_static and ov_shape.rank.get_length() > 0 + ), "rank must be static and greater than zero" assert ov_shape[0].is_static, "the first dimension must be static" return ov_shape[0].get_length() @@ -425,10 +425,10 @@ def convert_to_numpy(x): x = x.value else: return x.value.data - assert isinstance(x, OpenVINOKerasTensor), ( - "unsupported type {} for `convert_to_numpy` in openvino backend".format( - type(x) - ) + assert isinstance( + x, OpenVINOKerasTensor + ), "unsupported type {} for `convert_to_numpy` in openvino backend".format( + type(x) ) try: ov_result = x.output diff --git a/keras/src/backend/openvino/nn.py b/keras/src/backend/openvino/nn.py index c17d4af6e94..fcd9a8bb1b0 100644 --- a/keras/src/backend/openvino/nn.py +++ b/keras/src/backend/openvino/nn.py @@ -325,9 +325,9 @@ def depthwise_conv( data_format = backend.standardize_data_format(data_format) num_spatial_dims = inputs.get_partial_shape().rank.get_length() - 2 - assert data_format == "channels_last", ( - "`depthwise_conv` is supported only for channels_last data_format" - ) + assert ( + data_format == "channels_last" + ), "`depthwise_conv` is supported only for channels_last data_format" strides = _adjust_strides_dilation(strides, num_spatial_dims) dilation_rate = _adjust_strides_dilation(dilation_rate, num_spatial_dims) diff --git a/keras/src/backend/openvino/numpy.py b/keras/src/backend/openvino/numpy.py index e660d28ef03..76f83566af5 100644 --- a/keras/src/backend/openvino/numpy.py +++ b/keras/src/backend/openvino/numpy.py @@ -81,9 +81,9 @@ def mean(x, axis=None, keepdims=False): def max(x, axis=None, keepdims=False, initial=None): - assert initial is None, ( - "`max` with not None initial is not supported by openvino backend" - ) + assert ( + initial is None + ), "`max` with not None initial is not supported by openvino backend" x = get_ov_output(x) reduce_axis = ov_opset.constant(axis, Type.i32).output(0) return OpenVINOKerasTensor( @@ -260,9 +260,9 @@ def bincount(x, weights=None, minlength=0, sparse=False): def broadcast_to(x, shape): - assert isinstance(shape, (tuple, list)), ( - "`broadcast_to` is supported only for tuple and list `shape`" - ) + assert isinstance( + shape, (tuple, list) + ), "`broadcast_to` is supported only for tuple and list `shape`" target_shape = ov_opset.constant(list(shape), Type.i32).output(0) x = get_ov_output(x) return OpenVINOKerasTensor(ov_opset.broadcast(x, target_shape).output(0)) diff --git a/keras/src/backend/tensorflow/numpy.py b/keras/src/backend/tensorflow/numpy.py index 80503bddcdd..925f9d44ac2 100644 --- a/keras/src/backend/tensorflow/numpy.py +++ b/keras/src/backend/tensorflow/numpy.py @@ -26,43 +26,47 @@ def rot90(array, k=1, axes=(0, 1)): """Rotate an array by 90 degrees in the specified plane.""" array = convert_to_tensor(array) - + if array.shape.rank < 2: raise ValueError( - f"Input array must have at least 2 dimensions. Received: array.ndim={array.shape.rank}" + f"Input array must have at least 2 dimensions. " + f"Received: array.ndim={array.shape.rank}" ) - + if len(axes) != 2 or axes[0] == axes[1]: raise ValueError( - f"Invalid axes: {axes}. Axes must be a tuple of two different dimensions." + f"Invalid axes: {axes}. Axes must be a tuple of " + "two different dimensions." ) - + k = k % 4 if k == 0: return array - - axes = tuple(axis if axis >= 0 else array.shape.rank + axis for axis in axes) - + + axes = tuple( + axis if axis >= 0 else array.shape.rank + axis for axis in axes + ) + perm = [i for i in range(array.shape.rank) if i not in axes] perm.extend(axes) array = tf.transpose(array, perm) - + shape = tf.shape(array) non_rot_shape = shape[:-2] rot_shape = shape[-2:] - + array = tf.reshape(array, tf.concat([[-1], rot_shape], axis=0)) - + for _ in range(k): array = tf.transpose(array, [0, 2, 1]) array = tf.reverse(array, axis=[1]) array = tf.reshape(array, tf.concat([non_rot_shape, rot_shape], axis=0)) - + inv_perm = [0] * len(perm) for i, p in enumerate(perm): inv_perm[p] = i array = tf.transpose(array, inv_perm) - + return array diff --git a/keras/src/backend/torch/numpy.py b/keras/src/backend/torch/numpy.py index 84fb9ec3311..14c5173fefe 100644 --- a/keras/src/backend/torch/numpy.py +++ b/keras/src/backend/torch/numpy.py @@ -27,35 +27,40 @@ def rot90(array, k=1, axes=(0, 1)): """Rotate an array by 90 degrees in the specified plane using PyTorch. - + Args: array: Input tensor k: Number of 90-degree rotations (default=1) - axes: Tuple of two axes that define the plane of rotation (default=(0,1)) - + axes: Tuple of two axes that define the + plane of rotation (defaults to `(0, 1)`). + Returns: Rotated tensor """ array = convert_to_tensor(array) - + if array.ndim < 2: raise ValueError( - f"Input array must have at least 2 dimensions. Received: array.ndim={array.ndim}" + "Input array must have at least 2 dimensions. " + f"Received: array.ndim={array.ndim}" ) if len(axes) != 2 or axes[0] == axes[1]: raise ValueError( - f"Invalid axes: {axes}. Axes must be a tuple of two different dimensions." + f"Invalid axes: {axes}. Axes must be a tuple " + "of two different dimensions." ) - + axes = tuple(axis if axis >= 0 else array.ndim + axis for axis in axes) if not builtins.all(0 <= axis < array.ndim for axis in axes): - raise ValueError(f"Invalid axes {axes} for tensor with {array.ndim} dimensions") - + raise ValueError( + f"Invalid axes {axes} for tensor with {array.ndim} dimensions" + ) + rotated = torch.rot90(array, k=k, dims=axes) if isinstance(array, np.ndarray): rotated = rotated.cpu().numpy() - + return rotated diff --git a/keras/src/layers/attention/multi_head_attention_test.py b/keras/src/layers/attention/multi_head_attention_test.py index f4019b2834b..c4ed2f00b93 100644 --- a/keras/src/layers/attention/multi_head_attention_test.py +++ b/keras/src/layers/attention/multi_head_attention_test.py @@ -643,9 +643,11 @@ def test_multi_head_attention_output_shape_as_int(self): value = random.uniform((2, 4, 16)) output = mha(query=query, value=value) - assert output.shape == (2, 4, 8), ( - f"Expected shape (2, 4, 8), got {output.shape}" - ) + assert output.shape == ( + 2, + 4, + 8, + ), f"Expected shape (2, 4, 8), got {output.shape}" def test_multi_head_attention_output_shape_as_tuple(self): """Test MultiHeadAttention with output_shape as a tuple.""" @@ -656,9 +658,12 @@ def test_multi_head_attention_output_shape_as_tuple(self): value = random.uniform((2, 4, 16)) output = mha(query=query, value=value) - assert output.shape == (2, 4, 8, 8), ( - f"Expected shape (2, 4, 8, 8), got {output.shape}" - ) + assert output.shape == ( + 2, + 4, + 8, + 8, + ), f"Expected shape (2, 4, 8, 8), got {output.shape}" def test_multi_head_attention_output_shape_error(self): with self.assertRaisesRegex(ValueError, r"Invalid `output_shape`"): diff --git a/keras/src/ops/numpy.py b/keras/src/ops/numpy.py index 97aa58c500f..20383e5ad3b 100644 --- a/keras/src/ops/numpy.py +++ b/keras/src/ops/numpy.py @@ -34,10 +34,14 @@ def compute_output_spec(self, array): ) if len(self.axes) != 2 or self.axes[0] == self.axes[1]: raise ValueError( - f"Invalid axes: {self.axes}. Axes must be a tuple of two different dimensions." + f"Invalid axes: {self.axes}. " + "Axes must be a tuple of two different dimensions." ) axis1, axis2 = self.axes - array_shape[axis1], array_shape[axis2] = array_shape[axis2], array_shape[axis1] + array_shape[axis1], array_shape[axis2] = ( + array_shape[axis2], + array_shape[axis1], + ) return KerasTensor(shape=array_shape, dtype=array.dtype) @@ -45,13 +49,15 @@ def compute_output_spec(self, array): def rot90(array, k=1, axes=(0, 1)): """Rotate an array by 90 degrees in the plane specified by axes. - This function rotates an array counterclockwise by 90 degrees `k` times - in the plane specified by `axes`. Supports arrays of two or more dimensions. + This function rotates an array counterclockwise + by 90 degrees `k` times in the plane specified by `axes`. + Supports arrays of two or more dimensions. Args: array: Input array to rotate. k: Number of times the array is rotated by 90 degrees. - axes: A tuple of two integers specifying the plane for rotation. + axes: A tuple of two integers specifying the + plane of rotation (defaults to `(0, 1)`). Returns: Rotated array. diff --git a/keras/src/ops/numpy_test.py b/keras/src/ops/numpy_test.py index 8980e1e5075..859a23a0203 100644 --- a/keras/src/ops/numpy_test.py +++ b/keras/src/ops/numpy_test.py @@ -24,7 +24,9 @@ def test_basic(self): array = np.array([[1, 2], [3, 4]]) rotated = knp.rot90(array) expected = np.array([[2, 4], [1, 3]]) - assert np.array_equal(rotated, expected), f"Failed basic 2D test: {rotated}" + assert np.array_equal( + rotated, expected + ), f"Failed basic 2D test: {rotated}" def test_multiple_k(self): array = np.array([[1, 2], [3, 4]]) @@ -48,7 +50,9 @@ def test_axes(self): array = np.arange(8).reshape((2, 2, 2)) rotated = knp.rot90(array, k=1, axes=(1, 2)) expected = np.array([[[1, 3], [0, 2]], [[5, 7], [4, 6]]]) - assert np.array_equal(rotated, expected), f"Failed custom axes test: {rotated}" + assert np.array_equal( + rotated, expected + ), f"Failed custom axes test: {rotated}" def test_single_image(self): array = np.random.random((4, 4, 3)) @@ -68,7 +72,7 @@ def test_invalid_axes(self): knp.rot90(array, axes=(0, 0)) except ValueError as e: assert ( - "Invalid axes: (0, 0). Axes must be a tuple of two different dimensions." + "Invalid axes: (0, 0). Axes must be a tuple of two different" in str(e) ), f"Failed invalid axes test: {e}" else: @@ -79,11 +83,11 @@ def test_invalid_rank(self): try: knp.rot90(array) except ValueError as e: - assert ( - "Input array must have at least 2 dimensions." in str(e) + assert "Input array must have at least 2 dimensions." in str( + e ), f"Failed invalid rank test: {e}" else: - raise AssertionError("Failed to raise error for invalid input rank") + raise AssertionError("Failed to raise error for invalid input") class NumpyTwoInputOpsDynamicShapeTest(testing.TestCase):