{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Import Library"},{"metadata":{},"cell_type":"markdown","source":"* number of training samples: 8000  (4000 cat - 4000 dog)\n* number of validation samples: 1600 (800 cat - 800 dog)"},{"metadata":{"trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd \nimport tensorflow as tf\nfrom tensorflow import keras\nfrom keras.preprocessing.image import ImageDataGenerator, load_img\nfrom keras import optimizers\nfrom keras.models import Sequential\nfrom keras.layers import Dropout, Flatten, Dense,GlobalAveragePooling2D\nfrom keras import applications\nfrom pathlib import Path\nfrom keras.models import model_from_json\nfrom keras.callbacks import ModelCheckpoint, History\nfrom keras.callbacks import EarlyStopping, ReduceLROnPlateau\nimport matplotlib.pyplot as plt\nimport random\nimport os","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Preparing data"},{"metadata":{"trusted":true},"cell_type":"code","source":"import zipfile\nwith zipfile.ZipFile(\"../input/dogs-vs-cats/train.zip\",\"r\") as zip_ref:\n    zip_ref.extractall(\"train\")\n\nwith zipfile.ZipFile(\"../input/dogs-vs-cats/test1.zip\",\"r\") as zip_ref:\n    zip_ref.extractall(\"test1\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_directory = \"train/train/\"\ntest_directory  = \"test1/test1/\"\n# See sample image\nfilenames = os.listdir(train_directory)\nsample = random.choice(filenames)\nprint(sample)\nimage = load_img(train_directory + sample)\nplt.imshow(image)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# 8000 train samples\n# 1600 validation samples\nimport shutil\nsource_dir = 'train/'\ndef copy_files(prefix_str, range_start, range_end, target_dir):\n    image_paths = []\n    for i in range(range_start, range_end):\n        image_path = os.path.join(source_dir,'train', prefix_str + '.'+ str(i)+ '.jpg')\n        image_paths.append(image_path)\n    dest_dir = os.path.join( 'data', target_dir, prefix_str)\n    os.makedirs(dest_dir)\n\n    for image_path in image_paths:\n        shutil.copy(image_path,  dest_dir)\n\ncopy_files('dog', 0, 4000, 'train')\ncopy_files('cat', 0, 4000, 'train')\ncopy_files('dog', 4000, 4800,'validation')\ncopy_files('cat', 4000, 4800, 'validation')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# All data, 12500 cat, 12500 dog\nsource_dir = 'train/'\ndef copy_files(prefix_str, range_start, range_end, target_dir):\n    image_paths = []\n    for i in range(range_start, range_end):\n        image_path = os.path.join(source_dir,'train', prefix_str + '.'+ str(i)+ '.jpg')\n        image_paths.append(image_path)\n    dest_dir = os.path.join( 'Alldata', target_dir, prefix_str)\n    if not os.path.exists(dest_dir):\n        os.makedirs(dest_dir)\n\n    for image_path in image_paths:\n        shutil.copy(image_path,  dest_dir)\n\ncopy_files('dog', 0, 12500, 'train')\ncopy_files('cat', 0, 12500, 'train')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#remove train folder\nif  os.path.exists('train'):\n    #os.removedirs(\"train\")\n    shutil.rmtree(\"train\") ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# dimensions of our images.\nimg_width, img_height = 160, 160\nIMG_SHAPE = (img_width, img_height, 3)\n\ntrain_data_dir = 'data/train'\nvalidation_data_dir = 'data/validation'\n\nnb_train_samples = 8000\nnb_validation_samples = 1600\nepochs = 5\nbatch_size = 32","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Preparing Library"},{"metadata":{"trusted":true},"cell_type":"code","source":"#Learning curves\ndef Polt_history(hist):\n    acc = hist.history['accuracy']\n    val_acc = hist.history['val_accuracy']\n\n    loss = hist.history['loss']\n    val_loss = hist.history['val_loss']\n    print(\"Accuracy = %0.3f\" % (acc[epochs-1]*100),  \", val_acc = %0.3f\" % (val_acc[epochs-1]*100))\n    print(\"loss     = %0.3f\" % loss[epochs-1], \", val_loss= %0.3f\" % val_loss[epochs-1])\n    plt.figure(figsize=(8, 8))\n    plt.subplot(2, 1, 1)\n    plt.plot(acc, label='Training Accuracy')\n    plt.plot(val_acc, label='Validation Accuracy')\n    plt.legend(loc='lower right')\n    plt.ylabel('Accuracy')\n    plt.ylim([min(plt.ylim()),1])\n    plt.title('Training and Validation Accuracy')\n\n    plt.subplot(2, 1, 2)\n    plt.plot(loss, label='Training Loss')\n    plt.plot(val_loss, label='Validation Loss')\n    plt.legend(loc='upper right')\n    plt.ylabel('Cross Entropy')\n    plt.ylim([0,1.0])\n    plt.title('Training and Validation Loss')\n    plt.xlabel('epoch')\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Model predict\ndef MobileNetV2_predict(Model,Test_dir):  \n    test_filenames = []\n    for file in os.listdir(Test_dir):   \n        test_filenames.append(os.path.join(Test_dir,file))  \n\n    test_df = pd.DataFrame({\n        'filename': test_filenames\n    })\n\n    test_datagen = ImageDataGenerator(rescale=1./255)\n    test_generator=test_datagen.flow_from_dataframe(\n                dataframe=test_df,\n                x_col=\"filename\",\n                y_col=None,\n                batch_size=50,\n                seed=42,\n                shuffle=False,\n                class_mode=None,\n                target_size=(img_height,img_width))\n    \n    nb_test_samples = len(test_df)\n    test_steps=nb_test_samples // 50\n    pred=Model.predict_generator(test_generator,\n                    steps=test_steps,\n                    verbose=1)\n\n    predicted_class_indices=np.argmax(pred,axis=1)\n    #len(predicted_class_indices)\n    #print(predicted_class_indices[:12])\n    \n    return predicted_class_indices,test_df","execution_count":null,"outputs":[]},{"metadata":{"scrolled":true,"trusted":true},"cell_type":"code","source":"# Plot predict image output\n%matplotlib inline\n#import matplotlib.image as mpimg\nimport matplotlib.pyplot as plt\n\ndef Plot_predict(predicted_class_indices,Test_dir,test_df):\n    # Parameters for our graph; we'll output images in a 4x4 configuration\n    nrows = 12\n    ncols = 4\n    pic_index = 0 # Index for iterating over images\n    # Set up matplotlib fig, and size it to fit 4x4 pics\n    fig = plt.gcf()\n    fig.set_size_inches(ncols*4, nrows*4)\n\n    for i, img_path in enumerate(test_df.filename[:48]):\n        # Set up subplot; subplot indices start at 1\n        sp = plt.subplot(nrows, ncols, i + 1)\n        sp.axis('Off') # Don't show axes (or gridlines)\n\n        #img = mpimg.imread(img_path, target_size=(256, 256))Test_dir\n        img = load_img( img_path, target_size=(150,150))\n        plt.imshow(img) \n        result = predicted_class_indices[i]\n        if (result == 1 ):\n            name = 'Dog'\n        else :\n            name = 'Cat'\n        plt.title( name )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Save Submission to csv file\ndef Save_Submission(predict,model,mod,test_df):\n    if not os.path.exists(mod):\n        os.makedirs(mod)\n        \n    test_df['category'] = predict\n    submission_df = test_df.copy()\n    #submission_df['id'] = submission_df['filename'].str.split('.').str[0]\n    submission_df['id'] = submission_df['filename'].str.split('.').str[0].str.split('/').str[1]\n    submission_df['label'] = submission_df['category']\n    submission_df.drop(['filename', 'category'], axis=1, inplace=True)\n    submission_df.index += 1 \n    submission_df.to_csv( mod + '/submission_AM_'+ mod +'.csv', index=True)\n\n    #plt.figure(figsize=(10,5))\n    submission_df['label'].value_counts().plot.bar()\n    plt.title(\"(Test data , \"+mod + \" )\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Model 1"},{"metadata":{"trusted":true},"cell_type":"code","source":"# build the MobileNetV2 network\nbase_model = applications.MobileNetV2(input_shape=IMG_SHAPE,\n                                      include_top=False,\n                                      weights='imagenet')\nprint(\"base_model.layers\", len(base_model.layers)) #155\n\n#Freeze the convolutional base\nfor layer in base_model.layers[:100]:\n    layer.trainable = False","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-output":true,"collapsed":true},"cell_type":"code","source":"# build a classifier model to put on top of the convolutional model\ntop_model = Sequential()\ntop_model.add(Flatten(input_shape=base_model.output_shape[1:]))\ntop_model.add(Dense(256, activation='relu'))\ntop_model.add(Dropout(0.5))\ntop_model.add(Dense(2, activation='sigmoid'))\n\nmodel = Sequential()\nmodel.add(base_model)\nmodel.add(top_model)\n\nbase_model.summary()\ntop_model.summary()\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# prepare data augmentation configuration\ntrain_datagen = ImageDataGenerator(\n                rescale=1./255,\n                shear_range=0.2,\n                zoom_range=0.2,\n                horizontal_flip=True)\n\ntest_datagen = ImageDataGenerator(rescale=1./255)\n\ntrain_generator = train_datagen.flow_from_directory(\n                train_data_dir,\n                target_size=(img_height, img_width),\n                batch_size=batch_size,\n                seed=42,\n                class_mode='categorical')\n\nvalidation_generator = test_datagen.flow_from_directory(\n                validation_data_dir,\n                target_size=(img_height, img_width),\n                batch_size=batch_size,\n                seed=42,\n                class_mode='categorical')#binary","execution_count":null,"outputs":[]},{"metadata":{"scrolled":true,"trusted":true},"cell_type":"code","source":"if not os.path.exists('model'):\n    os.makedirs(\"model\")    \nlearningRate = 1e-4\n# compile the model with a SGD/momentum optimizer and a very slow learning rate.\nmodel.compile(loss='categorical_crossentropy',\n              optimizer=optimizers.SGD(lr=learningRate, momentum=0.9),\n              #optimizer=optimizers.RMSprop(lr=learningRate),\n              metrics=['accuracy'])\n\ncheckpointer = ModelCheckpoint(filepath='model/model.weights.best_MobileNetV2_1.hdf5', \n                               verbose=1, save_best_only=True)\n# fine-tune the model\nhist = model.fit_generator(\n        train_generator,\n        samples_per_epoch=nb_train_samples,\n        epochs=epochs,\n        validation_data=validation_generator,\n        validation_steps=nb_validation_samples // batch_size,\n        callbacks=[checkpointer] )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Save neural network structure and weights\nmodel_structure = model.to_json()\nf = Path(\"model/model_structure_MobileNetV2.json\")\nf.write_text(model_structure)\nmodel.save_weights(\"model/model_weights_MobileNetV2_1.h5\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Model output: Learning curves"},{"metadata":{"scrolled":true,"trusted":true},"cell_type":"code","source":"Polt_history(hist)\nplt.savefig('model/hist.png')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Testing model 1"},{"metadata":{},"cell_type":"markdown","source":"* Testing model 1: on 25000 image "},{"metadata":{"trusted":true},"cell_type":"code","source":"#testing known data in train folder\nprint(\"Testing cats....\")\nmodel_pred_cat,test_df  = MobileNetV2_predict(model,\"Alldata/train/cat\") #0\nprint(\"Testing dogs....\")\nmodel_pred_dog,test_df  = MobileNetV2_predict(model,\"Alldata/train/dog\") #1\n\n#print result\nmodel_true_cat  = len(test_df) - sum (model_pred_cat)\nmodel_true_dog  = sum (model_pred_dog)\nmodel_true      = model_true_cat + model_true_dog\n# model result\nprint(\"  model result\")\nprint(\"cat accuracy  = %2.3f\" % (model_true_cat /len(test_df) *100))\nprint(\"dog accuracy  = %2.3f\" % (model_true_dog /len(test_df) *100))\nprint(\"Total accuracy= %2.3f\" % (model_true /(2*len(test_df)) *100))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* Testing model 1: on 12500 image (test data)"},{"metadata":{"trusted":true},"cell_type":"code","source":"#testing unknown data in test folder\npredict,test_df =MobileNetV2_predict(model,test_directory)\nPlot_predict(predict,test_directory,test_df)\nplt.savefig('model/predicted.png')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Continue train: fine tune model "},{"metadata":{"scrolled":true,"trusted":true},"cell_type":"code","source":"# compile the model with a SGD/momentum optimizer and a very slow learning rate.\nlearningRate=1e-5\nmodel.compile(loss='categorical_crossentropy',\n              #optimizer=optimizers.SGD(lr=learningRate, momentum=0.9),\n              optimizer=optimizers.RMSprop(lr=learningRate),\n              metrics=['accuracy'])\n\ncheckpointer = ModelCheckpoint(filepath='model/model.weights.best_MobileNetV2_2.hdf5',\n                               verbose=1, save_best_only=True)\n\n# fine-tune the model\nhist_2 = model.fit_generator(\n        train_generator,\n        samples_per_epoch=nb_train_samples,\n        epochs=epochs,\n        validation_data=validation_generator,\n        validation_steps=nb_validation_samples // batch_size,\n        callbacks=[checkpointer])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Save neural network weights\nmodel.save_weights(\"model/model_weights_MobileNetV2_2.h5\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#Learning curves\nPolt_history(hist_2)\nplt.savefig('model/hist_2.png')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Testing model 1"},{"metadata":{},"cell_type":"markdown","source":"* Testing model: on 25000 image "},{"metadata":{"trusted":true},"cell_type":"code","source":"#testing known data in train folder\nprint(\"Testing cats....\")\nmodel_pred_cat,test_df  = MobileNetV2_predict(model,\"Alldata/train/cat\") #0\nprint(\"Testing dogs....\")\nmodel_pred_dog,test_df  = MobileNetV2_predict(model,\"Alldata/train/dog\") #1\n\n#print result\nmodel_true_cat  = len(test_df) - sum (model_pred_cat)\nmodel_true_dog  = sum (model_pred_dog)\nmodel_true      = model_true_cat + model_true_dog\n# model result\nprint(\"  model result\")\nprint(\"cat accuracy  = %2.3f\" % (model_true_cat /len(test_df) *100))\nprint(\"dog accuracy  = %2.3f\" % (model_true_dog /len(test_df) *100))\nprint(\"Total accuracy= %2.3f\" % (model_true /(2*len(test_df)) *100))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#testing unknown data in test folder\npredict,test_df =MobileNetV2_predict(model,test_directory)\nSave_Submission(predict,model,\"model\",test_df)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Plot sample of predicted result"},{"metadata":{"trusted":true},"cell_type":"code","source":"Plot_predict(predict,test_directory,test_df)\nplt.savefig('model/predicted_2.png')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"#  Model 2 "},{"metadata":{"trusted":true},"cell_type":"code","source":"if not os.path.exists('model2'):\n    os.makedirs(\"model2\")   \n# build the MobileNetV2 network\nbase_model2 = applications.MobileNetV2(input_shape=IMG_SHAPE,\n                                       include_top=False,\n                                       weights='imagenet')\nprint(\"base_model.layers= \", len(base_model.layers)) #155\n\n#Feature extraction\n#Freeze the convolutional base\nfor layer in base_model.layers[:155]:\n    layer.trainable = False\n    \n# build a classifier model to put on top of the convolutional model\ntop_model2 = Sequential()\ntop_model2.add(GlobalAveragePooling2D())\ntop_model2.add(Dense(2, activation='sigmoid'))\n\nmodel2 = Sequential()\nmodel2.add(base_model2)\nmodel2.add(top_model2)\n\nmodel2.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learningRate=1e-4\nmodel2.compile(loss='categorical_crossentropy',#binary_crossentropy\n              optimizer=optimizers.RMSprop(lr=learningRate),\n              #optimizer=optimizers.SGD(lr=learningRate, momentum=0.9),\n              metrics=['accuracy'])\n\ncheckpointer = ModelCheckpoint(filepath='model2/model2.weights.best_MobileNetV2_1.hdf5', \n                               verbose=1, save_best_only=True)\n\n# fine-tune the model\nhist2 = model2.fit_generator(\n    train_generator,\n    samples_per_epoch=nb_train_samples,\n    epochs=epochs,\n    validation_data=validation_generator,\n    validation_steps=nb_validation_samples // batch_size,\n    #nb_val_samples=nb_validation_samples)\n    callbacks=[checkpointer])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Save neural network structure and weights\nmodel2_structure = model2.to_json()\nf = Path(\"model2/model2_structure_MobileNetV2_2.json\")\nf.write_text(model2_structure)\nmodel2.save_weights(\"model2/model2_weights_MobileNetV2_2.h5\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"Polt_history(hist2)\nplt.savefig('model2/hist_3.png')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Testing model 2"},{"metadata":{},"cell_type":"markdown","source":"* Testing model 2: on 25000 image "},{"metadata":{"trusted":true},"cell_type":"code","source":"#testing known data in train folder\nprint(\"Testing cats....\")\nmodel_pred_cat,test_df  = MobileNetV2_predict(model2,\"Alldata/train/cat\") #0\nprint(\"Testing dogs....\")\nmodel_pred_dog,test_df  = MobileNetV2_predict(model2,\"Alldata/train/dog\") #1\n\n#print result\nmodel_true_cat  = len(test_df) - sum (model_pred_cat)\nmodel_true_dog  = sum (model_pred_dog)\nmodel_true      = model_true_cat + model_true_dog\n# model result\nprint(\"  model result\")\nprint(\"cat accuracy  = %2.3f\" % (model_true_cat /len(test_df) *100))\nprint(\"dog accuracy  = %2.3f\" % (model_true_dog /len(test_df) *100))\nprint(\"Total accuracy= %2.3f\" % (model_true /(2*len(test_df)) *100))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* Testing model 2: on 12500 image (test data)"},{"metadata":{"trusted":true},"cell_type":"code","source":"#testing unknown data in test folder\npredict2,test_df =MobileNetV2_predict(model2,test_directory)\nSave_Submission(predict2,model2,\"model2\",test_df)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"Plot_predict(predict,test_directory,test_df)\nplt.savefig('model2/predicted2.png')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#remove test folder\nif  os.path.exists('test1'):\n    shutil.rmtree(\"test1\") \nif  os.path.exists('data'):\n    shutil.rmtree(\"data\")\nif  os.path.exists('Alldata'):\n    shutil.rmtree(\"Alldata\") \nfile1 = \"model/model.weights.best_MobileNetV2_1.hdf5\"\nfile2 = \"model/model.weights.best_MobileNetV2_2.hdf5\"\nfile3 = \"model/model_weights_MobileNetV2_1.h5\"\nif  os.path.isfile(file1):\n    os.remove(file1)    \nif  os.path.isfile(file2):\n    os.remove(file2) \nif  os.path.isfile(file3):\n    os.remove(file3) ","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.7.3"}},"nbformat":4,"nbformat_minor":1}