{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\n###### Uncomment the code below if required #########\n#import os\n#for dirname, _, filenames in os.walk('/kaggle/input'):\n #   for filename in filenames:\n  #      print(os.path.join(dirname, filename))\n\n# You can write up to 5GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","collapsed":true,"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":false},"cell_type":"markdown","source":"## Environment Set up"},{"metadata":{"trusted":true},"cell_type":"code","source":"# usual imports #\nimport os\nimport numpy as np\nimport pandas as pd\n\n# visualization imports #\nimport matplotlib as mpl\nimport matplotlib.pyplot as plt\nfrom matplotlib.image import imread\n%matplotlib inline\n\n# consistent plots #\nfrom pylab import rcParams\nrcParams['figure.figsize']= 12,5\nrcParams['xtick.labelsize']= 12\nrcParams['ytick.labelsize']= 12\nrcParams['axes.labelsize']= 12\n\n# ignore unwanted warnings #\nimport warnings\nwarnings.filterwarnings(action='ignore',message='^internal gelsd')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# designate directory to save the images #\nROOT_DIR = '/kaggle/input/day-3-kaggle-competition'\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"DATA_PATH = os.path.join(ROOT_DIR , 'data_comp/data_comp')\nTRAIN_PATH = os.path.join(DATA_PATH,'train')\nTEST_PATH = os.path.join(DATA_PATH + '/' + 'test')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# check the files or directories in the training path #\nos.listdir(TRAIN_PATH)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Data Exploration \nSelect any random directory and view one of the images from the training folder"},{"metadata":{"trusted":true},"cell_type":"code","source":"rand = np.random.randint(len(os.listdir(TRAIN_PATH)))\nfurniture_title = os.listdir(TRAIN_PATH)[rand]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"furniture_path = os.path.join(TRAIN_PATH,furniture_title)\nfurniture_images  = os.listdir(furniture_path)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"n_rows = 2\nn_cols = 4\n\nfor row in range(n_rows):\n    for col in range(n_cols):\n        index = n_cols * row + col\n        plt.subplot(n_rows,n_cols,index+1)\n        sample_image_path = os.path.join(furniture_path + '/',furniture_images[index])\n        furniture = imread(sample_image_path)\n        plt.imshow(furniture,cmap='binary',interpolation='nearest')\n        plt.axis('off')\n        plt.title(furniture_title,fontsize=10)  ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Clearly \n- These are colored 3D images of the furnitures\n- The same furniture can be presented in any orientation and can have varying size\n- The brightness varies etc\n\nHene the model should be good enough to be able to identify the furniture type \nwhen it is shown in different angles. "},{"metadata":{},"cell_type":"markdown","source":"***Check the number of images in the training folder***"},{"metadata":{"trusted":true},"cell_type":"code","source":"num_images = 0\nfor folder in os.listdir(TRAIN_PATH):\n    num_images = num_images + len(os.listdir(os.path.join(TRAIN_PATH + '/' + folder)))    \nprint ('Total number of images in the train dir = {}'.format(num_images))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"***Check the dimension of these images***\nCalculate the mean dimension to set as the input_shape\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"# check the dimension of each training image and calculate the mean shape #\ndim1 = []\ndim2 = []\n\nfor folder in os.listdir(TRAIN_PATH):\n    for image_filename in os.listdir(TRAIN_PATH + '/' + folder):\n        img = imread(os.path.join(TRAIN_PATH,folder,image_filename))\n        #print(os.path.join(TRAIN_PATH,folder,image_filename))\n        d1,d2 = img.shape[0],img.shape[1]\n        dim1.append(d1)\n        dim2.append(d2)\nprint (np.mean(dim1),np.mean(dim2))\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"IMAGE_SHAPE = (int(np.mean(dim1)),int(np.mean(dim2)),3)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# image shape with the color channel to be later fed into the model #\nIMAGE_SHAPE","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Prepare the data for Deep Learning Model \n\nMore than 6000 images is too much data to read all at once in memory. The better strategy would be to use some built in functions in Keras to automatically process the data, generate a flow of batches from a directory, and also manipulate the images.\n\n### Image Manipulation\n\nIts usually a good idea to manipulate the images with rotation, resizing, and scaling so the model becomes more robust to different images that our data set doesn't have. We can use the **ImageDataGenerator** to do this automatically for us. "},{"metadata":{"trusted":true},"cell_type":"code","source":"# import the image data generator \nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"***Use the ImageDataGenerator to generate images by using the following parameters***\n- rotate_range --> rotate images by 20%\n- width_shift_range --> shift the width by 10%\n- height_shift_range --> shift the height by 10%\n- rescale --> rescale the image to be between 0 and 1 \n- shear_range --> cut off by a certain percentage 10%\n- zoom_range --> zoom the image by 10%\n- horizontal_flip --> flip the image horizontally\n- fill_mode --> fill the empty pixel based on the values of the nearest pixel in original image\n- vertical_flip --> flip the image vertically (upside down)\n- validation_split --> use 30% of the data in training folder for validation"},{"metadata":{"trusted":true},"cell_type":"code","source":"# generate images using the data generator --> check help(ImageDataGenerator) #\nimage_gen = ImageDataGenerator(rotation_range=90,\n                               width_shift_range=0.10, \n                               height_shift_range=0.10,\n                               rescale=1./255,\n                               shear_range=0.1,\n                               zoom_range=0.1,\n                               horizontal_flip=True,\n                               fill_mode='nearest',\n                               vertical_flip=False,\n                               validation_split=0.3)  ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# visualize one of the original image of a furniture #\nfurniture_orig = imread(sample_image_path)\nplt.imshow(furniture_orig)\nplt.axis('off')\nplt.title('Original Image');","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# visualize one the randomly generated image by the image generator of the same fruit #\nplt.imshow(image_gen.random_transform(furniture_orig))\nplt.axis('off')\nplt.title('Image Generated using Data Generator');","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Generating many manipulated images from directory"},{"metadata":{"trusted":true},"cell_type":"code","source":"image_gen.flow_from_directory(TRAIN_PATH)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Model Creation\n\n***Use combination of Covolutional, Pooling Layer and finally Dense Layer***"},{"metadata":{"trusted":true},"cell_type":"code","source":"# import the libraries #\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D,Dense,Flatten,MaxPooling2D,Dropout\nfrom tensorflow import keras","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# clear the session #\nkeras.backend.clear_session()\nnp.random.seed(42)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# create a sequential model #\nmodel = Sequential()\n\n# convolutional and max pool layer #\nmodel.add(Conv2D(filters=32,kernel_size=(3,3),padding='same',strides=(1,1),\n                activation='relu',input_shape=IMAGE_SHAPE))\nmodel.add(MaxPooling2D(pool_size=(2,2)))\n\nmodel.add(Conv2D(filters=64,kernel_size=(3,3),padding='same',strides=(1,1),\n                activation='relu',input_shape=IMAGE_SHAPE))\nmodel.add(MaxPooling2D(pool_size=(2,2)))\n\nmodel.add(Conv2D(filters=128,kernel_size=(3,3),padding='same',strides=(1,1),\n                activation='relu',input_shape=IMAGE_SHAPE))\nmodel.add(MaxPooling2D(pool_size=(2,2)))\n\n# flatten the layer before feeding into the dense layer #\nmodel.add(Flatten())\n\n# dense layer together with dropout to prevent overfitting #\nmodel.add(Dense(units=128,activation='relu',kernel_initializer='he_normal'))\nmodel.add(Dense(units=64,activation='relu',kernel_initializer='he_normal'))\nmodel.add(Dropout(0.5))\nmodel.add(Dense(units=32,activation='relu',kernel_initializer='he_normal'))\nmodel.add(Dropout(0.5))\n\n# there are 5 classes, hence 5 neurons in the final layer #\nmodel.add(Dense(units=5,activation='softmax'))\n\n# compile the model #\nmodel.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# check the model summary # \nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#model.layers","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Early Stopping"},{"metadata":{"trusted":true},"cell_type":"code","source":"# import early stopping and model checkpoint #\nfrom tensorflow.keras.callbacks import ModelCheckpoint,EarlyStopping","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"early_stop = EarlyStopping(monitor='val_loss',patience=5,restore_best_weights=True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Data for training the Model"},{"metadata":{"trusted":true},"cell_type":"code","source":"BATCH_SIZE = 16\nIMAGE_SHAPE[:2]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"***Train Image***"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_image_gen = image_gen.flow_from_directory(TRAIN_PATH,target_size=IMAGE_SHAPE[:2],\n                                               color_mode='rgb',batch_size=BATCH_SIZE,\n                                               class_mode='categorical',seed=1,subset='training')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"***Validation Image***"},{"metadata":{"trusted":true},"cell_type":"code","source":"validation_image_gen = image_gen.flow_from_directory(TRAIN_PATH,target_size=IMAGE_SHAPE[:2],\n                                               color_mode='rgb',batch_size=BATCH_SIZE,\n                                               class_mode='categorical', shuffle=False,subset='validation',\n                                               seed=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# check the class indices #\ntrain_image_gen.class_indices","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Train the Model"},{"metadata":{"trusted":true},"cell_type":"code","source":"# fit the model and train with early stop enabled #\nepoch = 30\nhistory=model.fit(train_image_gen,\n                  validation_data = validation_image_gen,\n                  epochs = epoch,callbacks=[early_stop])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# create dataframe of the loss and accuracy of the train and validation data #\ndf_loss = pd.DataFrame(model.history.history)\ndf_loss.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df_loss[['loss','accuracy','val_loss','val_accuracy']].plot()\nplt.xlabel('epochs')\nplt.ylabel('loss')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.evaluate(validation_image_gen)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_image_gen = ImageDataGenerator(rescale=1./255)   \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"os.makedirs('/kaggle/test',exist_ok=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from distutils.dir_util import copy_tree","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"TEST_PATH","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Arrange the test folder in teh required dir needed to use the image generator test/test/files"},{"metadata":{"trusted":true},"cell_type":"code","source":"src = TEST_PATH\ndest = '/kaggle/test/test'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"copy_tree(src,dest)\n#test_path = '/kaggle/test'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_path = '/kaggle/test'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_generator = test_image_gen.flow_from_directory(directory=test_path,\n                                                 target_size=IMAGE_SHAPE[:2],\n                                                 color_mode='rgb',\n                                                 batch_size=BATCH_SIZE,\n                                                 class_mode=None,\n                                                  shuffle=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pred = model.predict(test_generator,steps=len(test_generator),verbose=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"predicted_class_indices=np.argmax(pred,axis=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"labels = (train_image_gen.class_indices)\nlabels = dict((v,k) for k,v in labels.items())\npredictions = [labels[k] for k in predicted_class_indices]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# get filenames \nfilenames=test_generator.filenames\nresults=pd.DataFrame({\"Filename\":filenames,\n                      \"Predictions\":predictions})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"results","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"results.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def file_name(st):\n    x = st.split('/')\n    y = x[1].split('.')\n    return y[0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"results['image'] = results['Filename'].apply(file_name)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"results.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"results.drop('Filename',axis=1,inplace=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"results.head(5)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def pred(st):\n    if st=='chair':\n        return 1\n    elif st == 'swivelchair':\n        return 3\n    elif st == 'bed':\n        return 0\n    elif st == 'table':\n        return 4\n    else:\n        return 2\n        \n    \n    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"results['target'] = results['Predictions'].apply(pred)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"results.head(100)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"results.drop('Predictions',axis=1,inplace=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"results.head(10)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"results.to_csv('furn30_submission_2.csv',index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"os.listdir('/kaggle/working')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"results.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"type(results['image'][0])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","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}