├── .gitignore ├── images └── volcano.jpg ├── notebooks ├── utils.pyc └── utils.py ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.iml 3 | **/.ipynb_checkpoints -------------------------------------------------------------------------------- /images/volcano.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raghakot/demystifying-convnets/HEAD/images/volcano.jpg -------------------------------------------------------------------------------- /notebooks/utils.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raghakot/demystifying-convnets/HEAD/notebooks/utils.pyc -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Raghavendra Kotikalapudi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Demystifying ConvNets 2 | 3 | The goal is to maintain a collection of ipython notebooks to provide a less mathematical and more intuitive feel as to 4 | why convolutional nets work. 5 | 6 | There are several excellent blog posts explaining what convolutions are, how Conv, ReLU, MaxPooling operations 7 | transform the image. Soon afterwards we learn that a common design choice is to stack layers as 8 | [[Conv -> Relu] * N] -> Pool] * M (ignoring batch norm to keep the discussion simple). Why should it be this way? 9 | 10 | When I started learning about deep learning, I had a lot of questions on how they are applied in practice. For example: 11 | 12 | - When is it a good idea to use MaxPooling vs average pooling? 13 | - How to handle large image sizes, say 1000 X 1000? 14 | - What if the number of training examples are low? 15 | - Can we encode problem specific characteristics into convnet design? In medical image classification, 16 | the region of interest (ROI) is usually very small relative to the image. Can we design a conv net to somehow capture 17 | this knowledge a-priori? 18 | 19 | This repo is organized into notebooks. Each notebook is designed to provide a rough intuition on various aspects of 20 | designing conv nets. We will skip math and jump jump right into the code. 21 | 22 | 23 | # Notebooks 24 | 25 | 1. [Why should I use ReLU - A visual perspective](notebooks/exploring-convolutions.ipynb) 26 | 27 | More to come soon... 28 | 29 | 30 | # Contributing 31 | 32 | The goal is to democratize AI and make it easier for newcomers entering the field. 33 | If you have a unique perspective on some aspect of conv nets, please submit a PR. 34 | -------------------------------------------------------------------------------- /notebooks/utils.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import os 3 | import tempfile 4 | import math 5 | 6 | import numpy as np 7 | from skimage import io 8 | from keras.models import load_model 9 | 10 | 11 | def load_img(path, grayscale=False, target_size=None): 12 | """Utility function to load an image from disk. 13 | 14 | Args: 15 | path: The image file path. 16 | grayscale: True to convert to grayscale image (Default value = False) 17 | target_size: (w, h) to resize. (Default value = None) 18 | 19 | Returns: 20 | The loaded numpy image. 21 | """ 22 | img = io.imread(path, grayscale) 23 | img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 24 | if target_size: 25 | img = cv2.resize(img, (target_size[1], target_size[0])) 26 | return img 27 | 28 | 29 | def stitch_images(images, margin=5, cols=5): 30 | """Utility function to stitch images together with a `margin`. 31 | 32 | Args: 33 | images: The array of images (batch, height, width) to stitch. 34 | margin: The black border margin size between images (Default value = 5) 35 | cols: Max number of image cols. New row is created when number of images exceed the column size. 36 | (Default value = 5) 37 | 38 | Returns: 39 | A single numpy image array comprising of input images. 40 | """ 41 | n, w, h, = images.shape 42 | n_rows = max(1, int(math.ceil(n / cols))) 43 | n_cols = min(n, cols) 44 | 45 | out_w = n_cols * w + (n_cols - 1) * margin 46 | out_h = n_rows * h + (n_rows - 1) * margin 47 | stitched_images = np.zeros((out_h, out_w), dtype=images.dtype) 48 | 49 | for row in range(n_rows): 50 | for col in range(n_cols): 51 | img_idx = row * cols + col 52 | if img_idx >= n: 53 | break 54 | 55 | stitched_images[(h + margin) * row : (h + margin) * row + h, 56 | (w + margin) * col : (w + margin) * col + w] = images[img_idx] 57 | 58 | return stitched_images 59 | 60 | 61 | def apply_modifications(model): 62 | """Applies modifications to the model layers to create a new Graph. For example, simply changing 63 | `model.layers[idx].activation = new activation` does not change the graph. The entire graph needs to be updated 64 | with modified inbound and outbound tensors because of change in layer building function. 65 | 66 | Args: 67 | model: The `keras.models.Model` instance. 68 | 69 | Returns: 70 | The modified model with changes applied. Does not mutate the original `model`. 71 | """ 72 | # The strategy is to save the modified model and load it back. This is done because setting the activation 73 | # in a Keras layer doesnt actually change the graph. We have to iterate the entire graph and change the 74 | # layer inbound and outbound nodes with modified tensors. This is doubly complicated in Keras 2.x since 75 | # multiple inbound and outbound nodes are allowed with the Graph API. 76 | model_path = os.path.join(tempfile.gettempdir(), next(tempfile._get_candidate_names()) + '.h5') 77 | try: 78 | model.save(model_path) 79 | return load_model(model_path) 80 | finally: 81 | os.remove(model_path) 82 | from keras.activations import linear 83 | --------------------------------------------------------------------------------