upsampling layer for 3d inputs repeats the 1st 2nd and 3rd dimensions of the data by size0 size1 and size2 respectively example inputshape 2 1 2 1 3 x np onesinputshape y keras layers upsampling3dsize2 2 2x y shape 2 2 4 2 3 args size int or tuple of 3 integers the upsampling factors for dim1 dim2 and dim3 dataformat a string one of channelslast default or channelsfirst the ordering of the dimensions in the inputs channelslast corresponds to inputs with shape batchsize spatialdim1 spatialdim2 spatialdim3 channels while channelsfirst corresponds to inputs with shape batchsize channels spatialdim1 spatialdim2 spatialdim3 when unspecified uses imagedataformat value found in your keras config file at keraskeras json if exists else channelslast defaults to channelslast input shape 5d tensor with shape if dataformat is channelslast batchsize dim1 dim2 dim3 channels if dataformat is channelsfirst batchsize channels dim1 dim2 dim3 output shape 5d tensor with shape if dataformat is channelslast batchsize upsampleddim1 upsampleddim2 upsampleddim3 channels if dataformat is channelsfirst batchsize channels upsampleddim1 upsampleddim2 upsampleddim3 resizes the volume contained in a 5d tensor args x tensor or variable to resize depthfactor positive integer heightfactor positive integer widthfactor positive integer dataformat one of channelsfirst channelslast returns resized tensor upsampling layer for 3d inputs repeats the 1st 2nd and 3rd dimensions of the data by size 0 size 1 and size 2 respectively example input_shape 2 1 2 1 3 x np ones input_shape y keras layers upsampling3d size 2 2 2 x y shape 2 2 4 2 3 args size int or tuple of 3 integers the upsampling factors for dim1 dim2 and dim3 data_format a string one of channels_last default or channels_first the ordering of the dimensions in the inputs channels_last corresponds to inputs with shape batch_size spatial_dim1 spatial_dim2 spatial_dim3 channels while channels_first corresponds to inputs with shape batch_size channels spatial_dim1 spatial_dim2 spatial_dim3 when unspecified uses image_data_format value found in your keras config file at keras keras json if exists else channels_last defaults to channels_last input shape 5d tensor with shape if data_format is channels_last batch_size dim1 dim2 dim3 channels if data_format is channels_first batch_size channels dim1 dim2 dim3 output shape 5d tensor with shape if data_format is channels_last batch_size upsampled_dim1 upsampled_dim2 upsampled_dim3 channels if data_format is channels_first batch_size channels upsampled_dim1 upsampled_dim2 upsampled_dim3 resizes the volume contained in a 5d tensor args x tensor or variable to resize depth_factor positive integer height_factor positive integer width_factor positive integer data_format one of channels_first channels_last returns resized tensor
from keras import backend
from keras import ops
from keras.api_export import keras_export
from keras.layers.input_spec import InputSpec
from keras.layers.layer import Layer
from keras.utils import argument_validation


@keras_export("keras.layers.UpSampling3D")
class UpSampling3D(Layer):
    

    def __init__(self, size=(2, 2, 2), data_format=None, **kwargs):
        super().__init__(**kwargs)
        self.data_format = backend.config.standardize_data_format(data_format)
        self.size = argument_validation.standardize_tuple(size, 3, "size")
        self.input_spec = InputSpec(ndim=5)

    def compute_output_shape(self, input_shape):
        if self.data_format == "channels_first":
            dim1 = (
                self.size[0] * input_shape[2]
                if input_shape[2] is not None
                else None
            )
            dim2 = (
                self.size[1] * input_shape[3]
                if input_shape[3] is not None
                else None
            )
            dim3 = (
                self.size[2] * input_shape[4]
                if input_shape[4] is not None
                else None
            )
            return (input_shape[0], input_shape[1], dim1, dim2, dim3)
        else:
            dim1 = (
                self.size[0] * input_shape[1]
                if input_shape[1] is not None
                else None
            )
            dim2 = (
                self.size[1] * input_shape[2]
                if input_shape[2] is not None
                else None
            )
            dim3 = (
                self.size[2] * input_shape[3]
                if input_shape[3] is not None
                else None
            )
            return (input_shape[0], dim1, dim2, dim3, input_shape[4])

    def call(self, inputs):
        return self._resize_volumes(
            inputs, self.size[0], self.size[1], self.size[2], self.data_format
        )

    def get_config(self):
        config = {"size": self.size, "data_format": self.data_format}
        base_config = super().get_config()
        return {**base_config, **config}

    def _resize_volumes(
        self, x, depth_factor, height_factor, width_factor, data_format
    ):
        
        if data_format == "channels_first":
            output = ops.repeat(x, depth_factor, axis=2)
            output = ops.repeat(output, height_factor, axis=3)
            output = ops.repeat(output, width_factor, axis=4)
            return output
        elif data_format == "channels_last":
            output = ops.repeat(x, depth_factor, axis=1)
            output = ops.repeat(output, height_factor, axis=2)
            output = ops.repeat(output, width_factor, axis=3)
            return output
        else:
            raise ValueError(f"Invalid data_format: {data_format}")