<commit_before>import numpy as np
import theano.tensor as T

from .base import Layer

from theano.tensor.signal import downsample


__all__ = [
    "MaxPool2DLayer",
    "FeaturePoolLayer",
    "FeatureWTALayer",
    "GlobalPoolLayer",
]


def pool_output_length(input_length, pool_length):
    '''Compute the output length of a pooling operator.

    Parameters
    ----------
    input_length 
    pool_length

    Returns
    -------
    output_length
        * None if either input is None
        * `input_length / pool_length` otherwise
    '''

    if input_length is None or pool_length is None:
        return None

    # Should this just be "input_length // pool_length" ?
    return int(np.floor(float(input_length) / pool_length))


class MaxPool2DLayer(Layer):
    def __init__(self, incoming, ds, ignore_border=False, **kwargs):
        super(MaxPool2DLayer, self).__init__(incoming, **kwargs)
        self.ds = ds  # a tuple
        self.ignore_border = ignore_border

    def get_output_shape_for(self, input_shape):
        output_shape = list(input_shape)  # copy / convert to mutable list

        if self.ignore_border:
            output_shape[2] = pool_output_length(input_shape[2], self.ds[0])
            output_shape[3] = pool_output_length(input_shape[3], self.ds[1])
        else:
            output_shape[2] = pool_output_length(input_shape[2], self.ds[0])
            output_shape[3] = pool_output_length(input_shape[3], self.ds[1])

        return tuple(output_shape)

    def get_output_for(self, input, *args, **kwargs):
        return downsample.max_pool_2d(input, self.ds, self.ignore_border)


# TODO: add reshape-based implementation to MaxPool2DLayer
# TODO: add MaxPool1DLayer<commit_msg>fixed rounding of pooling operator shape for border mode<commit_after>import numpy as np
import theano.tensor as T

from .base import Layer

from theano.tensor.signal import downsample


__all__ = [
    "MaxPool2DLayer",
    "FeaturePoolLayer",
    "FeatureWTALayer",
    "GlobalPoolLayer",
]


def pool_output_length(input_length, pool_length, ceil=False):
    '''Compute the output length of a pooling operator
    along a particular dimension.

    Parameters
    ----------
    input_length
    pool_length
        Shape of the input and pooling operator in the chosen dimension

    ceil : bool
        If True, size is rounded up.
        If False (default), size is rounded down.

    Returns
    -------
    output_length
        * None if either input is None
        * `input_length / pool_length` otherwise
    '''

    if input_length is None or pool_length is None:
        return None

    if ceil:
        rounder = np.ceil
    else:
        rounder = np.floor

    # Should this just be "input_length // pool_length" ?
    return int(rounder(float(input_length) / pool_length))


class MaxPool2DLayer(Layer):
    def __init__(self, incoming, ds, ignore_border=False, **kwargs):
        super(MaxPool2DLayer, self).__init__(incoming, **kwargs)
        self.ds = ds  # a tuple
        self.ignore_border = ignore_border

    def get_output_shape_for(self, input_shape):
        output_shape = list(input_shape)  # copy / convert to mutable list

        if self.ignore_border:
            output_shape[2] = pool_output_length(input_shape[2], self.ds[0])
            output_shape[3] = pool_output_length(input_shape[3], self.ds[1])
        else:
            output_shape[2] = pool_output_length(input_shape[2], self.ds[0],
                                                 ceil=True)
            output_shape[3] = pool_output_length(input_shape[3], self.ds[1],
                                                 ceil=True)

        return tuple(output_shape)

    def get_output_for(self, input, *args, **kwargs):
        return downsample.max_pool_2d(input, self.ds, self.ignore_border)


# TODO: add reshape-based implementation to MaxPool2DLayer
# TODO: add MaxPool1DLayer
{'fraction_non_alphanumeric': 0.09460496036819228, 'fraction_numerical': 0.009204806954743032, 'mean_word_length': 2.6975425330812857, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '774084', 'n_tokens_mistral': 1195, 'n_tokens_neox': 1154, 'n_words': 301}