def initialize(self, input_size, num_classes, train_method) -> tuple:
    assert (np.size(input_size) == 3), 'invalid input size: 3-tuple required for convolution layer'
    (c_in, h_in, w_in) = input_size
    (f, c_f, h_f, w_f) = self.filter_shape
    assert (c_in == c_f), 'input channel dimension ({}) not compatible with filter channel dimension ({})'.format(c_in, c_f)
    assert ((((h_in - h_f) + (2 * self.padding)) % self.stride) == 0), 'filter width ({}) not compatible with input width ({})'.format(h_f, h_in)
    assert ((((w_in - w_f) + (2 * self.padding)) % self.stride) == 0), 'filter height ({}) not compatible with input height ({})'.format(h_f, h_in)
    self.h_out = ((((h_in - h_f) + (2 * self.padding)) // self.stride) + 1)
    self.w_out = ((((w_in - w_f) + (2 * self.padding)) // self.stride) + 1)
    if (self.weight_initializer is None):
        sqrt_fan_in = np.sqrt(((c_in * h_in) * w_in))
        self.W = np.random.uniform(low=((- 1) / sqrt_fan_in), high=(1 / sqrt_fan_in), size=self.filter_shape)
    else:
        self.W = self.weight_initializer.init(dim=(f, c_f, h_f, w_f))
    if (self.fb_weight_initializer is None):
        sqrt_fan_out = np.sqrt(((f * self.h_out) * self.w_out))
        self.B = np.random.uniform(low=((- 1) / sqrt_fan_out), high=(1 / sqrt_fan_out), size=(num_classes, ((f * self.h_out) * self.w_out)))
    else:
        self.B = self.fb_weight_initializer.init(dim=(num_classes, ((f * self.h_out) * self.w_out)))
    self.b = np.zeros(f)
    return (f, self.h_out, self.w_out)
def initialize(self, input_size, num_classes, train_method) -> tuple:
    assert (np.size(input_size) == 3), 'invalid input size: 3-tuple required for convolution layer'
    (c_in, h_in, w_in) = input_size
    (f, c_f, h_f, w_f) = self.filter_shape
    assert (c_in == c_f), 'input channel dimension ({}) not compatible with filter channel dimension ({})'.format(c_in, c_f)
    assert ((((h_in - h_f) + (2 * self.padding)) % self.stride) == 0), 'filter width ({}) not compatible with input width ({})'.format(h_f, h_in)
    assert ((((w_in - w_f) + (2 * self.padding)) % self.stride) == 0), 'filter height ({}) not compatible with input height ({})'.format(h_f, h_in)
    self.h_out = ((((h_in - h_f) + (2 * self.padding)) // self.stride) + 1)
    self.w_out = ((((w_in - w_f) + (2 * self.padding)) // self.stride) + 1)
    if (self.weight_initializer is None):
        sqrt_fan_in = np.sqrt(((c_in * h_in) * w_in))
        self.W = np.random.uniform(low=((- 1) / sqrt_fan_in), high=(1 / sqrt_fan_in), size=self.filter_shape)
    else:
        self.W = self.weight_initializer.init(dim=(f, c_f, h_f, w_f))
    if (self.fb_weight_initializer is None):
        sqrt_fan_out = np.sqrt(((f * self.h_out) * self.w_out))
        self.B = np.random.uniform(low=((- 1) / sqrt_fan_out), high=(1 / sqrt_fan_out), size=(num_classes, ((f * self.h_out) * self.w_out)))
    else:
        self.B = self.fb_weight_initializer.init(dim=(num_classes, ((f * self.h_out) * self.w_out)))
    self.b = np.zeros(f)
    return (f, self.h_out, self.w_out)