text: import numpy as np
  from keras.layers.core import  Lambda
  from keras.layers.convolutional import Convolution2D
  from keras import backend as K
  from keras.layers import Concatenate
  
  from keras.engine import Layer
  
  def crosschannelnormalization(alpha = 1e-4, k=2, beta=0.75, n=5,**kwargs):
      """
      This is the function used for cross channel normalization in the original
      Alexnet
      """
      def f(X):
          K.set_image_dim_ordering('th')
          if K.backend()=='tensorflow':
              b, r, c, ch = X.get_shape()
          else:
              b, ch, r, c = X.shape
          half = n // 2
          square = K.square(X)
          extra_channels = K.spatial_2d_padding(K.permute_dimensions(square, (0,2,3,1))
                                                , ((half, half), (0, 0)))
          extra_channels = K.permute_dimensions(extra_channels, (0,3,1,2))
          #extra_channels = K.spatial_2d_padding(square, ((half, half), (0, 0)))
          scale = k
          for i in range(n):
              if K.backend()=='tensorflow':
                  ch = int(ch)
              scale += alpha * extra_channels[:,:,:,i:i+ch]
          scale = scale ** beta
          return X / scale
  
      return Lambda(f, output_shape=lambda input_shape:input_shape,**kwargs)
  
  
  
  def splittensor(axis=1, ratio_split=1, id_split=0,**kwargs):
      def f(X):
          if K.backend()=='tensorflow':
              div = int(X.get_shape()[axis]) // ratio_split
          else:
              div = X.shape[axis] // ratio_split
  
          if axis == 0:
              output =  X[id_split*div:(id_split+1)*div,:,:,:]
          elif axis == 1:
              output =  X[:, id_split*div:(id_split+1)*div, :, :]
          elif axis == 2:
              output = X[:,:,id_split*div:(id_split+1)*div,:]
          elif axis == 3:
              output = X[:,:,:,id_split*div:(id_split+1)*div]
          else:
              raise ValueError("This axis is not possible")
  
          return output
  
      def g(input_shape):
          output_shape=list(input_shape)
          output_shape[axis] = output_shape[axis] // ratio_split
          return tuple(output_shape)
  
      return Lambda(f,output_shape=lambda input_shape:g(input_shape),**kwargs)
  
  
  
  
  def convolution2Dgroup(n_group, nb_filter, nb_row, nb_col, **kwargs):
      def f(input):
          return Concatenate([
              Convolution2D(nb_filter//n_group,nb_row,nb_col)(
                  splittensor(axis=1,
                              ratio_split=n_group,
                              id_split=i)(input))
              for i in range(n_group)
          ], axis=1)
  
      return f
  
  
  class Softmax4D(Layer):
      def __init__(self, axis=-1,**kwargs):
          self.axis=axis
          super(Softmax4D, self).__init__(**kwargs)
  
      def build(self,input_shape):
          pass
  
      def call(self, x,mask=None):
          e = K.exp(x - K.max(x, axis=self.axis, keepdims=True))
          s = K.sum(e, axis=self.axis, keepdims=True)
          return e / s
  
      def get_output_shape_for(self, input_shape):
          return input_shape
  
      def compute_output_shape(self, input_shape):
          return input_shape
  