diff --git a/llvm/projects/keras/src/mobilenet_imagenet.py b/llvm/projects/keras/src/mobilenet_imagenet.py
new file mode 100644
index 0000000000000000000000000000000000000000..1988d50f1e734fe6c922571708ea171295b31e11
--- /dev/null
+++ b/llvm/projects/keras/src/mobilenet_imagenet.py
@@ -0,0 +1,216 @@
+import os
+import glob
+
+import scipy
+import scipy.io
+import cv2
+import numpy as np
+
+import keras
+from keras.models import Sequential, Model
+from keras.layers import *
+from keras.applications.mobilenet import MobileNet, preprocess_input
+from keras.utils import to_categorical
+from keras import backend as K
+
+from frontend.approxhpvm_translator import translate_to_approxhpvm
+from frontend.weight_utils import dumpCalibrationData
+
+
+np.random.seed(2020)
+
+os.environ["CUDA_VISIBLE_DEVICES"] = "1"
+
+K.set_image_data_format('channels_first')
+
+data_format = 'channels_first'
+
+
+IMAGENET_DIR = '/home/nz11/ILSVRC2012/'
+OUTPUT_DIR = 'data/mobilenet_imagenet/'
+
+NUM_CLASSES = 100
+IMAGES_PER_CLASS = 200
+VAL_SIZE = 100
+
+
+
+# def relu6(x):
+#     return K.relu(x, max_value=6)
+
+
+def _conv_block(inputs, filters, alpha, kernel=(3, 3), strides=(1, 1)):
+    channel_axis = 1
+    filters = int(filters * alpha)
+        
+    x = ZeroPadding2D(padding=((0, 1), (0, 1)))(inputs)
+    x = Conv2D(filters, kernel,
+                      padding='valid',
+                      use_bias=False,
+                      strides=strides)(x)
+    x = BatchNormalization(axis=channel_axis)(x)
+    return Activation('relu')(x)
+    
+    
+def _depthwise_conv_block(inputs, pointwise_conv_filters, alpha,
+                          depth_multiplier=1, strides=(1, 1), block_id=1):
+    channel_axis = 1
+    pointwise_conv_filters = int(pointwise_conv_filters * alpha)
+
+    if strides != (1, 1):
+        x = ZeroPadding2D(padding=(1, 1))(inputs)
+    else:
+        x = inputs
+    
+    x = DepthwiseConv2D((3, 3),
+                               padding='same' if strides == (1, 1) else 'valid',
+                               depth_multiplier=depth_multiplier,
+                               strides=strides,
+                               use_bias=False)(x)
+    x = BatchNormalization(axis=channel_axis)(x)
+    x = Activation('relu')(x)
+
+    x = Conv2D(pointwise_conv_filters, (1, 1),
+                      padding='same',
+                      use_bias=False,
+                      strides=(1, 1))(x)
+    x = BatchNormalization(axis=channel_axis)(x)
+    return Activation('relu')(x)
+    
+    
+    
+def get_mobilenet_nchw_keras():
+
+    alpha=1.0
+    dropout=1e-3
+    depth_multiplier=1
+    
+    img_input = Input(shape=(3, 224, 224))
+
+
+    x = _conv_block(img_input, 32, alpha, strides=(2, 2))
+    x = _depthwise_conv_block(x, 64, alpha, depth_multiplier, block_id=1)
+
+    x = _depthwise_conv_block(x, 128, alpha, depth_multiplier,
+                              strides=(2, 2), block_id=2)
+    x = _depthwise_conv_block(x, 128, alpha, depth_multiplier, block_id=3)
+
+    x = _depthwise_conv_block(x, 256, alpha, depth_multiplier,
+                              strides=(2, 2), block_id=4)
+    x = _depthwise_conv_block(x, 256, alpha, depth_multiplier, block_id=5)
+
+    x = _depthwise_conv_block(x, 512, alpha, depth_multiplier,
+                              strides=(2, 2), block_id=6)
+    x = _depthwise_conv_block(x, 512, alpha, depth_multiplier, block_id=7)
+    x = _depthwise_conv_block(x, 512, alpha, depth_multiplier, block_id=8)
+    x = _depthwise_conv_block(x, 512, alpha, depth_multiplier, block_id=9)
+    x = _depthwise_conv_block(x, 512, alpha, depth_multiplier, block_id=10)
+    x = _depthwise_conv_block(x, 512, alpha, depth_multiplier, block_id=11)
+
+    x = _depthwise_conv_block(x, 1024, alpha, depth_multiplier,
+                              strides=(2, 2), block_id=12)
+    x = _depthwise_conv_block(x, 1024, alpha, depth_multiplier, block_id=13)
+
+
+    x = GlobalAveragePooling2D()(x)
+    x = Dropout(dropout)(x)
+    x = Dense(1000)(x)
+    x = Activation('softmax')(x)
+
+    model = Model(img_input, x)
+    
+    
+    K.set_image_data_format('channels_last')
+    original_model = MobileNet()
+    K.set_image_data_format('channels_first')
+    
+    j = 0
+    for i in range(0, len(original_model.layers)):
+        try:
+            model.layers[j].set_weights(original_model.layers[i].get_weights())
+            print (j, 'loaded')
+            j += 1
+        except:
+            print (j, 'skipped', model.layers[j])
+
+    return model
+
+
+
+def load_image(x):
+    image = cv2.imread(x)
+        
+    height, width, _ = image.shape
+    new_height = height * 256 // min(image.shape[:2])
+    new_width = width * 256 // min(image.shape[:2])
+    image = cv2.resize(image, (new_width, new_height), interpolation=cv2.INTER_CUBIC)
+    
+    height, width, _ = image.shape
+    startx = width // 2 - (224 // 2)
+    starty = height // 2 - (224 // 2)
+    image = image[starty:starty + 224, startx:startx + 224]
+    
+    image = image[:, :, ::-1]
+    image = np.transpose(image, (2, 0, 1))
+    image = preprocess_input(image.astype(np.float32))
+        
+    return image.astype(np.float32)
+
+
+meta = scipy.io.loadmat(IMAGENET_DIR + 'ILSVRC2012_devkit_t12/data/meta.mat')
+original_idx_to_synset = {}
+synset_to_name = {}
+
+for i in range(1000):
+    ilsvrc2012_id = int(meta['synsets'][i,0][0][0][0])
+    synset = meta['synsets'][i,0][1][0]
+    name = meta['synsets'][i,0][2][0]
+    original_idx_to_synset[ilsvrc2012_id] = synset
+    synset_to_name[synset] = name
+
+synset_to_keras_idx = {}
+keras_idx_to_name = {}
+f = open(IMAGENET_DIR + 'ILSVRC2012_devkit_t12/data/synset_words.txt', 'r')
+c = 0
+for line in f:
+    parts = line.split(' ')
+    synset_to_keras_idx[parts[0]] = c
+    keras_idx_to_name[c] = ' '.join(parts[1:])
+    c += 1
+f.close()
+
+
+
+model = get_mobilenet_nchw_keras()
+    
+X_test = []
+y_true = []
+    
+classes = glob.glob(IMAGENET_DIR + 'val/*')
+
+for c in np.random.permutation(len(classes))[:NUM_CLASSES]:
+    x = glob.glob(classes[c] + '/*')
+    x = np.array(x)
+            
+    idx = np.random.permutation(len(x))
+    idx = idx[:max(len(idx), IMAGES_PER_CLASS)]
+    
+    X_test += list(map(lambda x : load_image(x), x[idx]))
+    
+    synset = classes[c].split('/')[-1]
+    y_true += [synset_to_keras_idx[synset]] * len(x[idx])
+    
+X_test = np.array(X_test)
+y_true = np.array(y_true)
+
+
+
+translate_to_approxhpvm(model, OUTPUT_DIR, X_test[:VAL_SIZE], y_true[:VAL_SIZE], 1000)
+
+dumpCalibrationData(OUTPUT_DIR + 'test_input.bin', X_test, OUTPUT_DIR + 'test_labels.bin', y_true)
+
+
+pred = np.argmax(model.predict(X_test), axis=1)
+print ('val accuracy', np.sum(pred == y_true.ravel()) / len(X_test))    
+
+    
\ No newline at end of file
diff --git a/llvm/projects/keras/src/resnet50_imagenet.py b/llvm/projects/keras/src/resnet50_imagenet.py
index 902b60e8af767953dcc4ac16f2a6d55d986e9e54..ed15e0eabdd5da89ff0e8a40c76b2464aebdae52 100644
--- a/llvm/projects/keras/src/resnet50_imagenet.py
+++ b/llvm/projects/keras/src/resnet50_imagenet.py
@@ -1,15 +1,17 @@
 import os
 import glob
+import random
 
 import scipy
 import scipy.io
 import cv2
 import numpy as np
 
+import tensorflow as tf
 import keras
 from keras.models import Sequential, Model
 from keras.layers import *
-from keras.applications.vgg16 import VGG16, preprocess_input
+from keras.applications.resnet50 import ResNet50, preprocess_input
 from keras.utils import to_categorical
 from keras import backend as K
 
@@ -26,7 +28,7 @@ K.set_image_data_format('channels_first')
 data_format = 'channels_first'
 
 
-IMAGENET_DIR = '/shared/hsharif3/ILSVRC2012/'
+IMAGENET_DIR = '/home/nz11/ILSVRC2012/'
 OUTPUT_DIR = 'data/resnet50_imagenet/'
 
 NUM_CLASSES = 100
@@ -108,9 +110,10 @@ def get_resnet50_nchw_keras():
 
     x = ZeroPadding2D((3, 3))(img_input)
     x = Conv2D(64, (7, 7), strides=(2, 2))(x)
-    x = BatchNormalization(axis=bn_axis)(x)
+#     x = BatchNormalization(axis=bn_axis)(x)
     x = Activation('relu')(x)
     x = MaxPooling2D((3, 3), strides=(2, 2))(x)
+    x = BatchNormalization(axis=bn_axis)(x)
 
     x = conv_block(x, 3, [64, 64, 256], stage=2, block='a', strides=(1, 1))
     x = identity_block(x, 3, [64, 64, 256], stage=2, block='b')
@@ -138,11 +141,24 @@ def get_resnet50_nchw_keras():
     x = Activation('softmax')(x)
         
     model = Model(img_input, x)
-
+    
+    
+    original_model = ResNet50()
+    
+    for i in range(len(original_model.layers)):
+        try:
+            model.layers[i].set_weights(original_model.layers[i].get_weights())
+#             model.layers[i].trainable = False
+        except:
+            print (i, 'skipped')
+    model.layers[5].set_weights(original_model.layers[3].get_weights())
+    
+            
     return model
 
 
 def load_image(x):
+    
     image = cv2.imread(x)
         
     height, width, _ = image.shape
@@ -210,11 +226,62 @@ X_test = np.array(X_test)
 y_true = np.array(y_true)
 
 
+
+
+
+
+def train_helper(x):
+    
+    try:
+        x = x.decode('utf-8')
+    except:
+        pass
+    
+    image = load_image(x)
+    
+    y = np.zeros(1000, dtype=np.uint8)
+        
+    y[synset_to_keras_idx[x.split('/')[-2]]]= 1
+        
+    return image, y
+
+
+
+
+train_images = glob.glob(IMAGENET_DIR + 'train/*/*')
+random.shuffle(train_images)
+
+dataset = tf.data.Dataset().from_tensor_slices(train_images)
+dataset = dataset.map(
+    lambda x : tf.py_func(train_helper, [x], [tf.float32, tf.uint8]), 
+    num_parallel_calls=16
+)
+
+dataset = dataset.shuffle(buffer_size=1000)
+dataset = dataset.batch(32)
+dataset = dataset.repeat()
+
+next_element = dataset.make_one_shot_iterator().get_next()
+
+sess = tf.Session()
+
+def generate():
+    while True:
+        yield sess.run(next_element)
+    
+
+
+model.compile(optimizer=keras.optimizers.Adam(lr=0.00001), loss='categorical_crossentropy', metrics=['acc'])
+
+
+model.fit_generator(generate(), steps_per_epoch=1000, validation_data=(X_test, to_categorical(y_true, num_classes=1000)), epochs=6)
+
+
 translate_to_approxhpvm(model, OUTPUT_DIR, X_test[:VAL_SIZE], y_true[:VAL_SIZE], 1000)
 
 dumpCalibrationData(OUTPUT_DIR + 'test_input.bin', X_test, OUTPUT_DIR + 'test_labels.bin', y_true)
 
 
-# pred = np.argmax(model_nchw.predict(X_test), axis=1)
+# pred = np.argmax(model.predict(X_test), axis=1)
 # print ('val accuracy', np.sum(pred == y_true.ravel()) / len(X_test))
     
\ No newline at end of file