diff --git a/llvm/projects/keras/src/mobilenet_shallow.py b/llvm/projects/keras/src/mobilenet_shallow.py
new file mode 100644
index 0000000000000000000000000000000000000000..442004ef8e4148bf70e562a90784c2bcda5d753e
--- /dev/null
+++ b/llvm/projects/keras/src/mobilenet_shallow.py
@@ -0,0 +1,150 @@
+
+import sys
+import os
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
+
+from keras.models import Sequential
+from keras.layers import *
+from keras.datasets import cifar10
+from keras.utils import to_categorical
+from keras.callbacks import *
+from keras.preprocessing.image import ImageDataGenerator
+from keras.models import Model
+from keras import optimizers
+import keras.backend as K
+from frontend.approxhpvm_translator import translate_to_approxhpvm
+
+
+K.set_image_data_format('channels_first')
+
+(X_train, y_train), (X_test, y_test) = cifar10.load_data()
+test_labels = y_test
+
+print ("X_train.shape = ", X_train.shape)
+print ("X_test.shape = ", X_test.shape)
+
+
+X_train = X_train.astype('float32')
+X_test = X_test.astype('float32')
+
+
+mean = np.mean(X_train, axis=(0, 2, 3), keepdims=True)
+std = np.std(X_train, axis=(0, 2, 3), keepdims=True)
+
+X_train = (X_train - mean) / (std + 1e-9)
+X_test = (X_test - mean) / (std + 1e-9)
+
+y_train = to_categorical(y_train, num_classes=10)
+y_test = to_categorical(y_test, num_classes=10)
+
+
+def get_mobilenet(alpha=1, depth_multiplier=1):
+    model = Sequential()
+    
+    def _conv_block(filters, alpha, kernel=(3, 3), strides=(1, 1)):
+        channel_axis = 1
+        
+        model.add(Conv2D(filters, kernel,
+                          padding='same',
+                          use_bias=False,
+                          strides=strides, 
+                          input_shape=(3, 32, 32)))
+        model.add(BatchNormalization(axis=channel_axis))
+        model.add(Activation('relu'))
+    
+    def _depthwise_conv_block(pointwise_conv_filters, alpha, depth_multiplier=1, strides=(1, 1)):
+        channel_axis = 1 
+
+        model.add(ZeroPadding2D(padding = ((1,1), (1,1) )))
+
+        model.add(DepthwiseConv2D((3, 3),
+                                   padding='valid',
+                                   #depth_multiplier=depth_multiplier,
+                                   strides=strides,
+                                   use_bias=False))    
+        model.add(BatchNormalization(axis=channel_axis))
+        
+        model.add(Activation('relu'))
+        model.add(Conv2D(pointwise_conv_filters, (1, 1),
+                          padding='same',
+                          use_bias=False,
+                          strides=(1, 1)))
+        model.add(BatchNormalization(axis=channel_axis))
+        model.add(Activation('relu'))
+
+
+    _conv_block(32, alpha, strides=(1, 1))
+    
+    _depthwise_conv_block(64, alpha, depth_multiplier)
+
+    model.add(Dropout(rate=0.4))
+
+    _depthwise_conv_block(64, alpha, depth_multiplier,
+                              strides=(2, 2))
+    _depthwise_conv_block(128, alpha, depth_multiplier, strides=(2, 2))
+    model.add(Dropout(rate=0.4))
+
+    _depthwise_conv_block(256, alpha, depth_multiplier, 
+                      strides=(2, 2))
+    _depthwise_conv_block(256, alpha, depth_multiplier)
+    model.add(Dropout(rate=0.4))
+
+    model.add(AveragePooling2D(pool_size=2))
+    model.add(Flatten())
+    model.add(Dense(10))
+    #, activation='softmax'))
+    model.add(Activation('softmax'))
+
+
+    return model
+    
+    
+# data augmentation, horizontal flips only
+datagen = ImageDataGenerator(
+        featurewise_center=False,
+        featurewise_std_normalization=False,
+        rotation_range=0.0,
+        width_shift_range=0.2,
+        height_shift_range=0.2,
+        vertical_flip=False,
+        horizontal_flip=True)
+datagen.fit(X_train)
+
+
+model = get_mobilenet()
+
+learning_rates=[]
+for i in range(5):
+    learning_rates.append(5e-2)
+for i in range(50-5):
+    learning_rates.append(2e-2)
+for i in range(100-50):
+    learning_rates.append(8e-3)
+for i in range(150-100):
+    learning_rates.append(4e-3)
+for i in range(200-150):
+    learning_rates.append(2e-3)
+for i in range(250-200):
+    learning_rates.append(1e-3)
+
+callbacks = [
+    LearningRateScheduler(lambda epoch: float(learning_rates[epoch]))
+]
+
+model.compile(optimizer=optimizers.SGD(lr=learning_rates[0], momentum=0.9, decay=0.0, nesterov=False), 
+                       loss='categorical_crossentropy', 
+                       metrics=['accuracy'])
+
+model.fit_generator(
+    datagen.flow(X_train, y_train, batch_size=128),
+    steps_per_epoch=int(np.ceil(50000 / 128)),
+    validation_data=(X_test, y_test),
+    #epochs=300,
+    epochs=250,
+    callbacks=callbacks
+)
+
+model.summary()
+
+translate_to_approxhpvm(model, "data/mobilenet_shallow/", X_test, test_labels, 10)
+