Пример #1
0
    def __init__(self, filter_shape, depth, stride, padding, activation, regularization=None, input_shape: tuple = None,
                 connected_to: Layer = None, weights: np.ndarray = None, bias: np.ndarray = None):
        super(Convolution2D).__init__()
        if input_shape is None and connected_to is None:
            raise ValueError('argument input_shape or connected_to must be not None')
        if input_shape:
            if len(input_shape) == 4:
                self.input_shape = input_shape
            else:
                raise ValueError('input_shape must have 4 dimensions.')
        if connected_to:
            if len(connected_to.output_shape) == 4:
                self.input_shape = connected_to.output_shape
            else:
                raise ValueError('output_shape of connected_to layer must have 4 dimensions.')

        if (self.input_shape[2] + 2 * padding - filter_shape[0]) % stride != 0:
            raise ValueError(
                'Incorrect size: ({} + 2*{} - {})%{} != 0'.format(self.input_shape[2], padding, filter_shape[0],
                                                                  stride))
        if (self.input_shape[3] + 2 * padding - filter_shape[1]) % stride != 0:
            raise ValueError(
                'Incorrect size: ({} + 2*{} - {})%{} != 0'.format(self.input_shape[3], padding, filter_shape[1],
                                                                  stride))

        if isinstance(activation, SoftMax):
            raise ValueError("Can't tuple {} as activation of Convolution2D layer.".format(activation))

        self.filter_shape = filter_shape  # [rows, columns]
        self.stride = stride
        self.padding = padding
        self.output_shape = (None, depth,
                             1 + (self.input_shape[2] + 2 * padding - filter_shape[0]) // stride,
                             1 + (self.input_shape[3] + 2 * padding - filter_shape[1]) // stride)
        self.activation = activation
        self.regularization = regularization

        if self.regularization is None:
            self.regularization = NoRegularization()

        weights_shape = (self.output_shape[1],
                         self.input_shape[1],
                         self.filter_shape[0],
                         self.filter_shape[1])

        if bias is None:
            self.bias = 1 / np.sqrt(self.input_shape[2] * self.input_shape[3] / 2) * np.random.rand(
                *(self.output_shape[1], 1))
        elif bias.shape == (self.output_shape[1], 1):
            self.bias = np.copy(bias)

        if weights is None:
            self.weights = 1 / np.sqrt(self.input_shape[1] * self.input_shape[2] * self.input_shape[3] / 2) * \
                           np.random.normal(loc=0,
                                            scale=1,
                                            size=weights_shape)
        elif weights.shape == weights_shape:
            self.weights = np.copy(weights)
Пример #2
0
    def __init__(self, window_shape, stride, input_shape: tuple = None, connected_to: Layer = None):
        super(MaxPool2D).__init__()
        if input_shape is None and connected_to is None:
            raise ValueError('argument input_shape or connected_to must be not None')
        if input_shape:
            if len(input_shape) == 4:
                self.input_shape = input_shape
            else:
                raise ValueError('input_shape must have 4 dimensions.')
        if connected_to:
            if len(connected_to.output_shape) == 4:
                self.input_shape = connected_to.output_shape
            else:
                raise ValueError('output_shape of connected_to layer must have 4 dimensions.')

        if (self.input_shape[2] - window_shape[0]) % stride != 0:
            raise ValueError('Incorrect size: ({} - {})%{} != 0'.format(self.input_shape[2], window_shape[0], stride))
        if (self.input_shape[3] - window_shape[1]) % stride != 0:
            raise ValueError('Incorrect size: ({} - {})%{} != 0'.format(self.input_shape[3], window_shape[1], stride))

        self.window_shape = window_shape
        self.stride = stride
        self.output_shape = (None, self.input_shape[1],
                             1 + (self.input_shape[2] - window_shape[0]) // stride,
                             1 + (self.input_shape[3] - window_shape[1]) // stride)
        self.regularization = NoRegularization()
Пример #3
0
 def __init__(self, activation, input_shape: tuple = None, connected_to: Layer = None):
     super(Activation).__init__()
     self.activation = activation
     self.regularization = NoRegularization()
     if input_shape:
         self.input_shape = input_shape
     elif connected_to:
         self.input_shape = connected_to.output_shape
     else:
         raise ValueError('argument input_shape or connected_to must be not None')
     self.output_shape = self.input_shape
Пример #4
0
    def __init__(self, betta=0, gamma=1, momentum=0.9, epsilon=1e-5, is_trainable=True, regularization=None,
                 input_shape: tuple = None, connected_to: Layer = None):
        super(BatchNormalization).__init__()
        self.mean = 0
        self.var = 1
        self.betta = betta
        self.gamma = gamma
        self.momentum = momentum
        self.epsilon = epsilon
        self.regularization = regularization
        self.is_trainable = is_trainable
        if input_shape:
            self.input_shape = input_shape
        elif connected_to:
            self.input_shape = connected_to.output_shape
        else:
            raise ValueError('argument input_shape or connected_to must be not None')
        self.output_shape = self.input_shape

        if self.regularization is None:
            self.regularization = NoRegularization()
Пример #5
0
    def __init__(self, outputs, activation: ActivationFunction = None, input_shape: tuple = None,
                 regularization=None, weights: np.ndarray = None, bias: np.ndarray = None, connected_to: Layer = None):
        super(FullyConnected).__init__()
        if input_shape is None and connected_to is None:
            raise ValueError('argument input_shape or connected_to must be not None')
        if input_shape:
            if len(input_shape) == 2:
                self.input_shape = input_shape
            else:
                raise ValueError('input_shape must have 2 dimensions.')
        if connected_to:
            if len(connected_to.output_shape) == 2:
                self.input_shape = connected_to.output_shape
            else:
                raise ValueError('output_shape of connected_to layer must have 2 dimensions.')
        self.output_shape = (None, outputs)
        self.activation = activation
        self.regularization = regularization
        self.bias = None
        self.weights = None

        if self.activation is None:
            self.activation = Linear()

        if self.regularization is None:
            self.regularization = NoRegularization()

        if bias is not None and bias.shape[0] == outputs:
            self.bias = bias
        else:
            multiplier = 1 / np.sqrt(self.input_shape[1] / 2)
            self.bias = multiplier * np.random.normal(loc=0, scale=0.1, size=outputs)

        if weights is not None and weights.shape == (self.input_shape[1], outputs):
            self.weights = np.copy(weights)
        else:
            multiplier = 1 / np.sqrt(self.input_shape[1] / 2)
            self.weights = multiplier * np.random.normal(loc=0, scale=1, size=(self.input_shape[1], outputs))
Пример #6
0
    def __init__(self, input_shape: tuple = None, connected_to: Layer = None):
        super(Flatten).__init__()
        self.regularization = NoRegularization()

        if input_shape:
            self.input_shape = input_shape
        elif connected_to:
            self.input_shape = connected_to.output_shape
        else:
            raise ValueError('argument input_shape or connected_to must be not None')

        size = 1
        for s in self.input_shape[1:]:
            size *= s
        self.output_shape = (None, size)
Пример #7
0
    def __init__(self, prob=0.5, input_shape: tuple = None, connected_to: Layer = None):
        super(Dropout).__init__()
        self.p = 0.5
        self.regularization = NoRegularization()

        if input_shape:
            self.input_shape = input_shape
        elif connected_to:
            self.input_shape = connected_to.output_shape
        else:
            raise ValueError('argument input_shape or connected_to must be not None')
        self.output_shape = self.input_shape

        if 0 < prob <= 1:
            self.p = prob
        else:
            raise ValueError('An expected value is between 0 and 1. Instead got {}'.format(prob))
Пример #8
0
class FullyConnected(Layer):

    def __str__(self):
        return "FullyConnected"

    def description(self):
        return "{}({} params)".format(self.activation, self.input_shape[1] *
                                      self.output_shape[1] + self.output_shape[1])

    def __init__(self, outputs, activation: ActivationFunction = None, input_shape: tuple = None,
                 regularization=None, weights: np.ndarray = None, bias: np.ndarray = None, connected_to: Layer = None):
        super(FullyConnected).__init__()
        if input_shape is None and connected_to is None:
            raise ValueError('argument input_shape or connected_to must be not None')
        if input_shape:
            if len(input_shape) == 2:
                self.input_shape = input_shape
            else:
                raise ValueError('input_shape must have 2 dimensions.')
        if connected_to:
            if len(connected_to.output_shape) == 2:
                self.input_shape = connected_to.output_shape
            else:
                raise ValueError('output_shape of connected_to layer must have 2 dimensions.')
        self.output_shape = (None, outputs)
        self.activation = activation
        self.regularization = regularization
        self.bias = None
        self.weights = None

        if self.activation is None:
            self.activation = Linear()

        if self.regularization is None:
            self.regularization = NoRegularization()

        if bias is not None and bias.shape[0] == outputs:
            self.bias = bias
        else:
            multiplier = 1 / np.sqrt(self.input_shape[1] / 2)
            self.bias = multiplier * np.random.normal(loc=0, scale=0.1, size=outputs)

        if weights is not None and weights.shape == (self.input_shape[1], outputs):
            self.weights = np.copy(weights)
        else:
            multiplier = 1 / np.sqrt(self.input_shape[1] / 2)
            self.weights = multiplier * np.random.normal(loc=0, scale=1, size=(self.input_shape[1], outputs))

    def pre_activate(self, input_signal, is_training=False):
        return np.dot(input_signal, self.weights) + self.bias

    def activate(self, pre_act, is_training=False):
        return self.activation.calculate(pre_act)

    def forward_pass(self, input_signal, is_training=False):
        return self.activate(self.pre_activate(input_signal, is_training), is_training)

    def backward_pass(self, cached_input_signal, cached_pre_act, backward_signal):
        delta = backward_signal * self.activation.derivative(cached_pre_act)
        next_backward_signal = np.dot(delta, self.weights.T)
        grad_ = np.sum(delta, axis=0)
        grad = np.dot(cached_input_signal.T, delta) + self.regularization.derivative(self.get_regularization_params())
        return next_backward_signal, grad_, grad

    def update(self, lr, step_grad_, step_grad):
        self.weights -= lr * step_grad
        self.bias -= lr * step_grad_

    def get_regularization_params(self):
        return self.weights

    def get_weights_count(self):
        return self.input_shape[1] * self.output_shape[1] + self.output_shape[1]
Пример #9
0
class Convolution2D(Layer):

    def __str__(self):
        return "Convolution2D"

    def description(self):
        return " {} {}x{} {}({} params)".format(self.output_shape[1], self.filter_shape[0],
                                                self.filter_shape[1],
                                                str(self.activation),
                                                self.get_weights_count())

    def __init__(self, filter_shape, depth, stride, padding, activation, regularization=None, input_shape: tuple = None,
                 connected_to: Layer = None, weights: np.ndarray = None, bias: np.ndarray = None):
        super(Convolution2D).__init__()
        if input_shape is None and connected_to is None:
            raise ValueError('argument input_shape or connected_to must be not None')
        if input_shape:
            if len(input_shape) == 4:
                self.input_shape = input_shape
            else:
                raise ValueError('input_shape must have 4 dimensions.')
        if connected_to:
            if len(connected_to.output_shape) == 4:
                self.input_shape = connected_to.output_shape
            else:
                raise ValueError('output_shape of connected_to layer must have 4 dimensions.')

        if (self.input_shape[2] + 2 * padding - filter_shape[0]) % stride != 0:
            raise ValueError(
                'Incorrect size: ({} + 2*{} - {})%{} != 0'.format(self.input_shape[2], padding, filter_shape[0],
                                                                  stride))
        if (self.input_shape[3] + 2 * padding - filter_shape[1]) % stride != 0:
            raise ValueError(
                'Incorrect size: ({} + 2*{} - {})%{} != 0'.format(self.input_shape[3], padding, filter_shape[1],
                                                                  stride))

        if isinstance(activation, SoftMax):
            raise ValueError("Can't tuple {} as activation of Convolution2D layer.".format(activation))

        self.filter_shape = filter_shape  # [rows, columns]
        self.stride = stride
        self.padding = padding
        self.output_shape = (None, depth,
                             1 + (self.input_shape[2] + 2 * padding - filter_shape[0]) // stride,
                             1 + (self.input_shape[3] + 2 * padding - filter_shape[1]) // stride)
        self.activation = activation
        self.regularization = regularization

        if self.regularization is None:
            self.regularization = NoRegularization()

        weights_shape = (self.output_shape[1],
                         self.input_shape[1],
                         self.filter_shape[0],
                         self.filter_shape[1])

        if bias is None:
            self.bias = 1 / np.sqrt(self.input_shape[2] * self.input_shape[3] / 2) * np.random.rand(
                *(self.output_shape[1], 1))
        elif bias.shape == (self.output_shape[1], 1):
            self.bias = np.copy(bias)

        if weights is None:
            self.weights = 1 / np.sqrt(self.input_shape[1] * self.input_shape[2] * self.input_shape[3] / 2) * \
                           np.random.normal(loc=0,
                                            scale=1,
                                            size=weights_shape)
        elif weights.shape == weights_shape:
            self.weights = np.copy(weights)

    def pre_activate(self, input_signal, is_training=False):
        imscol = self.ims2col(input_signal, self.output_shape, self.filter_shape, self.stride, self.padding)
        wscol = self.weights.reshape(self.weights.shape[0], -1)
        d_prod = []
        for i in range(len(input_signal)):
            d_prod.append(np.dot(wscol, imscol[i]) + self.bias)
        d_prod = np.array(d_prod)
        d_prod = d_prod.reshape([len(d_prod), self.output_shape[1], self.output_shape[2], self.output_shape[3]])
        return d_prod

    def activate(self, pre_act, is_training=False):
        return self.activation.calculate(pre_act)

    def forward_pass(self, input_signal, is_training=False):
        return self.activate(self.pre_activate(input_signal, is_training), is_training)

    def backward_pass(self, cached_input_signal, cached_pre_act, backward_signal):
        delta = backward_signal * self.activation.derivative(cached_pre_act[0])
        dcol = delta.reshape([len(delta), self.output_shape[1], self.output_shape[2] * self.output_shape[3]])
        wscol = self.weights.reshape(self.weights.shape[0], -1)
        next_backward_signal_cols = []
        for i in range(len(backward_signal)):
            next_backward_signal_cols.append(np.dot(wscol.T, dcol[i]))
        next_backward_signal_cols = np.array(next_backward_signal_cols)
        next_backward_signal = self.cols2im(next_backward_signal_cols, self.input_shape, self.output_shape,
                                            self.filter_shape,
                                            self.stride,
                                            self.padding)

        imscols = self.ims2col(cached_input_signal, self.output_shape, self.filter_shape, self.stride, self.padding)
        dcols = []
        for d in delta:
            dcols.append(d.reshape(d.shape[0], -1))
        dcols = np.array(dcols)
        filter_shape = self.filter_shape
        w_grad_shape = (self.output_shape[1], self.input_shape[1] * filter_shape[0] * filter_shape[1])
        grad = np.zeros(shape=(w_grad_shape))
        grad_ = np.zeros(shape=(self.output_shape[1], 1))
        for k in range(dcols.shape[0]):
            grad += np.dot(dcols[k], imscols[k].T)
            grad_ += np.sum(dcols[k], axis=1, keepdims=True)
        grad = grad.reshape([self.output_shape[1], self.input_shape[1], filter_shape[0], filter_shape[1]])
        grad += self.regularization.derivative(self.get_regularization_params())

        return next_backward_signal, grad_, grad

    def update(self, lr, step_grad_, step_grad):
        self.weights -= lr * step_grad
        self.bias -= lr * step_grad_

    def get_regularization_params(self):
        return self.weights

    def pad_ims(self, im_arr, padding):
        return np.lib.pad(im_arr, ((0, 0), (0, 0), (padding, padding), (padding, padding)), 'constant',
                          constant_values=0)

    def im2col(self, im, output_shape, filter_shape, s):
        i_c, i_h, i_w = im.shape
        f_h, f_w = filter_shape
        o_h, o_w = output_shape[2:]

        col = np.zeros(shape=(i_c * f_h * f_w, o_h * o_w))
        for h in range(0, o_h, s):
            r = h * o_h
            for w in range(0, o_w, s):
                col[:, r + w] = im[:, h:h + f_h, w:w + f_w].flat
                # col[:, r + w] = im[:, h:h + f_h, w:w + f_w].flatten()
        return col

    def ims2col(self, ims, output_shape, filter_shape, stride, padding):
        p_ims = self.pad_ims(ims, padding)
        cols = np.empty(
            shape=(ims.shape[0], ims.shape[1] * filter_shape[0] * filter_shape[1], output_shape[2] * output_shape[3]))
        for i in range(ims.shape[0]):
            cols[i] = self.im2col(p_ims[i, :, :, :], output_shape, filter_shape, stride)
        return cols

    def col2im(self, col, input_shape, output_shape, filter_shape, s, p):
        f_h, f_w = filter_shape
        i_c, i_h, i_w = input_shape[1:]
        o_c, o_h, o_w = output_shape[1:]
        i_h += 2 * p
        i_w += 2 * p
        im = np.zeros(shape=(i_c, i_h, i_w))
        rs = [i for i in range(0, input_shape[2], s)]
        cs = [i for i in range(0, input_shape[3], s)]
        for k in range(col.shape[1]):
            i = k // o_h
            j = k % o_w
            im[:, rs[i]:rs[i] + f_h, cs[j]:cs[j] + f_w] += col[:, k].reshape([i_c, f_h, f_w])
        return im

    def cols2im(self, cols, input_shape, output_shape, filter_shape, stride, padding):
        ims = np.empty((cols.shape[0], input_shape[1], input_shape[2] + 2 * padding, input_shape[3] + 2 * padding))
        for i in range(cols.shape[0]):
            ims[i] = self.col2im(cols[i], input_shape, output_shape, filter_shape, stride, padding)
        if padding == 0:
            return ims
        else:
            return ims[:, :, padding:-padding, padding:-padding]

    def get_weights_count(self):
        return self.weights.shape[0] * self.weights.shape[1] * self.weights.shape[2] * self.weights.shape[3] + \
               self.bias.shape[0]
Пример #10
0
class BatchNormalization(Layer):

    def __str__(self):
        return "BatchNormalization"

    def description(self):
        return "{}".format("({} params)".format(2 * np.prod(self.input_shape[1:])) if self.is_trainable else '')

    def __init__(self, betta=0, gamma=1, momentum=0.9, epsilon=1e-5, is_trainable=True, regularization=None,
                 input_shape: tuple = None, connected_to: Layer = None):
        super(BatchNormalization).__init__()
        self.mean = 0
        self.var = 1
        self.betta = betta
        self.gamma = gamma
        self.momentum = momentum
        self.epsilon = epsilon
        self.regularization = regularization
        self.is_trainable = is_trainable
        if input_shape:
            self.input_shape = input_shape
        elif connected_to:
            self.input_shape = connected_to.output_shape
        else:
            raise ValueError('argument input_shape or connected_to must be not None')
        self.output_shape = self.input_shape

        if self.regularization is None:
            self.regularization = NoRegularization()

    def pre_activate(self, input_signal, is_training=False):
        if is_training:
            mean_ = np.mean(input_signal, axis=0)
            x_m = input_signal - mean_
            var_ = np.var(input_signal, axis=0)

            self.mean = self.momentum * self.mean + (1 - self.momentum) * mean_
            self.var = self.momentum * self.var + (1 - self.momentum) * var_

            return input_signal, x_m, mean_, var_
        else:
            return input_signal

    def activate(self, pre_act, is_training=False):
        if is_training:
            input_signal, x_m, mean, var = pre_act
            return self.gamma * x_m / np.sqrt(var + self.epsilon) + self.betta
        else:
            return self.gamma * (pre_act - self.mean) / np.sqrt(self.var + self.epsilon) + self.betta

    def forward_pass(self, input_signal, is_training=False):
        return self.activate(self.pre_activate(input_signal, is_training), is_training)

    def backward_pass(self, cached_input_signal, cached_pre_act, backward_signal):
        input_signal, x_m, mean, var = cached_pre_act

        delta = backward_signal

        d_x_hat = self.gamma * delta
        d_var = -0.5 * ((var + self.epsilon) ** 1.5) * np.sum(d_x_hat * x_m, axis=0)
        d_mean = -np.sum(d_x_hat, axis=0) / np.sqrt(var + self.epsilon) - 2 * d_var * np.mean(x_m, axis=0)
        next_backward_signal = d_x_hat / np.sqrt(var + self.epsilon) + 2 / len(
            input_signal) * d_var * x_m + d_mean / len(input_signal)
        grad_ = np.sum(delta, axis=0)
        grad = np.sum(delta * x_m / np.sqrt(var + self.epsilon), axis=0) + self.regularization.derivative(
            self.get_regularization_params())

        return next_backward_signal, grad_, grad

    def update(self, lr, step_grad_, step_grad):
        if self.is_trainable:
            self.gamma -= lr * step_grad
            self.betta -= lr * step_grad_

    def get_regularization_params(self):
        return self.gamma

    def get_weights_count(self):
        return 2 * np.prod(self.input_shape[1:]) if self.is_trainable else 0