Source code for layers.dropout_layer

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import division
from __future__ import print_function

import numpy as np
from NumPyNet.exception import LayerError
from NumPyNet.utils import check_is_fitted
from NumPyNet.layers.base import BaseLayer

__author__ = ['Mattia Ceccarelli', 'Nico Curti']
__email__ = ['mattia.ceccarelli3@studio.unibo.it', 'nico.curti2@unibo.it']


[docs]class Dropout_layer(BaseLayer): ''' Dropout Layer Drop a random selection of input pixels. This helps avoid overfitting. Parameters ---------- prob : float, probability for each entry to be set to zero. It Ranges 0. to 1. input_shape : tuple (default=None) Shape of the input in the format (batch, w, h, c), None is used when the layer is part of a Network model. Example ------- >>> import os >>> >>> import pylab as plt >>> from PIL import Image >>> >>> np.random.seed(123) >>> >>> img_2_float = lambda im : ((im - im.min()) * (1./(im.max() - im.min()) * 1.)).astype(float) >>> float_2_img = lambda im : ((im - im.min()) * (1./(im.max() - im.min()) * 255.)).astype(np.uint8) >>> >>> filename = os.path.join(os.path.dirname(__file__), '..', '..', 'data', 'dog.jpg') >>> inpt = np.asarray(Image.open(filename), dtype=float) >>> inpt.setflags(write=1) >>> inpt = img_2_float(inpt) >>> >>> inpt = np.expand_dims(inpt, axis=0) >>> >>> prob = 0.1 >>> >>> layer = Dropout_layer(input_shape=inpt.shape, prob=prob) >>> >>> # FORWARD >>> >>> layer.forward(inpt) >>> forward_out = layer.output >>> >>> print(layer) >>> >>> # BACKWARD >>> >>> delta = np.ones(shape=inpt.shape, dtype=float) >>> layer.delta = np.ones(shape=layer.out_shape, dtype=float) >>> layer.backward(delta) >>> >>> # Visualitations >>> >>> fig, (ax1, ax2, ax3) = plt.subplots(nrows=1, ncols=3, figsize=(10, 5)) >>> fig.subplots_adjust(left=0.1, right=0.95, top=0.95, bottom=0.15) >>> >>> fig.suptitle('Dropout Layer Drop Probability : {}'.format(prob)) >>> # Shown first image of the batch >>> ax1.imshow(float_2_img(inpt[0])) >>> ax1.set_title('Original image') >>> ax1.axis('off') >>> >>> ax2.imshow(float_2_img(layer.output[0])) >>> ax2.set_title('Forward') >>> ax2.axis('off') >>> >>> ax3.imshow(float_2_img(delta[0])) >>> ax3.set_title('Backward') >>> ax3.axis('off') >>> >>> fig.tight_layout() >>> plt.show() .. image:: ../../../NumPyNet/images/dropout_prob10.png References ---------- - TODO ''' def __init__(self, prob, input_shape=None, **kwargs): if prob >= 0. and prob <= 1.: self.probability = prob else: raise ValueError('DropOut layer : parameter "prob" must be 0. < prob < 1., but it is {}'.format(prob)) if prob != 1.: self.scale = 1. / (1. - prob) else: self.scale = 1. # it doesn't matter anyway, since everything is zero self.rnd = None super(Dropout_layer, self).__init__(input_shape=input_shape) def __str__(self): batch, out_width, out_height, out_channels = self.out_shape return 'dropout p = {0:.2f} {1:4d} x{2:4d} x{3:4d} x{4:4d} -> {1:4d} x{2:4d} x{3:4d} x{4:4d}'.format( self.probability, batch, out_width, out_height, out_channels)
[docs] def forward(self, inpt): ''' Forward function of the Dropout layer It create a random mask for every input in the batch and set to zero the chosen values. Other pixels are scaled with the inverse of (1 - prob) Parameters ---------- inpt : array-like Input batch of images in format (batch, in_w, in_h, in _c) Returns ---------- self ''' self._check_dims(shape=self.out_shape, arr=inpt, func='Forward') self.rnd = np.random.uniform(low=0., high=1., size=self.out_shape) >= self.probability self.output = self.rnd * inpt * self.scale self.delta = np.zeros(shape=inpt.shape) return self
[docs] def backward(self, delta=None): ''' Backward function of the Dropout layer Given the same mask as the layer it backprogates delta only to those pixel which values has not been set to zero in the forward function Parameters ---------- delta : array-like delta array of shape (batch, w, h, c). Global delta to be backpropagated. Returns ---------- self ''' check_is_fitted(self, 'delta') self._check_dims(shape=self.out_shape, arr=delta, func='Backward') if delta is not None: self.delta = self.rnd * delta[:] * self.scale delta[:] = self.delta.copy() return self
if __name__ == '__main__': import os import pylab as plt from PIL import Image np.random.seed(123) img_2_float = lambda im : ((im - im.min()) * (1./(im.max() - im.min()) * 1.)).astype(float) float_2_img = lambda im : ((im - im.min()) * (1./(im.max() - im.min()) * 255.)).astype(np.uint8) filename = os.path.join(os.path.dirname(__file__), '..', '..', 'data', 'dog.jpg') inpt = np.asarray(Image.open(filename), dtype=float) inpt.setflags(write=1) inpt = img_2_float(inpt) inpt = np.expand_dims(inpt, axis=0) prob = 0.1 layer = Dropout_layer(input_shape=inpt.shape, prob=prob) # FORWARD layer.forward(inpt) forward_out = layer.output print(layer) # BACKWARD delta = np.ones(shape=inpt.shape, dtype=float) layer.delta = np.ones(shape=layer.out_shape, dtype=float) layer.backward(delta) # Visualitations fig, (ax1, ax2, ax3) = plt.subplots(nrows=1, ncols=3, figsize=(10, 5)) fig.subplots_adjust(left=0.1, right=0.95, top=0.95, bottom=0.15) fig.suptitle('Dropout Layer\nDrop Probability : {}'.format(prob)) # Shown first image of the batch ax1.imshow(float_2_img(inpt[0])) ax1.set_title('Original image') ax1.axis('off') ax2.imshow(float_2_img(layer.output[0])) ax2.set_title('Forward') ax2.axis('off') ax3.imshow(float_2_img(delta[0])) ax3.set_title('Backward') ax3.axis('off') fig.tight_layout() plt.show()