Source code for carpedm.nn.conv

#
# Copyright (C) 2018 Neal Digre.
#
# This software may be modified and distributed under the terms
# of the MIT license. See the LICENSE file for details.

"""Convolutional layers and components.

"""

import tensorflow as tf

from carpedm.models.generic import TFModel
from carpedm.util import registry
from carpedm.nn import util

[docs]@registry.register_model class CNN(TFModel): """Modular convolutional neural network layer class.""" def __init__(self, kernel_size=((3, 3), (3, 3), (3, 3), (3, 3)), num_filters=(64, 96, 128, 160), padding='same', pool_size=((2, 2), (2, 2), (2, 2), (2, 2)), pool_stride=(2, 2, 2, 2), pool_every_n=1, pooling_fn=tf.layers.max_pooling2d, activation_fn=tf.nn.relu, *args, **kwargs): """Initializer. Args: num_classes (int): Number of output classes. kernel_size: (tuple of (int, int)): Convolution kernel size for each layer. num_filters (tuple of int): Number of filters for corresponding convolution layer from kernel_size. padding (str): Type of padding to use at each conv layer. pool_size (tuple of (int, int)): Pooling size. pool_stride (tuple of int): Pooling stride. pool_every_n (int or None): Perform pooling every n nn. pooling_fn: Pooling function, activation_fn: Activation function. *args: Unused arguments **kwargs: Unused arguments """ assert len(kernel_size) == len(num_filters), ( "kernel_size and num_filters must be equal length" ) assert len(pool_size) == len(pool_stride), ( "pool_size and pool_stride must be equal length" ) assert len(kernel_size) / pool_every_n == len(pool_size), ( "{} / {} != {}".format( len(kernel_size), pool_every_n, len(pool_size)) ) self._kernels = kernel_size self._filters = num_filters self._pad = padding self._pool_size = pool_size self._pool_stride = pool_stride self._pool_every_n = pool_every_n self._pool = pooling_fn self._activation = activation_fn super(CNN, self).__init__() @property def name(self): name = 'CNN_' p = 0 for i in range(len(self._kernels)): name += "c{}.{}-".format( 'x'.join(map(str, self._kernels[i])), self._filters[i]) if self._pool_every_n and i % self._pool_every_n == 0: name += "p{}.{}-".format( 'x'.join(map(str, self._pool_size[p])), self._pool_stride[p]) p += 1 return name[:-1] def _forward_pass(self, x, data_format, axes_order, is_training, reuse): x = tf.transpose(x, axes_order) if axes_order else x p = 0 for c in range(len(self._kernels)): x = tf.layers.conv2d( inputs=x, filters=self._filters[c], name='conv%d' % c, kernel_size=self._kernels[c], activation=self._activation, padding=self._pad, data_format=data_format) util.activation_summary(x) tf.logging.info( 'image after unit %s: %s', util.name_nice(x.op.name), x.get_shape()) if self._pool_every_n and c % self._pool_every_n == 0: x = self._pool( inputs=x, pool_size=self._pool_size[p], name='pool%d' % p, strides=self._pool_stride[p], data_format=data_format) tf.logging.info( 'image after unit %s: %s', util.name_nice(x.op.name), x.get_shape()) p += 1 return x