{"cells":[{"metadata":{},"cell_type":"markdown","source":"ref Deep learning with Python\n- data augmentation\n- using pre-trained convolution net\n- to do: feature extraction, fine tuning, from p170"},{"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 in \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 \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os, shutil\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"original_dataset_dir = r'/kaggle/input/train/train/'","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"base_dir = r'/kaggle/cats_and_dogs_small'\nif not os.path.exists(base_dir):\n    os.mkdir(base_dir)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_dir = os.path.join(base_dir, 'train')\nos.mkdir(train_dir)\nvalidation_dir = os.path.join(base_dir, 'validation')\nos.mkdir(validation_dir)\ntest_dir = os.path.join(base_dir, 'test')\nos.mkdir(test_dir)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Directory with training cat pictures\ntrain_cats_dir = os.path.join(train_dir, 'cats')\nos.mkdir(train_cats_dir)\n# Directory with training dog pictures\ntrain_dogs_dir = os.path.join(train_dir, 'dogs')\nos.mkdir(train_dogs_dir)\n# Directory with validation cat pictures\nvalidation_cats_dir = os.path.join(validation_dir, 'cats')\nos.mkdir(validation_cats_dir)\nvalidation_dogs_dir = os.path.join(validation_dir, 'dogs')\nos.mkdir(validation_dogs_dir)\ntest_cats_dir = os.path.join(test_dir, 'cats')\nos.mkdir(test_cats_dir)\ntest_dogs_dir = os.path.join(test_dir, 'dogs')\nos.mkdir(test_dogs_dir)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fnames = ['cat.{}.jpg'.format(i) for i in range(1000)]\nfor fname in fnames:\n    src = os.path.join(original_dataset_dir, fname)\n    dst = os.path.join(train_cats_dir, fname)\n    shutil.copyfile(src, dst)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fnames = ['cat.{}.jpg'.format(i) for i in range(1000, 1500)]\nfor fname in fnames:\n    src = os.path.join(original_dataset_dir, fname)\n    dst = os.path.join(validation_cats_dir, fname)\n    shutil.copyfile(src, dst)\nfnames = ['cat.{}.jpg'.format(i) for i in range(1500, 2000)]\nfor fname in fnames:\n    src = os.path.join(original_dataset_dir, fname)\n    dst = os.path.join(test_cats_dir, fname)\n    shutil.copyfile(src, dst)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fnames = ['dog.{}.jpg'.format(i) for i in range(1000)]\nfor fname in fnames:\n    src = os.path.join(original_dataset_dir, fname)\n    dst = os.path.join(train_dogs_dir, fname)\n    shutil.copyfile(src, dst)\nfnames = ['dog.{}.jpg'.format(i) for i in range(1000, 1500)]\nfor fname in fnames:\n    src = os.path.join(original_dataset_dir, fname)\n    dst = os.path.join(validation_dogs_dir, fname)\n    shutil.copyfile(src, dst)\nfnames = ['dog.{}.jpg'.format(i) for i in range(1500, 2000)]\nfor fname in fnames:\n    src = os.path.join(original_dataset_dir, fname)\n    dst = os.path.join(test_dogs_dir, fname)\n    shutil.copyfile(src, dst)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# check\nprint('total training cat images:', len(os.listdir(train_cats_dir)))\nprint('total training dog images:', len(os.listdir(train_dogs_dir)))\nprint('total validation cat images:', len(os.listdir(validation_cats_dir)))\nprint('total validation dog images:', len(os.listdir(validation_dogs_dir)))\nprint('total test cat images:', len(os.listdir(test_cats_dir)))\nprint('total test dog images:', len(os.listdir(test_dogs_dir)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras import layers\nfrom keras import models\nmodel = models.Sequential()\nmodel.add(layers.Conv2D(32, (3, 3), activation='relu',\ninput_shape=(150, 150, 3)))\nmodel.add(layers.MaxPooling2D((2, 2)))\nmodel.add(layers.Conv2D(64, (3, 3), activation='relu'))\nmodel.add(layers.MaxPooling2D((2, 2)))\nmodel.add(layers.Conv2D(128, (3, 3), activation='relu'))\nmodel.add(layers.MaxPooling2D((2, 2)))\nmodel.add(layers.Conv2D(128, (3, 3), activation='relu'))\nmodel.add(layers.MaxPooling2D((2, 2)))\nmodel.add(layers.Flatten())\nmodel.add(layers.Dense(512, activation='relu'))\nmodel.add(layers.Dense(1, activation='sigmoid'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras import optimizers\nmodel.compile(loss='binary_crossentropy',\n    optimizer=optimizers.RMSprop(lr=1e-4),\n    metrics=['acc'])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"1 Read the picture files.  \n2 Decode the JPEG content to RGB grids of pixels.  \n3 Convert these into floating-point tensors.  \n4 Rescale the pixel values (between 0 and 255) to the [0, 1] interval (as you know, neural networks prefer to deal with small input values).  "},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.preprocessing.image import ImageDataGenerator\ntrain_datagen = ImageDataGenerator(rescale=1./255)\ntest_datagen = ImageDataGenerator(rescale=1./255)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_generator = train_datagen.flow_from_directory(\n        train_dir,\n        target_size=(150, 150),\n        batch_size=20,\n        class_mode='binary')\nvalidation_generator = test_datagen.flow_from_directory(\n        validation_dir,\n        target_size=(150, 150),\n        batch_size=20,\n        class_mode='binary')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for data_batch, labels_batch in train_generator:\n    print('data batch shape:', data_batch.shape)\n    print('labels batch shape:', labels_batch.shape)\n    break","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history = model.fit_generator(\n        train_generator,\n        steps_per_epoch = 100,\n        epochs = 30,\n        validation_data = validation_generator,\n        validation_steps = 50)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.save('cats_and_dogs_small_1.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import matplotlib.pyplot as plt\nacc = history.history['acc']\nval_acc = history.history['val_acc']\nloss = history.history['loss']\nval_loss = history.history['val_loss']\nepochs = range(1, len(acc) + 1)\nplt.plot(epochs, acc, 'bo', label='Training acc')\nplt.plot(epochs, val_acc, 'b', label='Validation acc')\nplt.title('Training and validation accuracy')\nplt.legend()\nplt.figure()\nplt.plot(epochs, loss, 'bo', label='Training loss')\nplt.plot(epochs, val_loss, 'b', label='Validation loss')\nplt.title('Training and validation loss')\nplt.legend()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Using data augmentation"},{"metadata":{"trusted":true},"cell_type":"code","source":"datagen = ImageDataGenerator(   \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    fill_mode='nearest')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"- rotation_range  is  a  value  in  degrees  (0–180),  a  range  within  which  to  randomly rotate pictures.  \n- width_shift  and  height_shift  are  ranges  (as  a  fraction  of  total  width  or height) within which to randomly translate pictures vertically or horizontally.  \n- shear_range is for randomly applying shearing transformations.  \n-  zoom_range is for randomly zooming inside pictures.  \n-  horizontal_flip is for randomly flipping half the images horizontally—relevant  when  there  are  no  assumptions  of  horizontal  asymmetry  (for  example, real-world pictures).  \n- fill_mode  is  the  strategy  used  for  filling  in  newly  created  pixels,  which  can appear after a rotation or a width/height shift.  "},{"metadata":{"trusted":true},"cell_type":"code","source":"# look at augmented image\nfrom keras.preprocessing import image\nfnames = [os.path.join(train_cats_dir, fname) for\n    fname in os.listdir(train_cats_dir)]\nimg_path = fnames[3]\nimg = image.load_img(img_path, target_size=(150, 150))  # read and resize\nx = image.img_to_array(img)  # covert to np array\nx = x.reshape((1,) + x.shape)  # reshape to (1, 150, 150, 3)\ni = 0\nfor batch in datagen.flow(x, batch_size=1):\n    plt.figure(i)\n    imgplot = plt.imshow(image.array_to_img(batch[0]))\n    i += 1\n    if i % 4 == 0:\n        break\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# add dropout layer to prevent overfitting\nmodel = models.Sequential()\nmodel.add(layers.Conv2D(32, (3, 3), activation='relu',\n                input_shape=(150, 150, 3)))\nmodel.add(layers.MaxPooling2D((2, 2)))\nmodel.add(layers.Conv2D(64, (3, 3), activation='relu'))\nmodel.add(layers.MaxPooling2D((2, 2)))\nmodel.add(layers.Conv2D(128, (3, 3), activation='relu'))\nmodel.add(layers.MaxPooling2D((2, 2)))\nmodel.add(layers.Conv2D(128, (3, 3), activation='relu'))\nmodel.add(layers.MaxPooling2D((2, 2)))\nmodel.add(layers.Flatten())\nmodel.add(layers.Dropout(0.5))\nmodel.add(layers.Dense(512, activation='relu'))\nmodel.add(layers.Dense(1, activation='sigmoid'))\nmodel.compile(loss='binary_crossentropy',\n                optimizer=optimizers.RMSprop(lr=1e-4),\n                metrics=['acc'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_datagen = ImageDataGenerator(\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# validation data shouldn't be augmented\ntest_datagen = ImageDataGenerator(rescale=1./255)  \ntrain_generator = train_datagen.flow_from_directory(\n    train_dir,\n    target_size=(150, 150),  # resize to 150*150\n    batch_size=32,\n    # used binary_crossentropy loss, need binary labels\n    class_mode='binary')  \nvalidation_generator = test_datagen.flow_from_directory(\n    validation_dir,\n    target_size=(150, 150),\n    batch_size=32,\n    class_mode='binary')\nhistory = model.fit_generator(\n    train_generator,\n    steps_per_epoch=100,  \n    epochs=100,  \n    validation_data=validation_generator,\n    validation_steps=50)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.save('cats_and_dogs_small_2.h5')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"acc = history.history['acc']\nval_acc = history.history['val_acc']\nloss = history.history['loss']\nval_loss = history.history['val_loss']\nepochs = range(1, len(acc) + 1)\nplt.plot(epochs, acc, 'bo', label='Training acc')\nplt.plot(epochs, val_acc, 'b', label='Validation acc')\nplt.title('Training and validation accuracy')\nplt.legend()\nplt.figure()\nplt.plot(epochs, loss, 'bo', label='Training loss')\nplt.plot(epochs, val_loss, 'b', label='Validation loss')\nplt.title('Training and validation loss')\nplt.legend()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Using pretrained convnet\n## feature extraction"},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.applications import VGG16\nconv_base = VGG(weights = 'imagenet',\n               include_top = False,\n               input_shape = (150,150,3))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"- `weights` specifies the weight checkpoint from which to initialize the model.  \n- `include_top` refers to including (or not) the densely connected classifier on top of the network. By default, this densely connected classifier corresponds to the 1,000 classes from ImageNet. Because you intend to use your own densely connected  classifier  (with  only  two  classes:  cat  and  dog),  you  don’t  need  to include it.  \n- `input_shape` is the shape of the image tensors that you’ll feed to the network. This argument is purely optional: if you don’t pass it, the network will be able to process inputs of any size."},{"metadata":{"trusted":true},"cell_type":"code","source":"conv_base.summary()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Fast feature extraction without data augmentation"},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras.preprocessing.image import ImageDataGenerator\nbase_dir = '/Users/fchollet/Downloads/cats_and_dogs_small'\ntrain_dir = os.path.join(base_dir, 'train')\nvalidation_dir = os.path.join(base_dir, 'validation')\ntest_dir = os.path.join(base_dir, 'test')\ndatagen = ImageDataGenerator(rescale=1./255)\nbatch_size = 20\n\ndef extract_features(directory, sample_count):\nfeatures = np.zeros(shape=(sample_count, 4, 4, 512))\nlabels = np.zeros(shape=(sample_count))\ngenerator = datagen.flow_from_directory(\n    directory,\n    target_size=(150, 150),\n    batch_size=batch_size,\n    class_mode='binary')\ni = 0\nfor inputs_batch, labels_batch in generator:\n    features_batch = conv_base.predict(inputs_batch)\n    features[i * batch_size : (i + 1) * batch_size] = features_batch\n    labels[i * batch_size : (i + 1) * batch_size] = labels_batch\n    i += 1\n    if i * batch_size >= sample_count:\n        break\nreturn features, labels\n\ntrain_features, train_labels = extract_features(train_dir, 2000)\nvalidation_features, validation_labels = extract_features(validation_dir, 1000)\ntest_features, test_labels = extract_features(test_dir, 1000)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"cont p170, including feature extraction and find-tunning"},{"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":1}