{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"#import the neccesary packages\nimport pandas as pd\nimport numpy as np\n\n#constants\nnum_classes = 12 # the number of breeds we want to classify\nseed = 42 # makes the random numbers in numpy predictable\nim_size = 299 # This size of the images\nbatch_size = 32\n\n#read the csv into a dataframe, group the breeds and \ndf = pd.read_csv('../input/dog-breed-identification/labels.csv')\nselected_breed_list = list(df.groupby('breed').count().sort_values(by='id', ascending=False).head(num_classes).index)\ndf = df[df['breed'].isin(selected_breed_list)]\ndf['filename'] = df.apply(lambda x: ('train/' + x['id'] + '.jpg'), axis=1)\n\n\nbreeds = pd.Series(df['breed'])\nprint(\"total number of breeds to classify\",len(breeds.unique()))\n\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.preprocessing import image\n\ndef read_img(img_id, train_or_test, size):\n    \"\"\"Read and resize image.\n    # Arguments\n        img_id: string\n        train_or_test: string 'train' or 'test'.\n        size: resize the original image.\n    # Returns\n        Image as numpy array.\n    \"\"\"\n    path =  train_or_test + \"/\" + img_id + \".jpg\"\n    img = image.load_img(path, target_size=size)\n    return image.img_to_array(img)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.preprocessing import LabelEncoder\nlabel_enc = LabelEncoder()\nnp.random.seed(seed=seed)\nrnd = np.random.random(len(df))\ntrain_idx = rnd < 0.9\nvalid_idx = rnd >= 0.9\ny_train = label_enc.fit_transform(df[\"breed\"].values)\nytr = y_train[train_idx]\nyv = y_train[valid_idx]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from tqdm import tqdm\nfrom keras.applications import xception\n\nx_train = np.zeros((train_idx.sum(), im_size, im_size, 3), dtype='float32')\nx_valid = np.zeros((valid_idx.sum(), im_size, im_size, 3), dtype='float32')\ntrain_i = 0\nvalid_i = 0\nfor i, img_id in tqdm(enumerate(df['id'])):\n    img = read_img(img_id, '../input/dog-breed-identification/train', (im_size, im_size))\n    x = xception.preprocess_input(np.expand_dims(img.copy(), axis=0))\n    if train_idx[i]:\n        x_train[train_i] = x\n        train_i += 1\n    elif valid_idx[i]:\n        x_valid[valid_i] = x\n        valid_i += 1\nprint('Train Images shape: {} size: {:,}'.format(x_train.shape, x_train.size))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.preprocessing.image import ImageDataGenerator\n\ntrain_datagen = ImageDataGenerator(rotation_range=45,\n                                   width_shift_range=0.2,\n                                   height_shift_range=0.2,\n                                   shear_range=0.2,\n                                   zoom_range=0.25,\n                                   horizontal_flip=True,\n                                   fill_mode='nearest')\n\ntrain_generator = train_datagen.flow(x_train, \n                                     ytr, \n                                     batch_size=batch_size)\n\n\nvalid_datagen = ImageDataGenerator()\n\nvalid_generator = valid_datagen.flow(x_valid, \n                                     yv, \n                                     batch_size=batch_size)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.layers import GlobalAveragePooling2D, Dense, BatchNormalization, Dropout\nfrom keras.optimizers import Adam, SGD, RMSprop\nfrom keras.models import Model, Input\n\n# create the base pre-trained model\nbase_model = xception.Xception(weights='imagenet', include_top=False)\n# first: train only the top layers (which were randomly initialized)\n# i.e. freeze all convolutional Xception layers\nfor layer in base_model.layers:\n    layer.trainable = False\n\n# add a global spatial average pooling layer\nx = base_model.output\nx = BatchNormalization()(x)\nx = GlobalAveragePooling2D()(x)\n# let's add a fully-connected layer\nx = Dropout(0.5)(x)\nx = Dense(1024, activation='relu')(x)\nx = Dropout(0.5)(x)\n# and a logistic layer and set it to the number of breeds we want to classifiy, \npredictions = Dense(num_classes, activation='softmax')(x)\n\n# this is the model we will train\nmodel = Model(inputs=base_model.input, outputs=predictions)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import datetime\nfrom keras.callbacks import EarlyStopping, ModelCheckpoint\n\nepochs = 10\nlearning_rate = 0.001\n\n# checkpoints\nearly_stopping = EarlyStopping(monitor='val_accuracy', patience=5)\nSTAMP = \"{}_dog_breed_model\".format(datetime.date.today().strftime(\"%Y-%m-%d\"))\n\nbst_model_path = \"{}.h5\".format(STAMP)\nmodel_checkpoint = ModelCheckpoint(bst_model_path,\n                                   save_best_only=True,\n                                   save_weights_only=False,\n                                  verbose=1)\n\n\n\n# compile the model (should be done *after* setting layers to non-trainable)\noptimizer = RMSprop(lr=learning_rate, rho=0.9)\nmodel.compile(optimizer=optimizer,\n              loss='sparse_categorical_crossentropy',\n              metrics=[\"accuracy\"])\n\nhist = model.fit_generator(train_generator,\n                           steps_per_epoch=train_idx.sum() // batch_size,\n                           epochs=epochs, callbacks=[early_stopping, model_checkpoint],\n                           validation_data=valid_generator,\n                           validation_steps=valid_idx.sum() // batch_size)\n\n# serialize weights to HDF5\nmodel.save(bst_model_path)\nprint(\"Saved model to disk\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import matplotlib.pyplot as plt\nprint(hist.history.keys())\n# summarize history for accuracy\nplt.plot(hist.history['accuracy'])\nplt.plot(hist.history['val_accuracy'])\nplt.title('model accuracy')\nplt.ylabel('accuracy')\nplt.xlabel('epoch')\nplt.legend(['train', 'test'], loc='upper left')\nplt.show()\n# summarize history for loss\nplt.plot(hist.history['loss'])\nplt.plot(hist.history['val_loss'])\nplt.title('model loss')\nplt.ylabel('loss')\nplt.xlabel('epoch')\nplt.legend(['train', 'test'], loc='upper left')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.models import load_model\nfrom keras.preprocessing import image\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport os\n\n\ndef predict_from_image(img_path):\n\n    img = image.load_img(img_path, target_size=(299, 299))\n    img_tensor = image.img_to_array(img)                    # (height, width, channels)\n    img_tensor = np.expand_dims(img_tensor, axis=0)         # (1, height, width, channels), add a dimension because the model expects this shape: (batch_size, height, width, channels)\n    img_tensor /= 255.                                      # imshow expects values in the range [0, 1]\n    \n    pred = model.predict(img_tensor)\n    sorted_breeds_list = sorted(selected_breed_list)\n    predicted_class = sorted_breeds_list[np.argmax(pred)]\n    \n    plt.imshow(img_tensor[0])                           \n    plt.axis('off')\n    plt.show()\n\n    return predicted_class","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# image path\n!wget http://www.dogbreedslist.info/uploads/allimg/dog-pictures/Scottish-Deerhound-2.jpg\nimg_path = 'Scottish-Deerhound-2.jpg'    # dog\npredict_from_image(img_path)","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}