{"cells":[{"metadata":{"trusted":false},"cell_type":"code","source":"#importing all the libraries needed\nimport numpy as np\nimport tensorflow as tf \nfrom tensorflow import keras\nfrom tensorflow.keras import regularizers\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.preprocessing import image\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import Dense,Dropout,GlobalAveragePooling2D\nfrom tensorflow.keras import backend as K\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nimport matplotlib.pyplot as plt\nprint(keras.__version__)","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# created a custom callback when accuracy reaches 98%\n\nclass myCallback(tf.keras.callbacks.Callback):\n    def on_epoch_end(self,epoch,logs={}):\n        if logs.get('accuracy') is not None and logs.get('accuracy') > 0.98:\n            print(' 98% accuracy reached')\n            self.model.stop_training=True      ","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"#performing image augmentation on the training data , set validation split to a low value to increase no. of training examples\n\nimagegen=ImageDataGenerator(rescale=1./255,rotation_range=10,zoom_range=0.2,height_shift_range=0.2,width_shift_range=0.2,\n                                 horizontal_flip=True,fill_mode='nearest',shear_range=0.2,validation_split=0.02,\n                            channel_shift_range=10.0,brightness_range=[0.1,0.3])\n\n# set training samples to flow from train directory\ntrain_datagen=imagegen.flow_from_directory(r'C:\\Users\\admin\\Documents\\car_classifier\\Train',\n                                                target_size=(224,224),batch_size=89,shuffle=True,class_mode='categorical',\n                                                subset='training')\nvalid_datagen=imagegen.flow_from_directory(r'C:\\Users\\admin\\Documents\\car_classifier\\Train',subset='validation',target_size=(224,224))","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# used MobileNet architecture as it was lightweight and requires less computing power, provides nearly the same\n# accuracy as VGG16 and is less complex in nature, not as accurate as InceptionV3 , but significant reduction in \n# size of the model\nmobile = keras.applications.mobilenet.MobileNet()\nmobile.summary()\nprint(len(mobile.layers))","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# set output of MobileNet model to layer 87\nlast_output=mobile.layers[-6].output\npredictions=Dense(45,activation='softmax',name='fc3')(last_output)","execution_count":null,"outputs":[]},{"metadata":{"scrolled":true,"trusted":false},"cell_type":"code","source":"model=Model(inputs=mobile.input,outputs=predictions)","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# freezing the layers that i dont want to train\nfor layer in model.layers[:-36]:\n    layer.trainable=False\n    \nmodel.summary()\nprint(len(model.layers))","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"#created an object of my_callback class\n# used Adam optimizer with learning rate set to 5*10^-5\n# loss is set to categorical cross entropy , used mini batch gradient descent , set metrics to 'accuracy'\ncallbacks=myCallback()\nmodel.compile(Adam(lr=0.00005),loss='categorical_crossentropy',metrics=['accuracy'])","execution_count":null,"outputs":[]},{"metadata":{"scrolled":false,"trusted":false},"cell_type":"code","source":"history=model.fit(train_datagen,steps_per_epoch=int(train_datagen.samples/train_datagen.batch_size),\n                  validation_data=(item for item in valid_datagen),validation_steps=1,\n                  epochs=25,verbose=1,callbacks=[callbacks])\n\nmodel.save('car_classifier_8.h5')\n#NOTE: the model is overfitting , i tried using Dropout and l2 kernel regularizer , however with the case of \n# dropout my accuracy decreased , possibly due to information loss as a result of randomly shutting off nodes, with \n#the l2 kernel regularizer my cost increased which increased my training time , it marginally improved my accuracy ,\n#wasnt significant.\n# Also tried reducing the size of the input image , (224,224)--> (160,160) to reduce overfitting, however again ended \n# up decreasing my accuracy","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"# plotting the accuracy on train set and validation set\nacc = history.history['accuracy']\nval_acc = history.history['val_accuracy']\n\nloss = history.history['loss']\nval_loss = history.history['val_loss']\n\nplt.figure(figsize=(8, 8))\nplt.subplot(2, 1, 1)\nplt.plot(acc, label='Training Accuracy')\nplt.plot(val_acc, label='Validation Accuracy')\nplt.legend(loc='lower right')\nplt.ylabel('Accuracy')\nplt.ylim([min(plt.ylim()),1])\nplt.title('Training and Validation Accuracy')\n\n# plotting the cost on train set and validation set\nplt.subplot(2, 1, 2)\nplt.plot(loss, label='Training Loss')\nplt.plot(val_loss, label='Validation Loss')\nplt.legend(loc='upper right')\nplt.ylabel('Cross Entropy')\nplt.ylim([0,2.0])\nplt.title('Training and Validation Loss')\nplt.xlabel('epoch')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"import os \nimport cv2\nimport pandas as pd\nfrom keras.preprocessing import image\nimport numpy as np\n\n# set test_directory path\ntest_directory=r'C:\\Users\\admin\\Documents\\car_classifier\\Test'\npath=os.path.join(test_directory)\n# used pythons OS library to iterate through the test data \n\n# since os.listdir(path) randomly iterates through the directory, I sort the all the files in the directory according to the\n# image number using \" regular expression\" \"re\" library in python\nimport re\ndef sorted_alphanumeric(data):\n    convert = lambda text: int(text) if text.isdigit() else text.lower()\n    alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] \n    return sorted(data, key=alphanum_key)\n\n# set dirlist = the sorted directory \ndirlist = sorted_alphanumeric(os.listdir(path))\ncar_class=[]\nimages=[]\nfor img in dirlist:\n    img_array=image.load_img(os.path.join(path,img),target_size=(160,160))\n    img_array=image.img_to_array(img_array)\n    img_array=img_array/255\n    img_array=np.expand_dims(img_array,axis=0)\n    car=model.predict(img_array).argmax()\n    \n    # appended the predicted class of car and image no. to an empty list called *car_class* and *images*\n    car_class.append(car) \n    images.append(img)\n\n# saved the predictions in an excel file along with the image no. using Pandas Dataframe\npredicted_data=pd.DataFrame(np.column_stack([images,car_class]),columns=['image','predictions'])\npredicted_data.to_csv('car_predictions14.csv')","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}