{"cells":[{"cell_type":"markdown","metadata":{"_cell_guid":"ddc42b71-4da2-5d91-9b1c-b1cf21a33717"},"source":"# Dog vs. Cat Detection\nThis notebook presents an entire fully working convolutional neural network to classify dog vs. cat images. I am having trouble running it on the kaggle notebook server because I keep getting an \"out of memory\"/other resources error. I got it to work on my own machine with smaller number of training images."},{"cell_type":"markdown","metadata":{"_cell_guid":"79071766-c5a5-0b9c-8c29-f3dc9779ee85"},"source":"## Import Training Data\nThis section will prepare and import the training data images"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"62104665-904d-8599-a913-c39258f45def"},"outputs":[],"source":"TRAIN_DIR = '../input/train' #training directory\nTEST_DIR = '../input/test' #testing directory\n"},{"cell_type":"markdown","metadata":{"_cell_guid":"bc76fc59-1ae7-9282-a59c-3bdd8d131807"},"source":"Pre-define a function that will take the labels from the image name (thanks to other kernels on Kaggle)."},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"4f047808-a122-e949-a00f-b4a40d7e1486"},"outputs":[],"source":"def label_img(img):\n    word_label = img.split('.')[-3]\n    if word_label == 'cat': return [1,0] #[cat, not dog]\n    elif word_label == 'dog': return [0,1] #[not cat, dog]"},{"cell_type":"markdown","metadata":{"_cell_guid":"e7ad9757-7793-e92f-16a7-c74af71da9b8"},"source":"Define a function that will retrieve the training data:"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"fd68b583-b1b8-ba8a-90fa-78ba0e0b3033"},"outputs":[],"source":"import cv2\nimport os\nimport numpy as np\nfrom tqdm import tqdm \nIMG_SIZE=64 #Define short image size\n\ndef create_train_data():\n    X = [] #training images\n    Y = [] #training labels\n    for img in tqdm(os.listdir(TRAIN_DIR)[5000:20000]):\n        label = label_img(img)\n        path=os.path.join(TRAIN_DIR, img)\n        im=cv2.imread(path)\n        sh=im.shape\n        if sh[0] < sh[1]:  # Find the shortest dimension\n            im1=im[0:sh[0],0:sh[0]]\n            im2=im[0:sh[0],(sh[1]-sh[0]):sh[1]]\n            #rint(\"\"\n        else:\n            im1=im[0:sh[1],0:sh[0]]\n            im2=im[(sh[0]-sh[1]):sh[0],0:sh[1]]\n        #Resize images to make them smaller\n        im1 = cv2.resize(im1, (IMG_SIZE,IMG_SIZE))\n        im2 = cv2.resize(im2, (IMG_SIZE,IMG_SIZE))\n        #Append the two images together\n        imn=np.append(im1,im2,axis=0)\n        X.append(np.array(imn))\n        Y.append(np.array(label))\n    return(X,Y)\n    "},{"cell_type":"markdown","metadata":{"_cell_guid":"34c9de4a-d41a-0813-9336-1452d3a09406"},"source":"Run the new function to create the training data."},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"c2afe5f8-0117-0110-057d-b783b131a91d"},"outputs":[],"source":"X,Y = create_train_data()"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"8b529d03-8e87-b798-f0c9-490534730a6c"},"outputs":[],"source":"#Convert the training data to an appropriate filetype\nY=np.asarray(Y)\nY=Y.astype(np.float32) #Now Y is fixed to a datatype\n\nX=np.asarray(X)\n#type(X[1,1,1,1])\nX=(X/256).astype(np.float32)\nprint(\"Done converting the files to float64\")"},{"cell_type":"markdown","metadata":{"_cell_guid":"7bc705af-160d-ef97-62e5-7d2c54c643a2"},"source":"Try some of the images to make sure what they look like:"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"4c6ebdc8-7a69-c960-4a2d-76c159b22b5f"},"outputs":[],"source":"import matplotlib.pyplot as plt\nimport random\nfrom tflearn.data_utils import shuffle\n\n#index=random.randint(0,25000-1)\n#plt.imshow(X[index])\n#Y[index]\n#X[index].shape\n\nX, Y = shuffle(X, Y)\n\nXtrain=X[0:13000]\nYtrain=Y[0:13000]\nXtest=X[13000:15000]\nYtest=Y[13000:15000]\n"},{"cell_type":"markdown","metadata":{"_cell_guid":"027f2565-dcb7-a9ea-2e64-b1cfeec418dd"},"source":"## Define the Neural Network\nThis next section will define the neural network for the detector"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"aa9d952f-112a-c913-c3cb-731571b89f52"},"outputs":[],"source":"import tflearn\nfrom tflearn.layers.core import input_data, dropout, fully_connected\nfrom tflearn.layers.conv import conv_2d, max_pool_2d\nfrom tflearn.layers.estimator import regression\nfrom tflearn.data_preprocessing import ImagePreprocessing\nfrom tflearn.data_augmentation import ImageAugmentation\n\n#Pre-process the images\n# Real-time data preprocessing\nimg_prep = ImagePreprocessing()\nimg_prep.add_featurewise_zero_center()\nimg_prep.add_featurewise_stdnorm()\n\n# Real-time data augmentation\nimg_aug = ImageAugmentation()\nimg_aug.add_random_flip_leftright()\nimg_aug.add_random_rotation(max_angle=25.)\n\n\n# Convolutional network building\nnetwork = input_data(shape=[None, IMG_SIZE*2, IMG_SIZE, 3], #Define input layer\n                     data_preprocessing=img_prep, #set data_preprocessing\n                     data_augmentation=img_aug)\n\nnetwork = conv_2d(network, 32,3, activation='relu') #convolve data once\nnetwork = max_pool_2d(network,2) #down sample (reduce data)\nnetwork = conv_2d(network, 64, 3, activation='relu')\nnetwork = conv_2d(network, 64, 3, activation='relu')\nnetwork = max_pool_2d(network,2) #down sample (reduce data)\nnetwork = max_pool_2d(network, 2)\nnetwork = fully_connected(network, 512, activation='relu')\nnetwork = dropout(network, 0.5)\nnetwork = fully_connected(network, 2, activation='softmax')\nnetwork = regression(network, optimizer='adam',\n                     loss='categorical_crossentropy',\n                     learning_rate=0.001)"},{"cell_type":"markdown","metadata":{"_cell_guid":"f21318c0-5d17-f6a8-9570-389e521fe9b4"},"source":"Run the training iterations repeatedly"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"2619e2e4-2d7f-2be1-3ffd-841940228049"},"outputs":[],"source":"#import scipy\n\n#Define the model\nmodel = tflearn.DNN(network, tensorboard_verbose=0, checkpoint_path='dog-cat.tfl.ckpt')\nmodel.fit(Xtrain, Ytrain, n_epoch=10, \n          shuffle=True, \n          validation_set=(Xtest, Ytest),\n          show_metric=True, \n          batch_size=96, \n          run_id='catvdog')"},{"cell_type":"markdown","metadata":{"_cell_guid":"ca657c11-e33d-26c3-c788-7174a9319fdd"},"source":"## Preparation\nNow the model is trained. Time to prepare the training data and see what can be done."},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"47b3c74c-67d6-dc76-de58-269c1b31d8d3"},"outputs":[],"source":"def prepare_testing_data():\n    Xtest = [] #training images\n    filenames = []\n    for img in tqdm(os.listdir(TEST_DIR)):\n        path=os.path.join(TEST_DIR, img)\n        im=cv2.imread(path)\n        sh=im.shape\n        if sh[0] < sh[1]:  # Find the shortest dimension\n            im1=im[0:sh[0],0:sh[0]]\n            im2=im[0:sh[0],(sh[1]-sh[0]):sh[1]]\n            #rint(\"\"\n        else:\n            im1=im[0:sh[1],0:sh[0]]\n            im2=im[(sh[0]-sh[1]):sh[0],0:sh[1]]\n        #Resize images to make them smaller\n        im1 = cv2.resize(im1, (IMG_SIZE,IMG_SIZE))\n        im2 = cv2.resize(im2, (IMG_SIZE,IMG_SIZE))\n        #Append the two images together\n        imn=np.append(im1,im2,axis=0)\n        Xtest.append(np.array(imn))\n        filenames.append(img)\n    return(Xtest,filenames)\n    "},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"2ebe36fd-7cff-1826-d172-d84dcc7a9ea0"},"outputs":[],"source":"Xcomp1,fn = prepare_testing_data() #load a portion of the testing data"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"57a53bf9-75e7-2147-c855-7f054e3a7f26"},"outputs":[],"source":"Xcomp1=np.asarray(Xcomp1)\nXcomp1=(Xcomp1/256).astype(np.float64)\nprint(\"Done\")"},{"cell_type":"markdown","metadata":{"_cell_guid":"f6202617-87d9-640d-3021-c2509bdb17ac"},"source":"Now run the model on the testing data"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"64f8fd99-709d-ccee-315a-f8e54ca4807e"},"outputs":[],"source":"ind=random.randint(0,5000)\n\npath=os.path.join(TEST_DIR, fn[ind])\nim=cv2.imread(path)\nplt.imshow(im)\nplt.show()\n\nplt.imshow(Xcomp1[ind])\nplt.show()\n\nk=model.predict(np.reshape(Xcomp1[ind],(1,100,50,3)))\n\nprint(fn[ind])\nprint(\"Cat         Dog\")\nprint(\"%2.4f     %2.4f\" % (k[0][0], k[0][1]) )"},{"cell_type":"markdown","metadata":{"_cell_guid":"4779a567-5383-1018-139f-2cbe8cb9d784"},"source":"## Create the submission CSV file\nThe next code section will create a submission .CSV file. "},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"b8c8a977-0640-3ecb-51e0-43ab53289029"},"outputs":[],"source":"import csv\nfn\n\nindex_array=np.empty([12500,1]).astype(np.uint16)\npred_array=np.empty([12500,1]).astype(np.float64)\n\n\nindex=int(i[:-4])\n\n\np=0\nfor i in tqdm(fn):\n    index=int(i[:-4])\n    \n    pred=model.predict(np.reshape(Xcomp1[p],(1,100,50,3)))\n    \n    index_array[index-1]=index\n    pred_array[index-1]=pred[0][1]\n    p=p+1"},{"cell_type":"markdown","metadata":{"_cell_guid":"aa259586-1625-9048-77b3-4853c385f896"},"source":"Now write the results to the submission file."},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"5dde0a08-e5a8-9ea8-2d4a-85684209be55"},"outputs":[],"source":"output=np.column_stack((index_array,pred_array))\nnp.savetxt('submission.csv',\n           output,\n           fmt='%d, %1.4f',\n           delimiter=',',\n           header='id,label')"}],"metadata":{"_change_revision":0,"_is_fork":false,"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.6.0"}},"nbformat":4,"nbformat_minor":0}