{"cells":[{"metadata":{},"cell_type":"markdown","source":"Introduction: Using transfer learning to classify the aerial cactus"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os,cv2\nfrom IPython.display import Image\nfrom keras.preprocessing import image\nfrom keras import optimizers\nfrom keras import layers,models\nfrom keras.applications.imagenet_utils import preprocess_input\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom keras import regularizers\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.callbacks import ReduceLROnPlateau\nfrom keras.models import Sequential\nfrom keras.applications.vgg16 import VGG16\n\nimport numpy as np\nimport math\n\nfrom keras.layers import Dropout, Flatten,Activation\nfrom keras.layers import Dense\nfrom keras.optimizers import Adam,SGD,Adagrad,Adadelta,RMSprop\n\n#System\nimport os\nprint(os.listdir(\"../input\"))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#input datasets\ntrain_dir = '../input/aerial-cactus-identification/train/train'\ntest_dir = '../input/aerial-cactus-identification/test/test'\n\nlabels = pd.read_csv('../input/aerial-cactus-identification/train.csv')\n\nx_train = labels.id\ny_train = labels.has_cactus\n\nprint('total row and column of data =' + str(labels.shape[0:]))\nprint('total image with cactus count =',sum(y_train == 1))\nlabels.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#conversion of has_Cactus from int to string so that it can fit train_generator\nlabels.has_cactus = labels.has_cactus.astype(str)\n\n#specify details of image generator\ntrain_datagen = ImageDataGenerator(\n        #normalize all image\n        rescale=1./255,\n        rotation_range=40,\n        width_shift_range=0.2,\n        height_shift_range=0.2,\n        shear_range=0.2,\n        zoom_range=0.2,\n        horizontal_flip=True,\n        vertical_flip = True,\n        fill_mode='nearest')\n\n#use .flowfromDataFrame but not .flowfromDirectory as images are clustered in one folder\n#dataframe = csv file\ntrain_generator = train_datagen.flow_from_dataframe(\n    dataframe = labels[:13500],\n    directory = train_dir,\n    x_col = 'id',\n    y_col = 'has_cactus',\n    target_size = (128,128),\n    color_mode = 'rgb',\n    class_mode = 'binary')\n\nval_datagen = ImageDataGenerator(rescale = 1./255)\n\nval_generator = val_datagen.flow_from_dataframe(\n    dataframe = labels[13500:],\n    directory = train_dir,\n    x_col = 'id',\n    y_col = 'has_cactus',\n    target_size = (128,128),\n    color_mode = 'rgb',\n    class_mode = 'binary')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#set base_model as transfer learning model\n\nbase_model = VGG16(include_top = False,weights =None,input_shape =(128,128,3))\n#manually added weights as failed to download from Kaggle\nbase_model.load_weights('../input/trans-learn-weights/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"val_generator = val_datagen.flow_from_dataframe(\n    dataframe = labels[13500:],\n    directory = train_dir,\n    x_col = 'id',\n    y_col = 'has_cactus',\n    target_size = (128,128),\n    color_mode = 'rgb',\n    class_mode = 'binary')\nbase_model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Declare sequential for transfer training\nmodel = Sequential()\n\n#Add basemodel and 1 final layers\nmodel.add(base_model)\nmodel.add(Flatten())\nmodel.add(Dense(256,activation = 'relu'))\nmodel.add(Dropout(0.5))\nmodel.add(Dense(1,activation = 'sigmoid'))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#Unfreezing 2 layers of the base model\nfor i in range (len(base_model.layers)):\n    print (i,base_model.layers[i])\n  \nfor layer in base_model.layers[11:]:\n    layer.trainable=True\nfor layer in base_model.layers[0:11]:\n    layer.trainable=False"},{"metadata":{"trusted":true},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for i in range (len(base_model.layers)):\n    print (i,base_model.layers[i])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Unfreezing last 2 layers of VGG16 model\nfor layer in base_model.layers[11:]:\n    layer.trainable=True\nfor layer in base_model.layers[0:11]:\n    layer.trainable=False\nprint('Unfreezed base model')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"epochs=8\nbatch_size=128\n\n#Using learning rate annealer\nred_lr=ReduceLROnPlateau(monitor='val_acc', factor=0.1, patience=2, verbose=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Compile all layers\n#loss is binary_crossentropy as the problem only involve 1 and 0 ( binary ）\n#optimizer alternative : optimizers.rmsprop()\nmodel.compile(optimizer=Adam(lr=1e-4),loss='binary_crossentropy',metrics=['accuracy'])\n\nprint('model compiled')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Fit the model\nHistory = model.fit_generator(train_generator, callbacks = [red_lr],\n                              epochs = epochs, validation_data = val_generator, validation_steps = 50,\n                              verbose = 1, steps_per_epoch= math.ceil(labels.shape[0]/ batch_size))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Visualizing the result of accuracy\nplt.plot(History.history['acc'])\nplt.plot(History.history['val_acc'])\nplt.title('Model Accuracy')\nplt.ylabel('Accuracy')\nplt.xlabel('Epochs')\nplt.legend(['train', 'test'])\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Visualizing the result of loss\nplt.plot(History.history['loss'])\nplt.plot(History.history['val_loss'])\nplt.title('Model loss')\nplt.ylabel('Loss')\nplt.xlabel('Epochs')\nplt.legend(['train', 'test'])\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#save model using pickle method\nimport pickle\n\n#save the model\nmodel_file = \"model.sav\"\nwith open(model_file,mode='wb') as model_f:\n    pickle.dump(model,model_f)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_label=pd.read_csv('../input/aerial-cactus-identification/sample_submission.csv')\n\ntest_datagen = ImageDataGenerator(rescale = 1./255)\n\ntest_generator = test_datagen.flow_from_dataframe(\n    dataframe = test_label,\n    directory = test_dir,\n    x_col = 'id',\n    y_col = 'has_cactus',\n    target_size = (128,128),\n    color_mode = 'rgb',\n    class_mode = 'other',\n    shuffle = False)\n\npredict = model.predict_generator(test_generator,steps = test_label.shape[0],verbose = 1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Load the model\n#with open(model_file,mode='rb') as model_f:\n#model = pickle.load(model_f)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Code for submission\nprint(predict)\ny_submit = pd.read_csv('../input/aerial-cactus-identification/sample_submission.csv')\ncount = 0\nwhile (count <= y_submit.shape[0]):\n    y_submit.has_cactus[count] = predict[count]\n    count += 1\n    if(count % 100 == 0):\n        print('done 100 copies'+str(count))\n    if(count % 4000 == 0):\n        break\ny_submit.to_csv('submission.csv',index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"y_submit.head()","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}