{"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":"### What is transfer learning?\nTransfer learning is a research problem in machine learning that focuses on storing knowledge gained while solving one problem and applying it to a different but related problem. \n### An example \nFor example, knowledge gained while learning to recognize cars could apply when trying to recognize trucks.'\n\n\n![Transfer Learning](https://miro.medium.com/max/1400/1*9GTEzcO8KxxrfutmtsPs3Q.png)\n\n\n### Explaining it in simple terms, or atleast trying to \n\n- With transfer learning, we basically try to exploit what has been learned in one task to improve generalization in another. We transfer the weights that a network has learned at \"task A\" to a new \"task B.\"\n\n\n\n- The general idea is to use the knowledge a model has learned from a task with a lot of available labeled training data in a new task that doesn't have much data. \n- Instead of starting the learning process from scratch, we start with patterns learned from solving a related task.\n\n- Transfer learning is mostly used in computer vision and natural language processing tasks like sentiment analysis due to the huge amount of computational power required.\n\n- Transfer learning isn't really a machine learning technique, but can be seen as a \"design methodology\" within the field, for example, active learning. \n- It is also not an exclusive part or study-area of machine learning. Nevertheless, it has become quite popular in combination with neural networks that require huge amounts of data and computational power.\n\n![](https://cdn.builtin.com/sites/www.builtin.com/files/styles/ckeditor_optimize/public/inline-images/national/AGI-transfer-learning_0.png)\n\n\n\n##### I will be following the code done on the same dataset by [Ahmed Saied](https://www.kaggle.com/phylake1337) explained in the link [The Code](https://www.kaggle.com/phylake1337/0-18-loss-simple-feature-extractors/notebook)\n","metadata":{}},{"cell_type":"markdown","source":"### Introduction\n\n* This kernel is a detailed guide for transfer learning on Dog Breeds problem, it's all about learning a new technique, evaluate it using only Kaggle training set without cheating.\n\n* The aim of this kernel is to show you how to use pre-trained CNN models as feature extractors, which one of the most effective transfer learning techniques.\n\n* A reasonable question comes to your mind, 'Wait, why do we have to use this technique, why don't we just use regular transfer learning ?', if you try to do so, you will figure out that the problem is pretty hard for a single model to handle (you would get higher loss and less accuracy).\n\n* It's even hard for humankind to distinguish between 120 dog breeds!, single poor CNN would struggle.\n\n### Explanation\n\n- Take look at general CNN architecture for image classification in two main parts, “feature extractor” that based on conv-layers, and “classifier” which usually based on fully connected layers:\n- Simply, feature extractor could be created as follow > (Feature Extractor = Pretrained Model - Late Fully Connected Layers)\n\n- For example, InceptionV3 feature extractor (without last FC layer) outputs 2048 vector for each image sample, each value represent a certain feature of dog image (Coded in numerical values of course), like Dog color?, How big is his head?, Shape of the eyes?, length of the tale?, Size? .. etc\n\n- Hence, more \"different\" feature extractors mean more features to be used to determine which breed does this dog belong.\n\n- So our strategy goes as the following,\n\n - Create 4 feature extractor using different pre-trained CNN models\n - Extract features from raw data and stacks the features together.\n - Use a simple DNN with one dense layer and a heavy dropout layer to figure out patterns in the feature extracted from the data.\n - The code is simple, concise and fully-commented. Feel free to ask for help / more info / more explanation in the comments.\n\n- Finally if this kernel helps you somehow, kindly don't forget to leave a little upvote.\n\n","metadata":{}},{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os, cv2, random, time, shutil, csv\nimport tensorflow as tf\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\nfrom tqdm import tqdm\nnp.random.seed(42)\n%matplotlib inline \n\nimport tensorflow.keras\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import BatchNormalization, Dense, GlobalAveragePooling2D, Lambda, Dropout, InputLayer, Input\nfrom tensorflow.keras.utils import to_categorical\nfrom tensorflow.keras.preprocessing.image import load_img","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-09-18T07:26:09.681795Z","iopub.execute_input":"2021-09-18T07:26:09.68222Z","iopub.status.idle":"2021-09-18T07:26:14.821028Z","shell.execute_reply.started":"2021-09-18T07:26:09.682096Z","shell.execute_reply":"2021-09-18T07:26:14.820294Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_num_files(path):\n    '''\n    Counts the number of files in a folder.\n    '''\n    if not os.path.exists(path):\n        return 0\n    return sum([len(files) for r, d, files in os.walk(path)])","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:26:14.825049Z","iopub.execute_input":"2021-09-18T07:26:14.82525Z","iopub.status.idle":"2021-09-18T07:26:14.831861Z","shell.execute_reply.started":"2021-09-18T07:26:14.825226Z","shell.execute_reply":"2021-09-18T07:26:14.831129Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Data Paths\ntrain_dir = '/kaggle/input/dog-breed-identification/train'\ntest_dir = '/kaggle/input/dog-breed-identification/test'\n#Count/Print train and test samples.\ndata_size = get_num_files(train_dir)\ntest_size = get_num_files(test_dir)\nprint('Data samples size: ', data_size)\nprint('Test samples size: ', test_size)","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:26:14.833137Z","iopub.execute_input":"2021-09-18T07:26:14.833429Z","iopub.status.idle":"2021-09-18T07:26:27.20364Z","shell.execute_reply.started":"2021-09-18T07:26:14.833377Z","shell.execute_reply":"2021-09-18T07:26:27.202816Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Read train labels.\nlabels_dataframe = pd.read_csv('/kaggle/input/dog-breed-identification/labels.csv')\n#Read sample_submission file to be modified by pridected labels.\nsample_df = pd.read_csv('/kaggle/input/dog-breed-identification/sample_submission.csv')\n#Incpect labels_dataframe.\nlabels_dataframe.head(1)","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:46:48.965269Z","iopub.execute_input":"2021-09-18T07:46:48.965935Z","iopub.status.idle":"2021-09-18T07:46:49.490617Z","shell.execute_reply.started":"2021-09-18T07:46:48.965895Z","shell.execute_reply":"2021-09-18T07:46:49.489906Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Create list of alphabetically sorted labels.\ndog_breeds = sorted(list(set(labels_dataframe['breed'])))\nn_classes = len(dog_breeds)","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:26:27.766772Z","iopub.execute_input":"2021-09-18T07:26:27.767119Z","iopub.status.idle":"2021-09-18T07:26:27.773448Z","shell.execute_reply.started":"2021-09-18T07:26:27.767081Z","shell.execute_reply":"2021-09-18T07:26:27.77278Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import seaborn as sns\n\n\nsns.color_palette(\"light:#5A9\", as_cmap=True)\nfig, ax = plt.subplots()\nfig.set_size_inches(16, 8)\nsns.set_theme(style=\"darkgrid\")\nax = sns.countplot(x=\"breed\", data=labels_dataframe,palette=\"light:#5A9\",order=labels_dataframe.breed.value_counts().iloc[:5].index)","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:26:27.774503Z","iopub.execute_input":"2021-09-18T07:26:27.775268Z","iopub.status.idle":"2021-09-18T07:26:28.024202Z","shell.execute_reply.started":"2021-09-18T07:26:27.775232Z","shell.execute_reply":"2021-09-18T07:26:28.023479Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Map each label string to an integer label.\nclass_to_num = dict(zip(dog_breeds, range(n_classes)))","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:26:28.025421Z","iopub.execute_input":"2021-09-18T07:26:28.025679Z","iopub.status.idle":"2021-09-18T07:26:28.03065Z","shell.execute_reply.started":"2021-09-18T07:26:28.025645Z","shell.execute_reply":"2021-09-18T07:26:28.029787Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def images_to_array(data_dir, labels_dataframe, img_size = (224,224,3)):\n    '''\n    1- Read image samples from certain directory.\n    2- Risize it, then stack them into one big numpy array.\n    3- Read sample's label form the labels dataframe.\n    4- One hot encode labels array.\n    5- Shuffle Data and label arrays.\n    '''\n    images_names = labels_dataframe['id']\n    images_labels = labels_dataframe['breed']\n    data_size = len(images_names)\n    #initailize output arrays.\n    X = np.zeros([data_size, img_size[0], img_size[1], img_size[2]], dtype=np.uint8)\n    y = np.zeros([data_size,1], dtype=np.uint8)\n    #read data and lables.\n    for i in tqdm(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        image_breed = images_labels[i]\n        y[i] = class_to_num[image_breed]\n    \n    #One hot encoder\n    y = to_categorical(y)\n    #shuffle    \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-09-18T07:26:28.031886Z","iopub.execute_input":"2021-09-18T07:26:28.032503Z","iopub.status.idle":"2021-09-18T07:26:28.044255Z","shell.execute_reply.started":"2021-09-18T07:26:28.032459Z","shell.execute_reply":"2021-09-18T07:26:28.043484Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#img_size chosen to be 331 to suit the used architectures.\nimg_size = (331,331,3)\nX, y = images_to_array(train_dir, labels_dataframe, img_size)","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:26:28.045291Z","iopub.execute_input":"2021-09-18T07:26:28.045908Z","iopub.status.idle":"2021-09-18T07:27:41.95521Z","shell.execute_reply.started":"2021-09-18T07:26:28.04587Z","shell.execute_reply":"2021-09-18T07:27:41.954183Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_features(model_name, data_preprocessor, input_size, data):\n    '''\n    1- Create a feature extractor to extract features from the data.\n    2- Returns the extracted features and the feature extractor.\n    '''\n    #Prepare pipeline.\n    input_layer = Input(input_size)\n    preprocessor = Lambda(data_preprocessor)(input_layer)\n    base_model = model_name(weights='imagenet', include_top=False,\n                            input_shape=input_size)(preprocessor)\n    avg = GlobalAveragePooling2D()(base_model)\n    feature_extractor = Model(inputs = input_layer, outputs = avg)\n    #Extract feature.\n    feature_maps = feature_extractor.predict(data, batch_size=64, verbose=1)\n    print('Feature maps shape: ', feature_maps.shape)\n    return feature_maps","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:27:41.956916Z","iopub.execute_input":"2021-09-18T07:27:41.957309Z","iopub.status.idle":"2021-09-18T07:27:41.964213Z","shell.execute_reply.started":"2021-09-18T07:27:41.957265Z","shell.execute_reply":"2021-09-18T07:27:41.963262Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Extract features using InceptionV3 as extractor.\nfrom tensorflow.keras.applications.inception_v3 import InceptionV3, preprocess_input\ninception_preprocessor = preprocess_input\ninception_features = get_features(InceptionV3,\n                                  inception_preprocessor,\n                                  img_size, X)","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:27:41.965642Z","iopub.execute_input":"2021-09-18T07:27:41.965909Z","iopub.status.idle":"2021-09-18T07:28:22.506379Z","shell.execute_reply.started":"2021-09-18T07:27:41.965871Z","shell.execute_reply":"2021-09-18T07:28:22.505498Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Extract features using Xception as extractor.\nfrom tensorflow.keras.applications.xception import Xception, preprocess_input\nxception_preprocessor = preprocess_input\nxception_features = get_features(Xception,\n                                 xception_preprocessor,\n                                 img_size, X)","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:28:22.508174Z","iopub.execute_input":"2021-09-18T07:28:22.508492Z","iopub.status.idle":"2021-09-18T07:29:16.182441Z","shell.execute_reply.started":"2021-09-18T07:28:22.508447Z","shell.execute_reply":"2021-09-18T07:29:16.18081Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Extract features using ResNet152V2 as extractor.\nfrom tensorflow.keras.applications.resnet_v2 import ResNet152V2, preprocess_input\nresnet_preprocessor = preprocess_input\nresnet_features = get_features(ResNet152V2,\n                               resnet_preprocessor,\n                               img_size, X)","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:29:16.18419Z","iopub.execute_input":"2021-09-18T07:29:16.18449Z","iopub.status.idle":"2021-09-18T07:30:45.325805Z","shell.execute_reply.started":"2021-09-18T07:29:16.184449Z","shell.execute_reply":"2021-09-18T07:30:45.324543Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Extract features using NASNetLarge as extractor.\nfrom tensorflow.keras.applications.nasnet import NASNetLarge, preprocess_input\nnasnet_preprocessor = preprocess_input\nnasnet_features = get_features(NASNetLarge,\n                               nasnet_preprocessor,\n                               img_size, X)","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:30:45.33023Z","iopub.execute_input":"2021-09-18T07:30:45.330458Z","iopub.status.idle":"2021-09-18T07:33:56.470244Z","shell.execute_reply.started":"2021-09-18T07:30:45.330432Z","shell.execute_reply":"2021-09-18T07:33:56.469459Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Extract features using InceptionResNetV2 as extractor.\nfrom tensorflow.keras.applications.inception_resnet_v2 import InceptionResNetV2, preprocess_input\ninc_resnet_preprocessor = preprocess_input\ninc_resnet_features = get_features(InceptionResNetV2,\n                                   inc_resnet_preprocessor,\n                                   img_size, X)","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:33:56.473231Z","iopub.execute_input":"2021-09-18T07:33:56.473477Z","iopub.status.idle":"2021-09-18T07:35:11.060597Z","shell.execute_reply.started":"2021-09-18T07:33:56.473448Z","shell.execute_reply":"2021-09-18T07:35:11.05964Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#It's a good habit to free up some RAM memory.\n#X variable won't be needed anymore, so let's get rid of it.\ndel X","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:35:11.062745Z","iopub.execute_input":"2021-09-18T07:35:11.063046Z","iopub.status.idle":"2021-09-18T07:35:11.074667Z","shell.execute_reply.started":"2021-09-18T07:35:11.063008Z","shell.execute_reply":"2021-09-18T07:35:11.073588Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"final_features = np.concatenate([inception_features,\n                                 xception_features,\n                                 resnet_features,\n                                 nasnet_features,\n                                 inc_resnet_features,], axis=-1)\nprint('Final feature maps shape', final_features.shape)","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:35:11.07616Z","iopub.execute_input":"2021-09-18T07:35:11.076442Z","iopub.status.idle":"2021-09-18T07:35:11.265731Z","shell.execute_reply.started":"2021-09-18T07:35:11.076392Z","shell.execute_reply":"2021-09-18T07:35:11.264927Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.callbacks import EarlyStopping\n#Prepare call backs\nEarlyStop_callback = tensorflow.keras.callbacks.EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True)\nmy_callback=[EarlyStop_callback]","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:35:11.267024Z","iopub.execute_input":"2021-09-18T07:35:11.2678Z","iopub.status.idle":"2021-09-18T07:35:11.273033Z","shell.execute_reply.started":"2021-09-18T07:35:11.267757Z","shell.execute_reply":"2021-09-18T07:35:11.272337Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Prepare DNN model\ndnn = tensorflow.keras.models.Sequential([\n    InputLayer(final_features.shape[1:]),\n    Dropout(0.7),\n    Dense(n_classes, activation='softmax')\n])\n\ndnn.compile(optimizer='adam',\n              loss='categorical_crossentropy',\n              metrics=['accuracy'])\n\n#Train simple DNN on extracted features.\nh = dnn.fit(final_features, y,\n            batch_size=128,\n            epochs=60,\n            validation_split=0.1,\n            callbacks=my_callback)","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:35:11.274225Z","iopub.execute_input":"2021-09-18T07:35:11.275031Z","iopub.status.idle":"2021-09-18T07:35:17.813729Z","shell.execute_reply.started":"2021-09-18T07:35:11.274994Z","shell.execute_reply":"2021-09-18T07:35:17.81302Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def images_to_array2(data_dir, labels_dataframe, img_size = (224,224,3)):\n    '''\n    Do same as images_to_array but omit some unnecessary steps for test data.\n    '''\n    images_names = labels_dataframe['id']\n    data_size = len(images_names)-5000\n    X = np.zeros([data_size, img_size[0], img_size[1], 3], dtype=np.uint8)\n    \n    for i in tqdm(range(data_size)):\n        image_name = images_names[i]\n        img_dir = os.path.join(data_dir, image_name+'.jpg')\n        img_pixels = tf.keras.preprocessing.image.load_img(img_dir, target_size=img_size)\n        X[i] = img_pixels\n        \n    print('Ouptut Data Size: ', X.shape)\n    return X\n\ntest_data = images_to_array2(test_dir, sample_df, img_size)","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:35:17.814893Z","iopub.execute_input":"2021-09-18T07:35:17.815151Z","iopub.status.idle":"2021-09-18T07:35:55.725608Z","shell.execute_reply.started":"2021-09-18T07:35:17.815116Z","shell.execute_reply":"2021-09-18T07:35:55.724834Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# del sample_df","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:35:55.727216Z","iopub.execute_input":"2021-09-18T07:35:55.727525Z","iopub.status.idle":"2021-09-18T07:35:55.732285Z","shell.execute_reply.started":"2021-09-18T07:35:55.727486Z","shell.execute_reply":"2021-09-18T07:35:55.731525Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Extract test data features.\ninception_features = get_features(InceptionV3, inception_preprocessor, img_size, test_data)\nxception_features = get_features(Xception, xception_preprocessor, img_size, test_data)\nresnet_features = get_features(ResNet152V2, resnet_preprocessor, img_size, test_data)\nnasnet_features = get_features(NASNetLarge, nasnet_preprocessor, img_size, test_data)\ninc_resnet_features = get_features(InceptionResNetV2, inc_resnet_preprocessor, img_size, test_data)\n\ntest_features = np.concatenate([inception_features,\n                                 xception_features,\n                                 resnet_features,\n                                 nasnet_features,\n                                 inc_resnet_features],axis=-1)\nprint('Final feature maps shape', test_features.shape)","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:41:35.609097Z","iopub.execute_input":"2021-09-18T07:41:35.610014Z","iopub.status.idle":"2021-09-18T07:45:41.765462Z","shell.execute_reply.started":"2021-09-18T07:41:35.609968Z","shell.execute_reply":"2021-09-18T07:45:41.764624Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Free up some space.\ndel test_data","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:45:41.767221Z","iopub.execute_input":"2021-09-18T07:45:41.767812Z","iopub.status.idle":"2021-09-18T07:45:41.828977Z","shell.execute_reply.started":"2021-09-18T07:45:41.767769Z","shell.execute_reply":"2021-09-18T07:45:41.827161Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Predict test labels given test data features.\ny_pred = dnn.predict(test_features, batch_size=128)","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:46:07.872357Z","iopub.execute_input":"2021-09-18T07:46:07.873023Z","iopub.status.idle":"2021-09-18T07:46:08.235983Z","shell.execute_reply.started":"2021-09-18T07:46:07.872983Z","shell.execute_reply":"2021-09-18T07:46:08.235135Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Create submission file\nsample_df = sample_df.head(5357)\nfor b in dog_breeds:\n    sample_df[b] = y_pred[:,class_to_num[b]]\nsample_df.to_csv('pred.csv', index=None)","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:47:18.165519Z","iopub.execute_input":"2021-09-18T07:47:18.166208Z","iopub.status.idle":"2021-09-18T07:47:19.115106Z","shell.execute_reply.started":"2021-09-18T07:47:18.166164Z","shell.execute_reply":"2021-09-18T07:47:19.114281Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"If there are any suggesion for the notebook please comment, that would be helpful. Also please upvote if you liked it! Thank you!!\n\nSome of my other works:\n\n* [TPS- APR](https://www.kaggle.com/udbhavpangotra/tps-apr21-eda-model) \n* [HEART ATTACKS](https://www.kaggle.com/udbhavpangotra/heart-attacks-extensive-eda-and-visualizations) \n* [YOUTUBE DATA EXPLORATION](https://www.kaggle.com/udbhavpangotra/what-do-people-use-youtube-for-in-great-britain)\n* [TPS MAY](https://www.kaggle.com/udbhavpangotra/tps-may-21-extensive-eda-catboost-shap)\n* [COVID-19 DIGITAL LEARNING](https://www.kaggle.com/udbhavpangotra/how-did-covid-19-impact-digital-learning-eda)\n* [TPS - SEPT](https://www.kaggle.com/udbhavpangotra/extensive-eda-baseline-shap)\n* [EDA - Wikimedia Image/Caption Matching](https://www.kaggle.com/udbhavpangotra/eda-wikimedia-image-caption-matching)\n\n\n\n\nDataset \n* [also try this dataset ReliefWeb Crisis Figures Data](https://www.kaggle.com/udbhavpangotra/reliefweb-crisis-figures-data)","metadata":{}},{"cell_type":"code","source":"%%html\n<marquee style='width: 90% ;height:70%; color: #45B39D ;'>\n    <b>Do UPVOTE if you like my work!  :) </b></marquee>","metadata":{"execution":{"iopub.status.busy":"2021-09-18T07:49:27.118298Z","iopub.execute_input":"2021-09-18T07:49:27.119051Z","iopub.status.idle":"2021-09-18T07:49:27.127718Z","shell.execute_reply.started":"2021-09-18T07:49:27.119014Z","shell.execute_reply":"2021-09-18T07:49:27.126791Z"},"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}