commonlyused neural network operations not included in numpy from keras import backend from keras apiexport import kerasexport from keras backend import kerastensor from keras backend import anysymbolictensors from keras backend import standardizedataformat from keras backend common backendutils import computeconvtransposeoutputshape from keras ops import operationutils from keras ops operation import operation from keras ops operationutils import reduceshape class reluoperation def callself x return backend nn relux def computeoutputspecself x return kerastensorx shape dtypex dtype kerasexportkeras ops relu keras ops nn relu def relux if anysymbolictensorsx return relu symboliccallx return backend nn relux class relu6operation def callself x return backend nn relu6x def computeoutputspecself x return kerastensorx shape dtypex dtype kerasexportkeras ops relu6 keras ops nn relu6 def relu6x if anysymbolictensorsx return relu6 symboliccallx return backend nn relu6x class sigmoidoperation def callself x return backend nn sigmoidx def computeoutputspecself x return kerastensorx shape dtypex dtype kerasexportkeras ops sigmoid keras ops nn sigmoid def sigmoidx if anysymbolictensorsx return sigmoid symboliccallx return backend nn sigmoidx class softplusoperation def callself x return backend nn softplusx def computeoutputspecself x return kerastensorx shape dtypex dtype kerasexportkeras ops softplus keras ops nn softplus def softplusx if anysymbolictensorsx return softplus symboliccallx return backend nn softplusx class softsignoperation def callself x return backend nn softsignx def computeoutputspecself x return kerastensorx shape dtypex dtype kerasexportkeras ops softsign keras ops nn softsign def softsignx if anysymbolictensorsx return softsign symboliccallx return backend nn softsignx class siluoperation def callself x return backend nn silux def computeoutputspecself x return kerastensorx shape dtypex dtype kerasexport keras ops silu keras ops nn silu keras ops swish keras ops nn swish def silux if anysymbolictensorsx return silu symboliccallx return backend nn silux class logsigmoidoperation def callself x return backend nn logsigmoidx def computeoutputspecself x return kerastensorx shape dtypex dtype kerasexport keras ops logsigmoid keras ops nn logsigmoid def logsigmoidx if anysymbolictensorsx return logsigmoid symboliccallx return backend nn logsigmoidx class leakyreluoperation def initself negativeslope0 2 super init self negativeslope negativeslope def callself x return backend nn leakyrelux self negativeslope def computeoutputspecself x return kerastensorx shape dtypex dtype kerasexportkeras ops leakyrelu keras ops nn leakyrelu def leakyrelux negativeslope0 2 if anysymbolictensorsx return leakyrelunegativeslope symboliccallx return backend nn leakyrelux negativeslopenegativeslope class hardsigmoidoperation def callself x return backend nn hardsigmoidx def computeoutputspecself x return kerastensorx shape dtypex dtype kerasexport keras ops hardsigmoid keras ops nn hardsigmoid def hardsigmoidx if anysymbolictensorsx return hardsigmoid symboliccallx return backend nn hardsigmoidx class hardswishoperation def callself x return backend nn hardswishx def computeoutputspecself x return kerastensorx shape dtypex dtype kerasexportkeras ops hardswish keras ops nn hardswish def hardswishx if anysymbolictensorsx return hardswish symboliccallx return backend nn hardswishx class eluoperation def initself alpha1 0 super init self alpha alpha def callself x return backend nn elux alphaself alpha def computeoutputspecself x return kerastensorx shape dtypex dtype kerasexportkeras ops elu keras ops nn elu def elux alpha1 0 if anysymbolictensorsx return elualpha symboliccallx return backend nn elux alphaalpha class seluoperation def callself x return backend nn selux def computeoutputspecself x return kerastensorx shape dtypex dtype kerasexportkeras ops selu keras ops nn selu def selux if anysymbolictensorsx return selu symboliccallx return backend nn selux class geluoperation def initself approximatetrue super init self approximate approximate def callself x return backend nn gelux self approximate def computeoutputspecself x return kerastensorx shape dtypex dtype kerasexportkeras ops gelu keras ops nn gelu def gelux approximatetrue if anysymbolictensorsx return geluapproximate symboliccallx return backend nn gelux approximate class softmaxoperation def initself axis1 super init self axis axis def callself x return backend nn softmaxx axisself axis def computeoutputspecself x return kerastensorx shape dtypex dtype kerasexportkeras ops softmax keras ops nn softmax def softmaxx axis1 if anysymbolictensorsx return softmaxaxis symboliccallx if isinstanceaxis tuple originalshape x shape newshape skipdims setaxis i 0 while i lenoriginalshape if i in skipdims size 1 while i in skipdims size originalshapei i 1 newshape appendsize else newshape appendoriginalshapei i 1 x backend numpy reshapex newshape x backend nn softmaxx axis1 x backend numpy reshapex originalshape return x else return backend nn softmaxx axisaxis class logsoftmaxoperation def initself axis1 super init self axis axis def callself x return backend nn logsoftmaxx axisself axis def computeoutputspecself x return kerastensorx shape dtypex dtype kerasexport keras ops logsoftmax keras ops nn logsoftmax def logsoftmaxx axis1 if anysymbolictensorsx return logsoftmaxaxis symboliccallx if isinstanceaxis tuple originalshape x shape newshape skipdims setaxis i 0 while i lenoriginalshape if i in skipdims size 1 while i in skipdims size originalshapei i 1 newshape appendsize else newshape appendoriginalshapei i 1 x backend numpy reshapex newshape x backend nn logsoftmaxx axis1 x backend numpy reshapex originalshape return x else return backend nn logsoftmaxx axisaxis class maxpooloperation def init self poolsize stridesnone paddingvalid dataformatnone super init self poolsize poolsize self strides strides self padding padding lower self dataformat dataformat def callself inputs return backend nn maxpool inputs self poolsize self strides self padding self dataformat def computeoutputspecself inputs outputshape operationutils computepoolingoutputshape inputs shape self poolsize self strides self padding self dataformat return kerastensoroutputshape dtypeinputs dtype kerasexportkeras ops maxpool keras ops nn maxpool def maxpool inputs poolsize stridesnone paddingvalid dataformatnone dataformat standardizedataformatdataformat padding padding lower if anysymbolictensorsinputs return maxpool poolsize strides padding dataformat symboliccallinputs return backend nn maxpoolinputs poolsize strides padding dataformat class averagepooloperation def init self poolsize stridesnone paddingvalid dataformatnone super init self poolsize poolsize self strides strides self padding padding lower self dataformat dataformat def callself inputs return backend nn averagepool inputs self poolsize self strides self padding self dataformat def computeoutputspecself inputs outputshape operationutils computepoolingoutputshape inputs shape self poolsize self strides self padding self dataformat return kerastensoroutputshape dtypeinputs dtype kerasexport keras ops averagepool keras ops nn averagepool def averagepool inputs poolsize stridesnone paddingvalid dataformatnone dataformat standardizedataformatdataformat padding padding lower if anysymbolictensorsinputs return averagepool poolsize strides padding dataformat symboliccallinputs return backend nn averagepool inputs poolsize strides padding dataformat class convoperation def init self strides1 paddingvalid dataformatnone dilationrate1 super init self strides strides self padding padding lower self dataformat dataformat self dilationrate dilationrate def callself inputs kernel return backend nn conv inputs kernel stridesself strides paddingself padding dataformatself dataformat dilationrateself dilationrate def computeoutputspecself inputs kernel outputshape operationutils computeconvoutputshape inputs shape kernel shape1 kernel shape 2 self strides self padding self dataformat self dilationrate return kerastensoroutputshape dtypeinputs dtype kerasexportkeras ops conv keras ops nn conv def conv inputs kernel strides1 paddingvalid dataformatnone dilationrate1 dataformat standardizedataformatdataformat padding padding lower if anysymbolictensorsinputs return convstrides padding dataformat dilationrate symboliccall inputs kernel return backend nn conv inputs kernel strides padding dataformat dilationrate class depthwiseconvoperation def init self strides1 paddingvalid dataformatnone dilationrate1 super init self strides strides self padding padding lower self dataformat dataformat self dilationrate dilationrate def callself inputs kernel return backend nn depthwiseconv inputs kernel self strides self padding self dataformat self dilationrate def computeoutputspecself inputs kernel outputshape operationutils computeconvoutputshape inputs shape kernel shape1 kernel shape2 kernel shape 2 self strides self padding self dataformat self dilationrate return kerastensoroutputshape dtypeinputs dtype kerasexport keras ops depthwiseconv keras ops nn depthwiseconv def depthwiseconv inputs kernel strides1 paddingvalid dataformatnone dilationrate1 dataformat standardizedataformatdataformat padding padding lower if anysymbolictensorsinputs return depthwiseconv strides padding dataformat dilationrate symboliccallinputs kernel return backend nn depthwiseconv inputs kernel strides padding dataformat dilationrate class separableconvoperation def init self strides1 paddingvalid dataformatnone dilationrate1 super init self strides strides self padding padding lower self dataformat dataformat self dilationrate dilationrate def callself inputs depthwisekernel pointwisekernel return backend nn separableconv inputs depthwisekernel pointwisekernel self strides self padding self dataformat self dilationrate def computeoutputspecself inputs depthwisekernel pointwisekernel outputshape list depthwiseconv inputs depthwisekernel self strides self padding self dataformat self dilationrate shape if self dataformat channelslast outputshape1 pointwisekernel shape1 else outputshape1 pointwisekernel shape1 return kerastensoroutputshape dtypeinputs dtype kerasexport keras ops separableconv keras ops nn separableconv def separableconv inputs depthwisekernel pointwisekernel strides1 paddingvalid dataformatnone dilationrate1 dataformat standardizedataformatdataformat padding padding lower if anysymbolictensorsinputs return separableconv strides padding dataformat dilationrate symboliccallinputs depthwisekernel pointwisekernel return backend nn separableconv inputs depthwisekernel pointwisekernel strides padding dataformat dilationrate class convtransposeoperation def init self strides paddingvalid outputpaddingnone dataformatnone dilationrate1 super init self strides strides self outputpadding outputpadding self padding padding lower self dataformat dataformat self dilationrate dilationrate def call self inputs kernel return backend nn convtranspose inputs kernel self strides self outputpadding self padding self dataformat self dilationrate def computeoutputspecself inputs kernel kernelsize kernel shape 2 filters kernel shape2 outputshape computeconvtransposeoutputshape inputs shape kernelsize filters self strides self padding self outputpadding self dataformat self dilationrate return kerastensoroutputshape dtypeinputs dtype kerasexport keras ops convtranspose keras ops nn convtranspose def convtranspose inputs kernel strides paddingvalid outputpaddingnone dataformatnone dilationrate1 dataformat standardizedataformatdataformat padding padding lower if anysymbolictensorsinputs return convtranspose strides padding outputpadding dataformat dilationrate symboliccallinputs kernel return backend nn convtranspose inputs kernel strides padding outputpadding dataformat dilationrate class onehotoperation def initself numclasses axis1 dtypenone super init self numclasses numclasses self axis axis self dtype dtype or backend floatx def callself x return backend nn onehot x self numclasses axisself axis dtypeself dtype def computeoutputspecself x xshape listgetattrx shape if self axis 1 xshape appendself numclasses elif self axis 0 and self axis lenxshape xshape insertself axis self numclasses else raise valueerror faxis must be 1 or between 0 lenx shape but freceived self axis return kerastensorxshape dtypeself dtype kerasexportkeras ops onehot keras ops nn onehot def onehotx numclasses axis1 dtypenone if anysymbolictensorsx return onehotnumclasses axisaxis dtypedtype symboliccallx return backend nn onehot x numclasses axisaxis dtypedtype or backend floatx class binarycrossentropyoperation def initself fromlogitsfalse super init self fromlogits fromlogits def callself target output return backend nn binarycrossentropy target output fromlogitsself fromlogits def computeoutputspecself target output if target shape output shape raise valueerror arguments target and output must have the same shape received ftarget shapetarget shape output shapeoutput shape return kerastensoroutput shape dtypeoutput dtype kerasexport keras ops binarycrossentropy keras ops nn binarycrossentropy def binarycrossentropytarget output fromlogitsfalse if anysymbolictensorstarget output return binarycrossentropyfromlogitsfromlogits symboliccall target output return backend nn binarycrossentropy target output fromlogitsfromlogits class categoricalcrossentropyoperation def initself fromlogitsfalse axis1 super init self fromlogits fromlogits self axis axis def callself target output return backend nn categoricalcrossentropy target output fromlogitsself fromlogits axisself axis def computeoutputspecself target output if target shape output shape raise valueerror arguments target and output must have the same shape received ftarget shapetarget shape output shapeoutput shape if lentarget shape 1 raise valueerror arguments target and output must be at least rank 1 received ftarget shapetarget shape output shapeoutput shape return kerastensoroutput shape 1 dtypeoutput dtype kerasexport keras ops categoricalcrossentropy keras ops nn categoricalcrossentropy def categoricalcrossentropytarget output fromlogitsfalse axis1 if anysymbolictensorstarget output return categoricalcrossentropy fromlogitsfromlogits axisaxis symboliccalltarget output return backend nn categoricalcrossentropy target output fromlogitsfromlogits axisaxis class sparsecategoricalcrossentropyoperation def initself fromlogitsfalse axis1 super init self fromlogits fromlogits self axis axis def callself target output return backend nn sparsecategoricalcrossentropy target output fromlogitsself fromlogits axisself axis def computeoutputspecself target output if lenoutput shape 1 raise valueerror argument output must be at least rank 1 received foutput shapeoutput shape targetshape target shape if lentargetshape lenoutput shape and targetshape1 1 targetshape targetshape 1 if targetshape output shape 1 raise valueerror arguments target and output must have the same shape up until the last dimension ftarget shapetarget shape output shapeoutput shape return kerastensoroutput shape 1 dtypeoutput dtype kerasexport keras ops sparsecategoricalcrossentropy keras ops nn sparsecategoricalcrossentropy def sparsecategoricalcrossentropytarget output fromlogitsfalse axis1 if anysymbolictensorstarget output return sparsecategoricalcrossentropy fromlogitsfromlogits axisaxis symboliccalltarget output return backend nn sparsecategoricalcrossentropy target output fromlogitsfromlogits axisaxis class multihotoperation def initself numtokensnone axis1 dtypenone namenone super initname self numtokens numtokens self axis axis self dtype dtype or backend floatx def callself inputs return backend nn multihot inputs numclassesself numtokens axisself axis dtypeself dtype def computeoutputspecself inputs xshape listgetattrinputs shape if self axis 1 xshape appendself numtokens elif self axis 0 and self axis lenxshape xshape insertself axis self numtokens else raise valueerror faxis must be 1 or between 0 leninputs shape but freceived self axis if lenxshape 2 xshape xshape1 else xshape xshape0 xshape2 return kerastensorxshape dtypeinputs dtype kerasexport keras ops multihot keras ops nn multihot def multihotinputs numtokens axis1 dtypenone if anysymbolictensorsinputs return multihotnumtokens axis dtype symboliccallinputs return backend nn multihotinputs numtokens axis dtype class momentsoperation def initself axes keepdimsfalse synchronizedfalse namenone super initname self axes axes self keepdims keepdims self synchronized synchronized def callself x return backend nn moments x axesself axes keepdimsself keepdims synchronizedself synchronized def computeoutputspecself x return kerastensor reduceshapex shape axisself axes keepdimsself keepdims dtypex dtype kerastensor reduceshapex shape axisself axes keepdimsself keepdims dtypex dtype kerasexport keras ops moments keras ops nn moments def momentsx axes keepdimsfalse synchronizedfalse if anysymbolictensorsx return momentsaxes keepdims synchronizedsynchronized symboliccall x return backend nn momentsx axes keepdims synchronizedsynchronized class batchnormoperation def initself axis epsilon namenone super initname self axis axis self epsilon epsilon def checkshapeself name shape expectedshape if shape expectedshape raise valueerror farguments name must be a vector of length fx shapeaxis expected expectedshape freceived shape def computeoutputspecself x mean variance offset scale shape x shapeself axis self checkshapemean tuplemean shape shape self checkshapevariance tuplevariance shape shape if offset is not none self checkshapeoffset tupleoffset shape shape if offset is not scale self checkshapescale tuplescale shape shape return kerastensorx shape dtypex dtype kerasexport keras ops batchnormalization keras ops nn batchnormalization def batchnormalization x mean variance axis offsetnone scalenone epsilon1e3 if anysymbolictensorsx mean variance offset scale return batchnormaxis epsilon symboliccall x mean variance offset scale return backend nn batchnormalization x mean variance axis offset scale epsilon rectified linear unit activation function it is defined as f x max 0 x args x input tensor returns a tensor with the same shape as x example x1 keras ops convert_to_tensor 1 0 0 0 1 0 0 2 keras ops relu x1 array 0 0 0 0 1 0 0 2 dtype float32 rectified linear unit activation function with upper bound of 6 it is defined as f x np clip x 0 6 args x input tensor returns a tensor with the same shape as x example x keras ops convert_to_tensor 3 0 2 0 0 1 0 2 6 0 8 0 keras ops relu6 x array 0 0 0 0 0 1 0 2 6 0 6 0 dtype float32 sigmoid activation function it is defined as f x 1 1 exp x args x input tensor returns a tensor with the same shape as x example x keras ops convert_to_tensor 6 0 1 0 0 0 1 0 6 0 keras ops sigmoid x array 0 00247262 0 7310586 0 5 0 7310586 0 9975274 dtype float32 softplus activation function it is defined as f x log exp x 1 where log is the natural logarithm and exp is the exponential function args x input tensor returns a tensor with the same shape as x example x keras ops convert_to_tensor 0 555 0 0 0 555 keras ops softplus x array 0 45366603 0 6931472 1 008666 dtype float32 softsign activation function it is defined as f x x abs x 1 args x input tensor returns a tensor with the same shape as x example x keras ops convert_to_tensor 0 100 10 0 1 0 0 0 100 0 keras ops softsign x array 0 09090909 0 90909094 0 5 0 0 0 990099 dtype float32 sigmoid linear unit silu activation function also known as swish the silu activation function is computed by the sigmoid function multiplied by its input it is defined as f x x sigmoid x args x input tensor returns a tensor with the same shape as x example x keras ops convert_to_tensor 6 0 1 0 0 0 1 0 6 0 keras ops sigmoid x array 0 00247262 0 7310586 0 5 0 7310586 0 9975274 dtype float32 keras ops silu x array 0 0148357 0 7310586 0 0 0 7310586 5 9851646 dtype float32 logarithm of the sigmoid activation function it is defined as f x log 1 1 exp x args x input tensor returns a tensor with the same shape as x example x keras ops convert_to_tensor 0 541391 0 0 0 50 5 0 keras ops log_sigmoid x array 1 0000418 0 6931472 0 474077 0 00671535 dtype float32 leaky version of a rectified linear unit activation function it allows a small gradient when the unit is not active it is defined as f x alpha x for x 0 or f x x for x 0 args x input tensor negative_slope slope of the activation function at x 0 defaults to 0 2 returns a tensor with the same shape as x example x np array 1 0 1 x_leaky_relu keras ops leaky_relu x print x_leaky_relu array 0 2 0 1 shape 3 dtype float64 hard sigmoid activation function it is defined as 0 if x 2 5 1 if x 2 5 0 2 x 0 5 if 2 5 x 2 5 args x input tensor returns a tensor with the same shape as x example x np array 1 0 1 x_hard_sigmoid keras ops hard_sigmoid x print x_hard_sigmoid array 0 3 0 5 0 7 shape 3 dtype float64 hard swish activation function it is defined as 0 if if x 3 x if x 3 x x 3 6 if 3 x 3 it s a faster piecewise linear approximation of the swish activation args x input tensor returns a tensor with the same shape as x example x keras ops convert_to_tensor 3 0 1 0 0 0 1 0 3 0 keras ops hard_swish x array 0 0 0 3333333 0 0 0 6666667 3 0 shape 5 dtype float32 exponential linear unit activation function it is defined as f x alpha exp x 1 for x 0 f x x for x 0 args x input tensor alpha a scalar slope of positive section defaults to 1 0 returns a tensor with the same shape as x example x np array 1 0 1 x_elu keras ops elu x print x_elu array 0 63212055 0 1 shape 3 dtype float64 scaled exponential linear unit selu activation function it is defined as f x scale alpha exp x 1 for x 0 f x scale x for x 0 args x input tensor returns a tensor with the same shape as x example x np array 1 0 1 x_selu keras ops selu x print x_selu array 1 11133055 0 1 05070098 shape 3 dtype float64 gaussian error linear unit gelu activation function if approximate is true it is defined as f x 0 5 x 1 tanh sqrt 2 pi x 0 044715 x 3 or if approximate is false it is defined as f x x p x x 0 5 x 1 erf x sqrt 2 where p x n 0 1 args x input tensor approximate approximate version of gelu activation defaults to true returns a tensor with the same shape as x example x np array 1 0 1 x_gelu keras ops gelu x print x_gelu array 0 15865525 0 0 84134475 shape 3 dtype float64 softmax activation function the elements of the output vector lie within the range 0 1 and their total sum is exactly 1 excluding the floating point rounding error each vector is processed independently the axis argument specifies the axis along which the function is applied within the input it is defined as f x exp x sum exp x args x input tensor axis integer axis along which the softmax is applied returns a tensor with the same shape as x example x np array 1 0 1 x_softmax keras ops softmax x print x_softmax array 0 09003057 0 24472847 0 66524096 shape 3 dtype float64 log softmax activation function it is defined as f x x max x log sum exp x max x args x input tensor axis integer axis along which the log softmax is applied defaults to 1 returns a tensor with the same shape as x example x np array 1 0 1 x_log_softmax keras ops log_softmax x print x_log_softmax array 2 40760596 1 40760596 0 40760596 shape 3 dtype float64 max pooling operation args inputs tensor of rank n 2 inputs has shape batch_size inputs_spatial_shape num_channels if data_format channels_last or batch_size num_channels inputs_spatial_shape if data_format channels_first pooling happens over the spatial dimensions only pool_size int or tuple list of integers of size len inputs_spatial_shape specifying the size of the pooling window for each spatial dimension of the input tensor if pool_size is int then every spatial dimension shares the same pool_size strides int or tuple list of integers of size len inputs_spatial_shape the stride of the sliding window for each spatial dimension of the input tensor if strides is int then every spatial dimension shares the same strides padding string either valid or same valid means no padding is applied and same results in padding evenly to the left right or up down of the input such that output has the same height width dimension as the input when strides 1 data_format a string either channels_last or channels_first data_format determines the ordering of the dimensions in the inputs if data_format channels_last inputs is of shape batch_size channels while if data_format channels_first inputs is of shape batch_size channels returns a tensor of rank n 2 the result of the max pooling operation average pooling operation args inputs tensor of rank n 2 inputs has shape batch_size inputs_spatial_shape num_channels if data_format channels_last or batch_size num_channels inputs_spatial_shape if data_format channels_first pooling happens over the spatial dimensions only pool_size int or tuple list of integers of size len inputs_spatial_shape specifying the size of the pooling window for each spatial dimension of the input tensor if pool_size is int then every spatial dimension shares the same pool_size strides int or tuple list of integers of size len inputs_spatial_shape the stride of the sliding window for each spatial dimension of the input tensor if strides is int then every spatial dimension shares the same strides padding string either valid or same valid means no padding is applied and same results in padding evenly to the left right or up down of the input such that output has the same height width dimension as the input when strides 1 data_format a string either channels_last or channels_first data_format determines the ordering of the dimensions in the inputs if data_format channels_last inputs is of shape batch_size channels while if data_format channels_first inputs is of shape batch_size channels returns a tensor of rank n 2 the result of the average pooling operation general n d convolution this ops supports 1d 2d and 3d convolution args inputs tensor of rank n 2 inputs has shape batch_size inputs_spatial_shape num_channels if data_format channels_last or batch_size num_channels inputs_spatial_shape if data_format channels_first kernel tensor of rank n 2 kernel has shape kernel_spatial_shape num_input_channels num_output_channels num_input_channels should match the number of channels in inputs strides int or int tuple list of len inputs_spatial_shape specifying the strides of the convolution along each spatial dimension if strides is int then every spatial dimension shares the same strides padding string either valid or same valid means no padding is applied and same results in padding evenly to the left right or up down of the input such that output has the same height width dimension as the input when strides 1 data_format a string either channels_last or channels_first data_format determines the ordering of the dimensions in the inputs if data_format channels_last inputs is of shape batch_size channels while if data_format channels_first inputs is of shape batch_size channels dilation_rate int or int tuple list of len inputs_spatial_shape specifying the dilation rate to use for dilated convolution if dilation_rate is int then every spatial dimension shares the same dilation_rate returns a tensor of rank n 2 the result of the conv operation general n d depthwise convolution this ops supports 1d and 2d depthwise convolution args inputs tensor of rank n 2 inputs has shape batch_size inputs_spatial_shape num_channels if data_format channels_last or batch_size num_channels inputs_spatial_shape if data_format channels_first kernel tensor of rank n 2 kernel has shape kernel_spatial_shape num_input_channels num_channels_multiplier num_input_channels should match the number of channels in inputs strides int or int tuple list of len inputs_spatial_shape specifying the strides of the convolution along each spatial dimension if strides is int then every spatial dimension shares the same strides padding string either valid or same valid means no padding is applied and same results in padding evenly to the left right or up down of the input such that output has the same height width dimension as the input when strides 1 data_format a string either channels_last or channels_first data_format determines the ordering of the dimensions in the inputs if data_format channels_last inputs is of shape batch_size channels while if data_format channels_first inputs is of shape batch_size channels dilation_rate int or int tuple list of len inputs_spatial_shape specifying the dilation rate to use for dilated convolution if dilation_rate is int then every spatial dimension shares the same dilation_rate returns a tensor of rank n 2 the result of the depthwise conv operation general n d separable convolution this ops supports 1d and 2d separable convolution separable_conv is a depthwise conv followed by a pointwise conv args inputs tensor of rank n 2 inputs has shape batch_size inputs_spatial_shape num_channels if data_format channels_last or batch_size num_channels inputs_spatial_shape if data_format channels_first depthwise_kernel tensor of rank n 2 depthwise_kernel has shape kernel_spatial_shape num_input_channels num_channels_multiplier num_input_channels should match the number of channels in inputs pointwise_kernel tensor of rank n 2 pointwise_kernel has shape ones_like kernel_spatial_shape num_input_channels num_channels_multiplier num_output_channels strides int or int tuple list of len inputs_spatial_shape specifying the strides of the convolution along each spatial dimension if strides is int then every spatial dimension shares the same strides padding string either valid or same valid means no padding is applied and same results in padding evenly to the left right or up down of the input such that output has the same height width dimension as the input when strides 1 data_format a string either channels_last or channels_first data_format determines the ordering of the dimensions in the inputs if data_format channels_last inputs is of shape batch_size channels while if data_format channels_first inputs is of shape batch_size channels dilation_rate int or int tuple list of len inputs_spatial_shape specifying the dilation rate to use for dilated convolution if dilation_rate is int then every spatial dimension shares the same dilation_rate returns a tensor of rank n 2 the result of the depthwise conv operation general n d convolution transpose also known as de convolution this ops supports 1d 2d and 3d convolution args inputs tensor of rank n 2 inputs has shape batch_size inputs_spatial_shape num_channels if data_format channels_last or batch_size num_channels inputs_spatial_shape if data_format channels_first kernel tensor of rank n 2 kernel has shape kernel_spatial_shape num_output_channels num_input_channels num_input_channels should match the number of channels in inputs strides int or int tuple list of len inputs_spatial_shape specifying the strides of the convolution along each spatial dimension if strides is int then every spatial dimension shares the same strides padding string either valid or same valid means no padding is applied and same results in padding evenly to the left right or up down of the input such that output has the same height width dimension as the input when strides 1 output_padding int or int tuple list of len inputs_spatial_shape specifying the amount of padding along the height and width of the output tensor can be a single integer to specify the same value for all spatial dimensions the amount of output padding along a given dimension must be lower than the stride along that same dimension if set to none default the output shape is inferred data_format a string either channels_last or channels_first data_format determines the ordering of the dimensions in the inputs if data_format channels_last inputs is of shape batch_size channels while if data_format channels_first inputs is of shape batch_size channels dilation_rate int or int tuple list of len inputs_spatial_shape specifying the dilation rate to use for dilated convolution if dilation_rate is int then every spatial dimension shares the same dilation_rate returns a tensor of rank n 2 the result of the conv operation converts integer tensor x into a one hot tensor the one hot encoding is a representation where each integer value is converted into a binary vector with a length equal to num_classes and the index corresponding to the integer value is marked as 1 while all other indices are marked as 0 args x integer tensor to be encoded the shape can be arbitrary but the dtype should be integer num_classes number of classes for the one hot encoding axis axis along which the encoding is performed defaults to 1 which represents the last axis dtype optional data type of the output tensor if not provided it defaults to the default data type of the backend returns integer tensor one hot encoded tensor with the same shape as x except for the specified axis dimension which will have a length of num_classes the dtype of the output tensor is determined by dtype or the default data type of the backend example x keras ops convert_to_tensor 1 3 2 0 one_hot x num_classes 4 array 0 1 0 0 0 0 0 1 0 0 1 0 1 0 0 0 shape 4 4 dtype float32 computes binary cross entropy loss between target and output tensor the binary cross entropy loss is commonly used in binary classification tasks where each input sample belongs to one of the two classes it measures the dissimilarity between the target and output probabilities or logits args target the target tensor representing the true binary labels its shape should match the shape of the output tensor output the output tensor representing the predicted probabilities or logits its shape should match the shape of the target tensor from_logits optional whether output is a tensor of logits or probabilities set it to true if output represents logits otherwise set it to false if output represents probabilities defaults to false returns integer tensor the computed binary cross entropy loss between target and output example target keras ops convert_to_tensor 0 1 1 0 output keras ops convert_to_tensor 0 1 0 9 0 8 0 2 binary_crossentropy target output array 0 10536054 0 10536054 0 22314355 0 22314355 shape 4 dtype float32 computes categorical cross entropy loss between target and output tensor the categorical cross entropy loss is commonly used in multi class classification tasks where each input sample can belong to one of multiple classes it measures the dissimilarity between the target and output probabilities or logits args target the target tensor representing the true categorical labels its shape should match the shape of the output tensor except for the last dimension output the output tensor representing the predicted probabilities or logits its shape should match the shape of the target tensor except for the last dimension from_logits optional whether output is a tensor of logits or probabilities set it to true if output represents logits otherwise set it to false if output represents probabilities defaults to false axis optional the axis along which the categorical cross entropy is computed defaults to 1 which corresponds to the last dimension of the tensors returns integer tensor the computed categorical cross entropy loss between target and output example target keras ops convert_to_tensor 1 0 0 0 1 0 0 0 1 output keras ops convert_to_tensor 0 9 0 05 0 05 0 1 0 8 0 1 0 2 0 3 0 5 categorical_crossentropy target output array 0 10536054 0 22314355 0 6931472 shape 3 dtype float32 computes sparse categorical cross entropy loss the sparse categorical cross entropy loss is similar to categorical cross entropy but it is used when the target tensor contains integer class labels instead of one hot encoded vectors it measures the dissimilarity between the target and output probabilities or logits args target the target tensor representing the true class labels as integers its shape should match the shape of the output tensor except for the last dimension output the output tensor representing the predicted probabilities or logits its shape should match the shape of the target tensor except for the last dimension from_logits optional whether output is a tensor of logits or probabilities set it to true if output represents logits otherwise set it to false if output represents probabilities defaults to false axis optional the axis along which the sparse categorical cross entropy is computed defaults to 1 which corresponds to the last dimension of the tensors returns integer tensor the computed sparse categorical cross entropy loss between target and output example target keras ops convert_to_tensor 0 1 2 dtype int32 output keras ops convert_to_tensor 0 9 0 05 0 05 0 1 0 8 0 1 0 2 0 3 0 5 sparse_categorical_crossentropy target output array 0 10536056 0 22314355 0 6931472 shape 3 dtype float32 encodes integer labels as multi hot vectors this function encodes integer labels as multi hot vectors where each label is mapped to a binary value in the resulting vector args inputs tensor of integer labels to be converted to multi hot vectors num_tokens integer the total number of unique tokens or classes axis optional axis along which the multi hot encoding should be added defaults to 1 which corresponds to the last dimension dtype optional the data type of the resulting tensor default is backend s float type returns tensor the multi hot encoded tensor example data keras ops convert_to_tensor 0 4 keras ops multi_hot data num_tokens 5 array 1 0 0 0 0 0 0 0 1 0 dtype float32 calculates the mean and variance of x the mean and variance are calculated by aggregating the contents of x across axes if x is 1 d and axes 0 this is just the mean and variance of a vector args x input tensor axes a list of axes which to compute mean and variance keepdims if this is set to true the axes which are reduced are left in the result as dimensions with size one synchronized only applicable with the tensorflow backend if true synchronizes the global batch statistics mean and variance across all devices at each training step in a distributed training strategy if false each replica uses its own local batch statistics returns a tuple containing two tensors mean and variance example x keras ops convert_to_tensor 0 1 2 3 100 dtype float32 keras ops moments x axes 0 array 21 2 dtype float32 array 1553 3601 dtype float32 normalizes x by mean and variance this op is typically used by the batch normalization step in a neural network it normalizes the input tensor along the given axis args x input tensor mean a mean vector of the same length as the axis dimension of the input thensor variance a variance vector of the same length as the axis dimension of the input tensor axis integer the axis that should be normalized offset an offset vector of the same length as the axis dimension of the input tensor if not none offset is added to the normalized tensor defaults to none scale a scale vector of the same length as the axis dimension of the input tensor if not none the normalized tensor is multiplied by scale defaults to none epsilon small float added to variance to avoid dividing by zero defaults to 1e 3 returns the normalized tensor example x keras ops convert_to_tensor 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 keras ops batch_normalization x mean 0 4 0 5 0 6 variance 0 67 0 67 0 67 axis 1 array 3 6624e 01 3 6624e 01 3 6624e 01 4 6445e 09 0 0000e 00 1 8578e 08 3 6624e 01 3 6624e 01 3 6624e 01
from keras import backend
from keras.api_export import keras_export
from keras.backend import KerasTensor
from keras.backend import any_symbolic_tensors
from keras.backend import standardize_data_format
from keras.backend.common.backend_utils import (
    compute_conv_transpose_output_shape,
)
from keras.ops import operation_utils
from keras.ops.operation import Operation
from keras.ops.operation_utils import reduce_shape


class Relu(Operation):
    def call(self, x):
        return backend.nn.relu(x)

    def compute_output_spec(self, x):
        return KerasTensor(x.shape, dtype=x.dtype)


@keras_export(["keras.ops.relu", "keras.ops.nn.relu"])
def relu(x):
    
    if any_symbolic_tensors((x,)):
        return Relu().symbolic_call(x)
    return backend.nn.relu(x)


class Relu6(Operation):
    def call(self, x):
        return backend.nn.relu6(x)

    def compute_output_spec(self, x):
        return KerasTensor(x.shape, dtype=x.dtype)


@keras_export(["keras.ops.relu6", "keras.ops.nn.relu6"])
def relu6(x):
    
    if any_symbolic_tensors((x,)):
        return Relu6().symbolic_call(x)
    return backend.nn.relu6(x)


class Sigmoid(Operation):
    def call(self, x):
        return backend.nn.sigmoid(x)

    def compute_output_spec(self, x):
        return KerasTensor(x.shape, dtype=x.dtype)


@keras_export(["keras.ops.sigmoid", "keras.ops.nn.sigmoid"])
def sigmoid(x):
    
    if any_symbolic_tensors((x,)):
        return Sigmoid().symbolic_call(x)
    return backend.nn.sigmoid(x)


class Softplus(Operation):
    def call(self, x):
        return backend.nn.softplus(x)

    def compute_output_spec(self, x):
        return KerasTensor(x.shape, dtype=x.dtype)


@keras_export(["keras.ops.softplus", "keras.ops.nn.softplus"])
def softplus(x):
    
    if any_symbolic_tensors((x,)):
        return Softplus().symbolic_call(x)
    return backend.nn.softplus(x)


class Softsign(Operation):
    def call(self, x):
        return backend.nn.softsign(x)

    def compute_output_spec(self, x):
        return KerasTensor(x.shape, dtype=x.dtype)


@keras_export(["keras.ops.softsign", "keras.ops.nn.softsign"])
def softsign(x):
    
    if any_symbolic_tensors((x,)):
        return Softsign().symbolic_call(x)
    return backend.nn.softsign(x)


class Silu(Operation):
    def call(self, x):
        return backend.nn.silu(x)

    def compute_output_spec(self, x):
        return KerasTensor(x.shape, dtype=x.dtype)


@keras_export(
    [
        "keras.ops.silu",
        "keras.ops.nn.silu",
        "keras.ops.swish",
        "keras.ops.nn.swish",
    ]
)
def silu(x):
    
    if any_symbolic_tensors((x,)):
        return Silu().symbolic_call(x)
    return backend.nn.silu(x)


class LogSigmoid(Operation):
    def call(self, x):
        return backend.nn.log_sigmoid(x)

    def compute_output_spec(self, x):
        return KerasTensor(x.shape, dtype=x.dtype)


@keras_export(
    [
        "keras.ops.log_sigmoid",
        "keras.ops.nn.log_sigmoid",
    ]
)
def log_sigmoid(x):
    
    if any_symbolic_tensors((x,)):
        return LogSigmoid().symbolic_call(x)
    return backend.nn.log_sigmoid(x)


class LeakyRelu(Operation):
    def __init__(self, negative_slope=0.2):
        super().__init__()
        self.negative_slope = negative_slope

    def call(self, x):
        return backend.nn.leaky_relu(x, self.negative_slope)

    def compute_output_spec(self, x):
        return KerasTensor(x.shape, dtype=x.dtype)


@keras_export(["keras.ops.leaky_relu", "keras.ops.nn.leaky_relu"])
def leaky_relu(x, negative_slope=0.2):
    
    if any_symbolic_tensors((x,)):
        return LeakyRelu(negative_slope).symbolic_call(x)
    return backend.nn.leaky_relu(x, negative_slope=negative_slope)


class HardSigmoid(Operation):
    def call(self, x):
        return backend.nn.hard_sigmoid(x)

    def compute_output_spec(self, x):
        return KerasTensor(x.shape, dtype=x.dtype)


@keras_export(
    [
        "keras.ops.hard_sigmoid",
        "keras.ops.nn.hard_sigmoid",
    ]
)
def hard_sigmoid(x):
    
    if any_symbolic_tensors((x,)):
        return HardSigmoid().symbolic_call(x)
    return backend.nn.hard_sigmoid(x)


class HardSwish(Operation):
    def call(self, x):
        return backend.nn.hard_swish(x)

    def compute_output_spec(self, x):
        return KerasTensor(x.shape, dtype=x.dtype)


@keras_export(["keras.ops.hard_swish", "keras.ops.nn.hard_swish"])
def hard_swish(x):
    
    if any_symbolic_tensors((x,)):
        return HardSwish().symbolic_call(x)
    return backend.nn.hard_swish(x)


class Elu(Operation):
    def __init__(self, alpha=1.0):
        super().__init__()
        self.alpha = alpha

    def call(self, x):
        return backend.nn.elu(x, alpha=self.alpha)

    def compute_output_spec(self, x):
        return KerasTensor(x.shape, dtype=x.dtype)


@keras_export(["keras.ops.elu", "keras.ops.nn.elu"])
def elu(x, alpha=1.0):
    
    if any_symbolic_tensors((x,)):
        return Elu(alpha).symbolic_call(x)
    return backend.nn.elu(x, alpha=alpha)


class Selu(Operation):
    def call(self, x):
        return backend.nn.selu(x)

    def compute_output_spec(self, x):
        return KerasTensor(x.shape, dtype=x.dtype)


@keras_export(["keras.ops.selu", "keras.ops.nn.selu"])
def selu(x):
    
    if any_symbolic_tensors((x,)):
        return Selu().symbolic_call(x)
    return backend.nn.selu(x)


class Gelu(Operation):
    def __init__(self, approximate=True):
        super().__init__()
        self.approximate = approximate

    def call(self, x):
        return backend.nn.gelu(x, self.approximate)

    def compute_output_spec(self, x):
        return KerasTensor(x.shape, dtype=x.dtype)


@keras_export(["keras.ops.gelu", "keras.ops.nn.gelu"])
def gelu(x, approximate=True):
    
    if any_symbolic_tensors((x,)):
        return Gelu(approximate).symbolic_call(x)
    return backend.nn.gelu(x, approximate)


class Softmax(Operation):
    def __init__(self, axis=-1):
        super().__init__()
        self.axis = axis

    def call(self, x):
        return backend.nn.softmax(x, axis=self.axis)

    def compute_output_spec(self, x):
        return KerasTensor(x.shape, dtype=x.dtype)


@keras_export(["keras.ops.softmax", "keras.ops.nn.softmax"])
def softmax(x, axis=-1):
    
    if any_symbolic_tensors((x,)):
        return Softmax(axis).symbolic_call(x)
    if isinstance(axis, tuple):
        original_shape = x.shape
        new_shape = []
        skip_dims = set(axis)
        i = 0
        while i < len(original_shape):
            if i in skip_dims:
                size = 1
                while i in skip_dims:
                    size *= original_shape[i]
                    i += 1
                new_shape.append(size)
            else:
                new_shape.append(original_shape[i])
                i += 1
        x = backend.numpy.reshape(x, new_shape)
        x = backend.nn.softmax(x, axis=-1)
        x = backend.numpy.reshape(x, original_shape)
        return x
    else:
        return backend.nn.softmax(x, axis=axis)


class LogSoftmax(Operation):
    def __init__(self, axis=-1):
        super().__init__()
        self.axis = axis

    def call(self, x):
        return backend.nn.log_softmax(x, axis=self.axis)

    def compute_output_spec(self, x):
        return KerasTensor(x.shape, dtype=x.dtype)


@keras_export(
    [
        "keras.ops.log_softmax",
        "keras.ops.nn.log_softmax",
    ]
)
def log_softmax(x, axis=-1):
    
    if any_symbolic_tensors((x,)):
        return LogSoftmax(axis).symbolic_call(x)
    if isinstance(axis, tuple):
        original_shape = x.shape
        new_shape = []
        skip_dims = set(axis)
        i = 0
        while i < len(original_shape):
            if i in skip_dims:
                size = 1
                while i in skip_dims:
                    size *= original_shape[i]
                    i += 1
                new_shape.append(size)
            else:
                new_shape.append(original_shape[i])
                i += 1
        x = backend.numpy.reshape(x, new_shape)
        x = backend.nn.log_softmax(x, axis=-1)
        x = backend.numpy.reshape(x, original_shape)
        return x
    else:
        return backend.nn.log_softmax(x, axis=axis)


class MaxPool(Operation):
    def __init__(
        self,
        pool_size,
        strides=None,
        padding="valid",
        data_format=None,
    ):
        super().__init__()
        self.pool_size = pool_size
        self.strides = strides
        self.padding = padding.lower()
        self.data_format = data_format

    def call(self, inputs):
        return backend.nn.max_pool(
            inputs,
            self.pool_size,
            self.strides,
            self.padding,
            self.data_format,
        )

    def compute_output_spec(self, inputs):
        output_shape = operation_utils.compute_pooling_output_shape(
            inputs.shape,
            self.pool_size,
            self.strides,
            self.padding,
            self.data_format,
        )
        return KerasTensor(output_shape, dtype=inputs.dtype)


@keras_export(["keras.ops.max_pool", "keras.ops.nn.max_pool"])
def max_pool(
    inputs,
    pool_size,
    strides=None,
    padding="valid",
    data_format=None,
):
    
    data_format = standardize_data_format(data_format)
    padding = padding.lower()
    if any_symbolic_tensors((inputs,)):
        return MaxPool(
            pool_size,
            strides,
            padding,
            data_format,
        ).symbolic_call(inputs)
    return backend.nn.max_pool(inputs, pool_size, strides, padding, data_format)


class AveragePool(Operation):
    def __init__(
        self,
        pool_size,
        strides=None,
        padding="valid",
        data_format=None,
    ):
        super().__init__()
        self.pool_size = pool_size
        self.strides = strides
        self.padding = padding.lower()
        self.data_format = data_format

    def call(self, inputs):
        return backend.nn.average_pool(
            inputs,
            self.pool_size,
            self.strides,
            self.padding,
            self.data_format,
        )

    def compute_output_spec(self, inputs):
        output_shape = operation_utils.compute_pooling_output_shape(
            inputs.shape,
            self.pool_size,
            self.strides,
            self.padding,
            self.data_format,
        )
        return KerasTensor(output_shape, dtype=inputs.dtype)


@keras_export(
    [
        "keras.ops.average_pool",
        "keras.ops.nn.average_pool",
    ]
)
def average_pool(
    inputs,
    pool_size,
    strides=None,
    padding="valid",
    data_format=None,
):
    
    data_format = standardize_data_format(data_format)
    padding = padding.lower()
    if any_symbolic_tensors((inputs,)):
        return AveragePool(
            pool_size,
            strides,
            padding,
            data_format,
        ).symbolic_call(inputs)
    return backend.nn.average_pool(
        inputs, pool_size, strides, padding, data_format
    )


class Conv(Operation):
    def __init__(
        self,
        strides=1,
        padding="valid",
        data_format=None,
        dilation_rate=1,
    ):
        super().__init__()
        self.strides = strides
        self.padding = padding.lower()
        self.data_format = data_format
        self.dilation_rate = dilation_rate

    def call(self, inputs, kernel):
        return backend.nn.conv(
            inputs,
            kernel,
            strides=self.strides,
            padding=self.padding,
            data_format=self.data_format,
            dilation_rate=self.dilation_rate,
        )

    def compute_output_spec(self, inputs, kernel):
        output_shape = operation_utils.compute_conv_output_shape(
            inputs.shape,
            kernel.shape[-1],
            kernel.shape[:-2],
            self.strides,
            self.padding,
            self.data_format,
            self.dilation_rate,
        )
        return KerasTensor(output_shape, dtype=inputs.dtype)


@keras_export(["keras.ops.conv", "keras.ops.nn.conv"])
def conv(
    inputs,
    kernel,
    strides=1,
    padding="valid",
    data_format=None,
    dilation_rate=1,
):
    
    data_format = standardize_data_format(data_format)
    padding = padding.lower()
    if any_symbolic_tensors((inputs,)):
        return Conv(strides, padding, data_format, dilation_rate).symbolic_call(
            inputs, kernel
        )
    return backend.nn.conv(
        inputs, kernel, strides, padding, data_format, dilation_rate
    )


class DepthwiseConv(Operation):
    def __init__(
        self,
        strides=1,
        padding="valid",
        data_format=None,
        dilation_rate=1,
    ):
        super().__init__()
        self.strides = strides
        self.padding = padding.lower()
        self.data_format = data_format
        self.dilation_rate = dilation_rate

    def call(self, inputs, kernel):
        return backend.nn.depthwise_conv(
            inputs,
            kernel,
            self.strides,
            self.padding,
            self.data_format,
            self.dilation_rate,
        )

    def compute_output_spec(self, inputs, kernel):
        output_shape = operation_utils.compute_conv_output_shape(
            inputs.shape,
            kernel.shape[-1] * kernel.shape[-2],
            kernel.shape[:-2],
            self.strides,
            self.padding,
            self.data_format,
            self.dilation_rate,
        )
        return KerasTensor(output_shape, dtype=inputs.dtype)


@keras_export(
    [
        "keras.ops.depthwise_conv",
        "keras.ops.nn.depthwise_conv",
    ]
)
def depthwise_conv(
    inputs,
    kernel,
    strides=1,
    padding="valid",
    data_format=None,
    dilation_rate=1,
):
    
    data_format = standardize_data_format(data_format)
    padding = padding.lower()
    if any_symbolic_tensors((inputs,)):
        return DepthwiseConv(
            strides, padding, data_format, dilation_rate
        ).symbolic_call(inputs, kernel)
    return backend.nn.depthwise_conv(
        inputs,
        kernel,
        strides,
        padding,
        data_format,
        dilation_rate,
    )


class SeparableConv(Operation):
    def __init__(
        self,
        strides=1,
        padding="valid",
        data_format=None,
        dilation_rate=1,
    ):
        super().__init__()
        self.strides = strides
        self.padding = padding.lower()
        self.data_format = data_format
        self.dilation_rate = dilation_rate

    def call(self, inputs, depthwise_kernel, pointwise_kernel):
        return backend.nn.separable_conv(
            inputs,
            depthwise_kernel,
            pointwise_kernel,
            self.strides,
            self.padding,
            self.data_format,
            self.dilation_rate,
        )

    def compute_output_spec(self, inputs, depthwise_kernel, pointwise_kernel):
        output_shape = list(
            depthwise_conv(
                inputs,
                depthwise_kernel,
                self.strides,
                self.padding,
                self.data_format,
                self.dilation_rate,
            ).shape
        )
        if self.data_format == "channels_last":
            output_shape[-1] = pointwise_kernel.shape[-1]
        else:
            output_shape[1] = pointwise_kernel.shape[-1]
        return KerasTensor(output_shape, dtype=inputs.dtype)


@keras_export(
    [
        "keras.ops.separable_conv",
        "keras.ops.nn.separable_conv",
    ]
)
def separable_conv(
    inputs,
    depthwise_kernel,
    pointwise_kernel,
    strides=1,
    padding="valid",
    data_format=None,
    dilation_rate=1,
):
    
    data_format = standardize_data_format(data_format)
    padding = padding.lower()
    if any_symbolic_tensors((inputs,)):
        return SeparableConv(
            strides,
            padding,
            data_format,
            dilation_rate,
        ).symbolic_call(inputs, depthwise_kernel, pointwise_kernel)
    return backend.nn.separable_conv(
        inputs,
        depthwise_kernel,
        pointwise_kernel,
        strides,
        padding,
        data_format,
        dilation_rate,
    )


class ConvTranspose(Operation):
    def __init__(
        self,
        strides,
        padding="valid",
        output_padding=None,
        data_format=None,
        dilation_rate=1,
    ):
        super().__init__()
        self.strides = strides
        self.output_padding = output_padding
        self.padding = padding.lower()
        self.data_format = data_format
        self.dilation_rate = dilation_rate

    def call(
        self,
        inputs,
        kernel,
    ):
        return backend.nn.conv_transpose(
            inputs,
            kernel,
            self.strides,
            self.output_padding,
            self.padding,
            self.data_format,
            self.dilation_rate,
        )

    def compute_output_spec(self, inputs, kernel):
        kernel_size = kernel.shape[:-2]
        filters = kernel.shape[-2]
        output_shape = compute_conv_transpose_output_shape(
            inputs.shape,
            kernel_size,
            filters,
            self.strides,
            self.padding,
            self.output_padding,
            self.data_format,
            self.dilation_rate,
        )
        return KerasTensor(output_shape, dtype=inputs.dtype)


@keras_export(
    [
        "keras.ops.conv_transpose",
        "keras.ops.nn.conv_transpose",
    ]
)
def conv_transpose(
    inputs,
    kernel,
    strides,
    padding="valid",
    output_padding=None,
    data_format=None,
    dilation_rate=1,
):
    
    data_format = standardize_data_format(data_format)
    padding = padding.lower()
    if any_symbolic_tensors((inputs,)):
        return ConvTranspose(
            strides, padding, output_padding, data_format, dilation_rate
        ).symbolic_call(inputs, kernel)
    return backend.nn.conv_transpose(
        inputs,
        kernel,
        strides,
        padding,
        output_padding,
        data_format,
        dilation_rate,
    )


class OneHot(Operation):
    def __init__(self, num_classes, axis=-1, dtype=None):
        super().__init__()
        self.num_classes = num_classes
        self.axis = axis
        self.dtype = dtype or backend.floatx()

    def call(self, x):
        return backend.nn.one_hot(
            x, self.num_classes, axis=self.axis, dtype=self.dtype
        )

    def compute_output_spec(self, x):
        x_shape = list(getattr(x, "shape", []))
        if self.axis == -1:
            x_shape.append(self.num_classes)
        elif self.axis >= 0 and self.axis < len(x_shape):
            x_shape.insert(self.axis, self.num_classes)
        else:
            raise ValueError(
                f"axis must be -1 or between [0, {len(x.shape)}), but "
                f"received {self.axis}."
            )
        return KerasTensor(x_shape, dtype=self.dtype)


@keras_export(["keras.ops.one_hot", "keras.ops.nn.one_hot"])
def one_hot(x, num_classes, axis=-1, dtype=None):
    
    if any_symbolic_tensors((x,)):
        return OneHot(num_classes, axis=axis, dtype=dtype).symbolic_call(x)
    return backend.nn.one_hot(
        x, num_classes, axis=axis, dtype=dtype or backend.floatx()
    )


class BinaryCrossentropy(Operation):
    def __init__(self, from_logits=False):
        super().__init__()
        self.from_logits = from_logits

    def call(self, target, output):
        return backend.nn.binary_crossentropy(
            target, output, from_logits=self.from_logits
        )

    def compute_output_spec(self, target, output):
        if target.shape != output.shape:
            raise ValueError(
                "Arguments `target` and `output` must have the same shape. "
                "Received: "
                f"target.shape={target.shape}, output.shape={output.shape}"
            )
        return KerasTensor(output.shape, dtype=output.dtype)


@keras_export(
    [
        "keras.ops.binary_crossentropy",
        "keras.ops.nn.binary_crossentropy",
    ]
)
def binary_crossentropy(target, output, from_logits=False):
    
    if any_symbolic_tensors((target, output)):
        return BinaryCrossentropy(from_logits=from_logits).symbolic_call(
            target, output
        )
    return backend.nn.binary_crossentropy(
        target, output, from_logits=from_logits
    )


class CategoricalCrossentropy(Operation):
    def __init__(self, from_logits=False, axis=-1):
        super().__init__()
        self.from_logits = from_logits
        self.axis = axis

    def call(self, target, output):
        return backend.nn.categorical_crossentropy(
            target, output, from_logits=self.from_logits, axis=self.axis
        )

    def compute_output_spec(self, target, output):
        if target.shape != output.shape:
            raise ValueError(
                "Arguments `target` and `output` must have the same shape. "
                "Received: "
                f"target.shape={target.shape}, output.shape={output.shape}"
            )
        if len(target.shape) < 1:
            raise ValueError(
                "Arguments `target` and `output` must be at least rank 1. "
                "Received: "
                f"target.shape={target.shape}, output.shape={output.shape}"
            )
        return KerasTensor(output.shape[:-1], dtype=output.dtype)


@keras_export(
    [
        "keras.ops.categorical_crossentropy",
        "keras.ops.nn.categorical_crossentropy",
    ]
)
def categorical_crossentropy(target, output, from_logits=False, axis=-1):
    
    if any_symbolic_tensors((target, output)):
        return CategoricalCrossentropy(
            from_logits=from_logits, axis=axis
        ).symbolic_call(target, output)
    return backend.nn.categorical_crossentropy(
        target, output, from_logits=from_logits, axis=axis
    )


class SparseCategoricalCrossentropy(Operation):
    def __init__(self, from_logits=False, axis=-1):
        super().__init__()
        self.from_logits = from_logits
        self.axis = axis

    def call(self, target, output):
        return backend.nn.sparse_categorical_crossentropy(
            target, output, from_logits=self.from_logits, axis=self.axis
        )

    def compute_output_spec(self, target, output):
        if len(output.shape) < 1:
            raise ValueError(
                "Argument `output` must be at least rank 1. "
                "Received: "
                f"output.shape={output.shape}"
            )
        target_shape = target.shape
        if len(target_shape) == len(output.shape) and target_shape[-1] == 1:
            target_shape = target_shape[:-1]
        if target_shape != output.shape[:-1]:
            raise ValueError(
                "Arguments `target` and `output` must have the same shape "
                "up until the last dimension: "
                f"target.shape={target.shape}, output.shape={output.shape}"
            )
        return KerasTensor(output.shape[:-1], dtype=output.dtype)


@keras_export(
    [
        "keras.ops.sparse_categorical_crossentropy",
        "keras.ops.nn.sparse_categorical_crossentropy",
    ]
)
def sparse_categorical_crossentropy(target, output, from_logits=False, axis=-1):
    
    if any_symbolic_tensors((target, output)):
        return SparseCategoricalCrossentropy(
            from_logits=from_logits, axis=axis
        ).symbolic_call(target, output)
    return backend.nn.sparse_categorical_crossentropy(
        target, output, from_logits=from_logits, axis=axis
    )


class MultiHot(Operation):
    def __init__(self, num_tokens=None, axis=-1, dtype=None, name=None):
        super().__init__(name)
        self.num_tokens = num_tokens
        self.axis = axis
        self.dtype = dtype or backend.floatx()

    def call(self, inputs):
        return backend.nn.multi_hot(
            inputs,
            num_classes=self.num_tokens,
            axis=self.axis,
            dtype=self.dtype,
        )

    def compute_output_spec(self, inputs):
        x_shape = list(getattr(inputs, "shape", []))
        if self.axis == -1:
            x_shape.append(self.num_tokens)
        elif self.axis >= 0 and self.axis < len(x_shape):
            x_shape.insert(self.axis, self.num_tokens)
        else:
            raise ValueError(
                f"axis must be -1 or between [0, {len(inputs.shape)}), but "
                f"received {self.axis}."
            )

        if len(x_shape) == 2:
            x_shape = [x_shape[-1]]
        else:
            x_shape = [x_shape[0]] + x_shape[2:]

        return KerasTensor(x_shape, dtype=inputs.dtype)


@keras_export(
    [
        "keras.ops.multi_hot",
        "keras.ops.nn.multi_hot",
    ]
)
def multi_hot(inputs, num_tokens, axis=-1, dtype=None):
    
    if any_symbolic_tensors((inputs,)):
        return MultiHot(num_tokens, axis, dtype).symbolic_call(inputs)

    return backend.nn.multi_hot(inputs, num_tokens, axis, dtype)


class Moments(Operation):
    def __init__(self, axes, keepdims=False, synchronized=False, name=None):
        super().__init__(name)
        self.axes = axes
        self.keepdims = keepdims
        self.synchronized = synchronized

    def call(self, x):
        return backend.nn.moments(
            x,
            axes=self.axes,
            keepdims=self.keepdims,
            synchronized=self.synchronized,
        )

    def compute_output_spec(self, x):
        return (
            KerasTensor(
                reduce_shape(x.shape, axis=self.axes, keepdims=self.keepdims),
                dtype=x.dtype,
            ),
            KerasTensor(
                reduce_shape(x.shape, axis=self.axes, keepdims=self.keepdims),
                dtype=x.dtype,
            ),
        )


@keras_export(
    [
        "keras.ops.moments",
        "keras.ops.nn.moments",
    ]
)
def moments(x, axes, keepdims=False, synchronized=False):
    
    if any_symbolic_tensors((x,)):
        return Moments(axes, keepdims, synchronized=synchronized).symbolic_call(
            x
        )

    return backend.nn.moments(x, axes, keepdims, synchronized=synchronized)


class BatchNorm(Operation):
    def __init__(self, axis, epsilon, name=None):
        super().__init__(name)
        self.axis = axis
        self.epsilon = epsilon

    def _check_shape(self, name, shape, expected_shape):
        if shape != expected_shape:
            raise ValueError(
                f"Arguments `{name}` must be a vector of length "
                f"`x.shape[axis]`. Expected: `{expected_shape}`. "
                f"Received: `{shape}."
            )

    def compute_output_spec(self, x, mean, variance, offset, scale):
        shape = (x.shape[self.axis],)
        self._check_shape("mean", tuple(mean.shape), shape)
        self._check_shape("variance", tuple(variance.shape), shape)
        if offset is not None:
            self._check_shape("offset", tuple(offset.shape), shape)
        if offset is not scale:
            self._check_shape("scale", tuple(scale.shape), shape)
        return KerasTensor(x.shape, dtype=x.dtype)


@keras_export(
    [
        "keras.ops.batch_normalization",
        "keras.ops.nn.batch_normalization",
    ]
)
def batch_normalization(
    x, mean, variance, axis, offset=None, scale=None, epsilon=1e-3
):
    
    if any_symbolic_tensors((x, mean, variance, offset, scale)):
        return BatchNorm(axis, epsilon).symbolic_call(
            x, mean, variance, offset, scale
        )

    return backend.nn.batch_normalization(
        x, mean, variance, axis, offset, scale, epsilon
    )