text: import tensorflow as tf
  from tensorflow.keras import backend as K
  from tensorflow.keras.models import Model
  from tensorflow.keras.layers import Dense, Activation, Dropout, MaxPooling2D
  from tensorflow.keras.layers import Conv2D, AveragePooling2D
  from tensorflow.keras.layers import BatchNormalization, Lambda
  from tensorflow.keras.layers import Input, Flatten
  from tensorflow.keras.constraints import max_norm
  
  
  def square(x):
      return K.square(x)
  
  
  def log(x):
      return K.log(K.clip(x, min_value=1e-7, max_value=10000))
  
  
  def ShallowConvNet(nb_classes, Chans=60, Samples=368, dropoutRate=0.5):
      """ Keras implementation of the Shallow Convolutional Network as described
      in Schirrmeister et. al. (2017), Human Brain Mapping.
      
      Assumes the input is a 2-second EEG signal sampled at 128Hz. Note that in 
      the original paper, they do temporal convolutions of length 25 for EEG
      data sampled at 250Hz. We instead use length 13 since the sampling rate is 
      roughly half of the 250Hz which the paper used. The pool_size and stride
      in later layers is also approximately half of what is used in the paper.
      
      Note that we use the max_norm constraint on all convolutional layers, as 
      well as the classification layer. We also change the defaults for the
      BatchNormalization layer. We used this based on a personal communication 
      with the original authors.
      
                       ours        original paper
      pool_size        1, 35       1, 75
      strides          1, 7        1, 15
      conv filters     1, 13       1, 25    
      
      Note that this implementation has not been verified by the original 
      authors. We do note that this implementation reproduces the results in the
      original paper with minor deviations. 
      """
  
      # start the model
      input_main = Input((Chans, Samples, 1))
      block1 = Conv2D(40, (1, 13),
                      input_shape=(Chans, Samples, 1),
                      kernel_constraint=max_norm(2., axis=(0, 1, 2)))(input_main)
      block1 = Conv2D(40, (Chans, 1),
                      use_bias=False,
                      kernel_constraint=max_norm(2., axis=(0, 1, 2)))(block1)
      block1 = BatchNormalization(epsilon=1e-05, momentum=0.1)(block1)
      block1 = Activation(square)(block1)
      block1 = AveragePooling2D(pool_size=(1, 35), strides=(1, 7))(block1)
      block1 = Activation(log)(block1)
      block1 = Dropout(dropoutRate)(block1)
      flatten = Flatten()(block1)
      dense = Dense(nb_classes, kernel_constraint=max_norm(0.5))(flatten)
      softmax = Activation('softmax')(dense)
  
      return Model(inputs=input_main, outputs=softmax)
  
  
  def DeepConvNet(nb_classes, Chans=60, Samples=368, dropoutRate=0.5):
      """ Keras implementation of the Deep Convolutional Network as described in
      Schirrmeister et. al. (2017), Human Brain Mapping.
      
      This implementation assumes the input is a 2-second EEG signal sampled at 
      128Hz, as opposed to signals sampled at 250Hz as described in the original
      paper. We also perform temporal convolutions of length (1, 5) as opposed
      to (1, 10) due to this sampling rate difference. 
      
      Note that we use the max_norm constraint on all convolutional layers, as 
      well as the classification layer. We also change the defaults for the
      BatchNormalization layer. We used this based on a personal communication 
      with the original authors.
      
                        ours        original paper
      pool_size        1, 2        1, 3
      strides          1, 2        1, 3
      conv filters     1, 5        1, 10
      
      Note that this implementation has not been verified by the original 
      authors. 
      
      """
  
      # start the model
      input_main = Input((Chans, Samples, 1))
      block1 = Conv2D(25, (1, 5),
                      input_shape=(Chans, Samples, 1),
                      kernel_constraint=max_norm(2., axis=(0, 1, 2)))(input_main)
      block1 = Conv2D(25, (Chans, 1),
                      kernel_constraint=max_norm(2., axis=(0, 1, 2)))(block1)
      block1 = BatchNormalization(epsilon=1e-05, momentum=0.1)(block1)
      block1 = Activation('elu')(block1)
      block1 = MaxPooling2D(pool_size=(1, 2), strides=(1, 2))(block1)
      block1 = Dropout(dropoutRate)(block1)
  
      block2 = Conv2D(50, (1, 5),
                      kernel_constraint=max_norm(2., axis=(0, 1, 2)))(block1)
      block2 = BatchNormalization(epsilon=1e-05, momentum=0.1)(block2)
      block2 = Activation('elu')(block2)
      block2 = MaxPooling2D(pool_size=(1, 2), strides=(1, 2))(block2)
      block2 = Dropout(dropoutRate)(block2)
  
      block3 = Conv2D(100, (1, 5),
                      kernel_constraint=max_norm(2., axis=(0, 1, 2)))(block2)
      block3 = BatchNormalization(epsilon=1e-05, momentum=0.1)(block3)
      block3 = Activation('elu')(block3)
      block3 = MaxPooling2D(pool_size=(1, 2), strides=(1, 2))(block3)
      block3 = Dropout(dropoutRate)(block3)
  
      block4 = Conv2D(200, (1, 5),
                      kernel_constraint=max_norm(2., axis=(0, 1, 2)))(block3)
      block4 = BatchNormalization(epsilon=1e-05, momentum=0.1)(block4)
      block4 = Activation('elu')(block4)
      block4 = MaxPooling2D(pool_size=(1, 2), strides=(1, 2))(block4)
      block4 = Dropout(dropoutRate)(block4)
  
      flatten = Flatten()(block4)
      dense = Dense(nb_classes, kernel_constraint=max_norm(0.5))(flatten)
      softmax = Activation('softmax')(dense)
  
      return Model(inputs=input_main, outputs=softmax)
  
  