{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"### Dog breed classifier","metadata":{}},{"cell_type":"code","source":"import numpy as np \nimport pandas as pd\nfrom pathlib import Path\nimport os.path\nimport matplotlib.pyplot as plt\n%matplotlib inline\nimport seaborn as sns\nimport os\nimport cv2\nimport gc","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-06-21T06:25:59.790533Z","iopub.execute_input":"2021-06-21T06:25:59.791103Z","iopub.status.idle":"2021-06-21T06:26:00.871373Z","shell.execute_reply.started":"2021-06-21T06:25:59.791015Z","shell.execute_reply":"2021-06-21T06:26:00.870347Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a list with the filepaths for training and testing\ntrain_img_Path = '../input/dog-breed-identification/train'\n\ntest_img_Path = '../input/dog-breed-identification/test'\n\nlabels = pd.read_csv(r'../input/dog-breed-identification/labels.csv')\n\nsample_submission = pd.read_csv(r'../input/dog-breed-identification/sample_submission.csv')","metadata":{"execution":{"iopub.status.busy":"2021-06-21T06:26:02.810754Z","iopub.execute_input":"2021-06-21T06:26:02.811104Z","iopub.status.idle":"2021-06-21T06:26:03.421691Z","shell.execute_reply.started":"2021-06-21T06:26:02.811077Z","shell.execute_reply":"2021-06-21T06:26:03.420800Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels.head()","metadata":{"execution":{"iopub.status.busy":"2021-06-21T06:26:03.422978Z","iopub.execute_input":"2021-06-21T06:26:03.423286Z","iopub.status.idle":"2021-06-21T06:26:03.454620Z","shell.execute_reply.started":"2021-06-21T06:26:03.423257Z","shell.execute_reply":"2021-06-21T06:26:03.453648Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"* this dataset have 120 dogs breeds but in the given task predict only on 10 breeds.","metadata":{}},{"cell_type":"code","source":"print(f'Number of pictures in the training dataset: {labels.shape[0]}\\n')\nprint(f'Number of different labels: {len(labels.breed.unique())}\\n')\nprint(f'Labels: {labels.breed.unique()}')","metadata":{"execution":{"iopub.status.busy":"2021-06-21T06:26:05.130084Z","iopub.execute_input":"2021-06-21T06:26:05.130424Z","iopub.status.idle":"2021-06-21T06:26:05.143771Z","shell.execute_reply.started":"2021-06-21T06:26:05.130391Z","shell.execute_reply":"2021-06-21T06:26:05.142763Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels['breed'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2021-06-21T06:26:06.481011Z","iopub.execute_input":"2021-06-21T06:26:06.481347Z","iopub.status.idle":"2021-06-21T06:26:06.492576Z","shell.execute_reply.started":"2021-06-21T06:26:06.481319Z","shell.execute_reply":"2021-06-21T06:26:06.491537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels['id'] = labels['id'] + '.jpg'","metadata":{"execution":{"iopub.status.busy":"2021-06-21T06:26:07.590757Z","iopub.execute_input":"2021-06-21T06:26:07.591128Z","iopub.status.idle":"2021-06-21T06:26:07.613214Z","shell.execute_reply.started":"2021-06-21T06:26:07.591098Z","shell.execute_reply":"2021-06-21T06:26:07.612389Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(20,40))\ni=1\nfor idx,s in labels.head(6).iterrows():\n    img_path = os.path.join(train_img_Path,s['id'])\n    img=cv2.imread(img_path)\n    img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)\n    fig=plt.subplot(6,2,i)\n    fig.imshow(img)\n    fig.set_title(s['breed'])\n    i+=1","metadata":{"execution":{"iopub.status.busy":"2021-06-21T06:26:08.751888Z","iopub.execute_input":"2021-06-21T06:26:08.752266Z","iopub.status.idle":"2021-06-21T06:26:10.029084Z","shell.execute_reply.started":"2021-06-21T06:26:08.752235Z","shell.execute_reply":"2021-06-21T06:26:10.027453Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Extracting different classes\ndog_breeds = sorted(labels['breed'].unique())\nn_classes = len(dog_breeds)\nprint(n_classes)","metadata":{"scrolled":true,"execution":{"iopub.status.busy":"2021-06-21T06:26:10.030452Z","iopub.execute_input":"2021-06-21T06:26:10.030720Z","iopub.status.idle":"2021-06-21T06:26:10.036813Z","shell.execute_reply.started":"2021-06-21T06:26:10.030693Z","shell.execute_reply":"2021-06-21T06:26:10.035807Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Converting classes to numbers\nclass_to_num = dict(zip(dog_breeds,range(n_classes)))","metadata":{"execution":{"iopub.status.busy":"2021-06-21T06:26:13.541592Z","iopub.execute_input":"2021-06-21T06:26:13.542082Z","iopub.status.idle":"2021-06-21T06:26:13.546121Z","shell.execute_reply.started":"2021-06-21T06:26:13.542049Z","shell.execute_reply":"2021-06-21T06:26:13.545213Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Function to load and convert images to array\nfrom keras.preprocessing.image import load_img\nfrom keras.utils import to_categorical\n\ndef images_to_array(data_dir,df,image_size):\n    image_names = df['id']\n    image_labels = df['breed']\n    data_size = len(image_names)\n    \n    X = np.zeros([data_size,image_size[0],image_size[1],image_size[2]],dtype = np.uint8)\n    y = np.zeros([data_size,1],dtype = np.uint8)\n    \n    for i in range(data_size):\n        img_name = image_names[i]\n        img_dir = os.path.join(data_dir,img_name)\n        img_pixels = load_img(img_dir,target_size=image_size)\n        X[i] = img_pixels\n        y[i] = class_to_num[image_labels[i]]\n        \n    y = to_categorical(y)\n    ind = np.random.permutation(data_size)\n    X = X[ind]\n    y = y[ind]\n    print('Ouptut Data Size: ', X.shape)\n    print('Ouptut Label Size: ', y.shape)\n    return X, y  ","metadata":{"execution":{"iopub.status.busy":"2021-06-21T06:26:16.560113Z","iopub.execute_input":"2021-06-21T06:26:16.560593Z","iopub.status.idle":"2021-06-21T06:26:22.280004Z","shell.execute_reply.started":"2021-06-21T06:26:16.560549Z","shell.execute_reply":"2021-06-21T06:26:22.279115Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Selecting image size according to pretrained models\nimg_size = (299,299,3)\nX, y = images_to_array(train_img_Path,labels,img_size)","metadata":{"execution":{"iopub.status.busy":"2021-06-21T06:26:22.281316Z","iopub.execute_input":"2021-06-21T06:26:22.281922Z","iopub.status.idle":"2021-06-21T06:28:19.655024Z","shell.execute_reply.started":"2021-06-21T06:26:22.281861Z","shell.execute_reply":"2021-06-21T06:28:19.654078Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras.models import Model\nfrom keras.layers import BatchNormalization, Dense, GlobalAveragePooling2D,Lambda, Dropout, InputLayer, Input\n\ndef get_features(model_name, data_preprocessor,weight, input_size, data):\n    #Prepare pipeline.\n    input_layer = Input(input_size)\n    preprocessor = Lambda(data_preprocessor)(input_layer)\n    \n    base_model = model_name(weights=weight,\n                            include_top=False,\n                            input_shape=input_size)(preprocessor)\n    \n    avg = GlobalAveragePooling2D()(base_model)\n    feature_extractor = Model(inputs = input_layer, outputs = avg)\n    \n    #Extract feature.\n    feature_maps = feature_extractor.predict(data, batch_size=32, verbose=1)\n    print('Feature maps shape: ', feature_maps.shape)\n    return feature_maps\n","metadata":{"execution":{"iopub.status.busy":"2021-06-21T06:28:19.656954Z","iopub.execute_input":"2021-06-21T06:28:19.657314Z","iopub.status.idle":"2021-06-21T06:28:19.663155Z","shell.execute_reply.started":"2021-06-21T06:28:19.657276Z","shell.execute_reply":"2021-06-21T06:28:19.662382Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Extracting features using Xception\nfrom tensorflow import keras\nfrom keras.applications import Xception\nfrom keras.applications.xception import preprocess_input\nXception_preprocessor = preprocess_input\nXception_features = get_features(Xception,\n                                  Xception_preprocessor,\n                                 '../input/d/aeryss/keras-pretrained-models/Xception_NoTop_ImageNet.h5',\n                                  img_size, X)","metadata":{"execution":{"iopub.status.busy":"2021-06-21T06:28:19.664364Z","iopub.execute_input":"2021-06-21T06:28:19.664728Z","iopub.status.idle":"2021-06-21T07:04:10.431849Z","shell.execute_reply.started":"2021-06-21T06:28:19.664702Z","shell.execute_reply":"2021-06-21T07:04:10.430996Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Extracting features using NASNetMobile\nfrom keras.applications import NASNetMobile\nfrom keras.applications.nasnet import preprocess_input\nNASNetMobile_preprocessor = preprocess_input\nNASNetMobile_features = get_features(NASNetMobile,\n                                  NASNetMobile_preprocessor,\n                                 '../input/d/aeryss/keras-pretrained-models/NASNetMobile_NoTop_ImageNet.h5',\n                                  img_size, X)","metadata":{"execution":{"iopub.status.busy":"2021-06-21T07:04:10.433171Z","iopub.execute_input":"2021-06-21T07:04:10.433431Z","iopub.status.idle":"2021-06-21T07:19:35.909606Z","shell.execute_reply.started":"2021-06-21T07:04:10.433397Z","shell.execute_reply":"2021-06-21T07:19:35.908508Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Extracting features using InceptionResNetV2\nfrom keras.applications import InceptionResNetV2\nfrom keras.applications.inception_resnet_v2 import preprocess_input\nInceptionResNetV2_preprocessor = preprocess_input\nInceptionResNetV2_features = get_features(InceptionResNetV2,\n                                  InceptionResNetV2_preprocessor,\n                                 '../input/d/aeryss/keras-pretrained-models/InceptionResNetV2_NoTop_ImageNet.h5',\n                                  img_size, X)","metadata":{"execution":{"iopub.status.busy":"2021-06-21T07:19:35.911196Z","iopub.execute_input":"2021-06-21T07:19:35.911495Z","iopub.status.idle":"2021-06-21T07:57:47.494360Z","shell.execute_reply.started":"2021-06-21T07:19:35.911465Z","shell.execute_reply":"2021-06-21T07:57:47.493710Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del X #to free up some ram memory\ngc.collect()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-06-21T07:57:47.495491Z","iopub.execute_input":"2021-06-21T07:57:47.495912Z","iopub.status.idle":"2021-06-21T07:57:48.001895Z","shell.execute_reply.started":"2021-06-21T07:57:47.495855Z","shell.execute_reply":"2021-06-21T07:57:48.000983Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Creating final featuremap by combining all extracted features\n\nfinal_features = np.concatenate([Xception_features,\n                                 NASNetMobile_features,\n                                 InceptionResNetV2_features,], axis=-1) #axis=-1 to concatinate horizontally\n\nprint('Final feature maps shape', final_features.shape)","metadata":{"execution":{"iopub.status.busy":"2021-06-21T07:57:48.004594Z","iopub.execute_input":"2021-06-21T07:57:48.004864Z","iopub.status.idle":"2021-06-21T07:57:48.176042Z","shell.execute_reply.started":"2021-06-21T07:57:48.004837Z","shell.execute_reply":"2021-06-21T07:57:48.175117Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Callbacks\nfrom keras.callbacks import EarlyStopping\nEarlyStop_callback = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True)\nmy_callback=[EarlyStop_callback]","metadata":{"execution":{"iopub.status.busy":"2021-06-21T07:59:38.776754Z","iopub.execute_input":"2021-06-21T07:59:38.777116Z","iopub.status.idle":"2021-06-21T07:59:38.781868Z","shell.execute_reply.started":"2021-06-21T07:59:38.777085Z","shell.execute_reply":"2021-06-21T07:59:38.781000Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Adding the final layers to the above base models where the actual classification is done in the dense layers\n#Building Model\nfrom keras.models import Sequential\nmodel = Sequential()\nmodel.add(InputLayer(final_features.shape[1:]))\nmodel.add(Dropout(0.7))\nmodel.add(Dense(120,activation='softmax'))\n\nmodel.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])\nmodel.summary()\n\n# Training the CNN on the Train features and evaluating it on the val data\nhistory = model.fit(final_features,y,validation_split=0.1,callbacks=my_callback, epochs = 50, batch_size=32)","metadata":{"execution":{"iopub.status.busy":"2021-06-21T07:59:40.076002Z","iopub.execute_input":"2021-06-21T07:59:40.076468Z","iopub.status.idle":"2021-06-21T07:59:59.933280Z","shell.execute_reply.started":"2021-06-21T07:59:40.076439Z","shell.execute_reply":"2021-06-21T07:59:59.932399Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#deleting to free up ram memory\n\ndel NASNetMobile_features\ndel Xception_features\ndel InceptionResNetV2_features\ndel final_features\ngc.collect()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-06-21T08:00:04.686047Z","iopub.execute_input":"2021-06-21T08:00:04.686368Z","iopub.status.idle":"2021-06-21T08:00:04.881948Z","shell.execute_reply.started":"2021-06-21T08:00:04.686341Z","shell.execute_reply":"2021-06-21T08:00:04.880985Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Converting test images to array\ndef images_to_array2(data_dir,df, img_size):\n    images_names = df['id']\n    data_size = len(images_names)\n    X = np.zeros([data_size, img_size[0], img_size[1], 3], dtype=np.uint8)\n    \n    for i in range(data_size):\n        image_name = images_names[i]\n        img_dir = os.path.join(data_dir, image_name+'.jpg')\n        img_pixels = load_img(img_dir, target_size=img_size)\n        X[i] = img_pixels\n        \n    print('Ouptut Data Size: ', X.shape)\n    return X","metadata":{"execution":{"iopub.status.busy":"2021-06-21T08:00:08.615757Z","iopub.execute_input":"2021-06-21T08:00:08.616141Z","iopub.status.idle":"2021-06-21T08:00:08.622354Z","shell.execute_reply.started":"2021-06-21T08:00:08.616104Z","shell.execute_reply":"2021-06-21T08:00:08.621358Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_data = images_to_array2(test_img_Path, sample_submission, img_size)","metadata":{"execution":{"iopub.status.busy":"2021-06-21T08:00:11.025460Z","iopub.execute_input":"2021-06-21T08:00:11.026003Z","iopub.status.idle":"2021-06-21T08:02:00.402232Z","shell.execute_reply.started":"2021-06-21T08:00:11.025954Z","shell.execute_reply":"2021-06-21T08:02:00.401332Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Extract test data features.\ndef extact_features(data):\n    \n    Xception_features = get_features(Xception,\n                                     Xception_preprocessor,\n                                     '../input/d/aeryss/keras-pretrained-models/Xception_NoTop_ImageNet.h5',\n                                     img_size,\n                                     data)\n    \n    NASNetMobile_features = get_features(NASNetMobile,\n                                         NASNetMobile_preprocessor,\n                                         '../input/d/aeryss/keras-pretrained-models/NASNetMobile_NoTop_ImageNet.h5',\n                                         img_size, \n                                         data)\n    \n    InceptionResNetV2_features = get_features(InceptionResNetV2,\n                                              InceptionResNetV2_preprocessor,\n                                              '../input/d/aeryss/keras-pretrained-models/InceptionResNetV2_NoTop_ImageNet.h5',\n                                              img_size, \n                                              data)\n\n    final_features = np.concatenate([Xception_features,\n                                 NASNetMobile_features,\n                                 InceptionResNetV2_features,], axis=-1)\n    \n    print('Final feature maps shape', final_features.shape)\n    #deleting to free up ram memory\n    \n    del Xception_features\n    del NASNetMobile_features\n    del InceptionResNetV2_features\n    gc.collect()\n    \n    \n    return final_features","metadata":{"execution":{"iopub.status.busy":"2021-06-21T08:02:22.497099Z","iopub.execute_input":"2021-06-21T08:02:22.497461Z","iopub.status.idle":"2021-06-21T08:02:22.503663Z","shell.execute_reply.started":"2021-06-21T08:02:22.497427Z","shell.execute_reply":"2021-06-21T08:02:22.502785Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_features = extact_features(test_data)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_pred = model.predict(test_features, batch_size=32)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for breed in dog_breeds:\n    sample_submission[breed] = y_pred[:,class_to_num[breed]]\nsample_submission.to_csv('pred.csv', index=None)\nsample_submission","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# saving model for further use\nmodel.save('dogs_breed.h5')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}