Esempio n. 1
0
    def __init__(self, input_width, input_height, channel_number,
                 learning_rate, cost_function):
        self.cost_function = cost_function
        self.predict_output_list = []
        self.conv1 = ConvLayer(input_width, input_height, channel_number, 3, 3,
                               16, 1, 1, ReluActivator(), learning_rate)

        self.conv3 = MaxPoolingLayer(input_width, input_height, 16, 3, 3, 1, 2)

        self.conv4 = ConvLayer(input_width // 2, input_height // 2, 16, 3, 3,
                               32, 1, 1, ReluActivator(), learning_rate)

        self.conv5 = MaxPoolingLayer(input_width // 2, input_height // 2, 32,
                                     3, 3, 1, 2)

        self.conv6 = ConvLayer(input_width // 4, input_height // 4, 32, 3, 3,
                               32, 1, 1, ReluActivator(), learning_rate)

        self.conv8 = UpsamplingLayer(input_width // 4, input_height // 4, 32)

        self.conv9 = ConvLayer(input_width // 2, input_height // 2, 32, 3, 3,
                               16, 1, 1, ReluActivator(), learning_rate)

        self.conv10 = UpsamplingLayer(input_width // 2, input_height // 2, 16)

        self.conv12 = ConvLayer(input_width, input_height, 16, 3, 3, 2, 1, 1,
                                TanhActivator(), learning_rate)
Esempio n. 2
0
class CryptoNet_fivelayer(Module):
    def __init__(self, in_dim, n_class):
        super(CryptoNet_fivelayer, self).__init__()

        self.conv = ConvLayer(in_dim, 5, 5,5, zero_padding=1, stride=2, method='SAME')
        self.sq1 = Activators.Square()
        self.fc1 = FullyConnect(845, 100)
        self.sq2 = Activators.Square()
        self.fc2 = FullyConnect(100, n_class)
        self.logsoftmax = Logsoftmax()

    def forward(self, x):
        in_size = x.shape[0]
        out_1 = self.sq1.forward(self.conv.forward(x))
        self.conv_out_shape = out_1.shape
        # print('out1shape: ',self.conv_out_shape)
        out_1 = out_1.reshape(in_size, -1) # 将输出拉成一行
        out_2 = self.sq2.forward(self.fc1.forward(out_1))
        out_3 = self.fc2.forward(out_2)
        
        out_logsoftmax = self.logsoftmax.forward(out_3)

        return out_logsoftmax
    
    def backward(self, dy):
        dy_logsoftmax = self.logsoftmax.gradient(dy)
        dy_f3 = self.fc2.gradient(dy_logsoftmax)
        dy_f2 = self.fc1.gradient(self.sq2.gradient(dy_f3))
        dy_f2 = dy_f2.reshape(self.conv_out_shape)
        self.conv.gradient(self.sq1.gradient(dy_f2))
Esempio n. 3
0
    def __init__(self, in_dim, n_class):
        super(CryptoNet_fivelayer, self).__init__()

        self.conv = ConvLayer(in_dim, 5, 5,5, zero_padding=1, stride=2, method='SAME')
        self.sq1 = Activators.Square()
        self.fc1 = FullyConnect(845, 100)
        self.sq2 = Activators.Square()
        self.fc2 = FullyConnect(100, n_class)
        self.logsoftmax = Logsoftmax()
Esempio n. 4
0
    def __init__(self, in_dim, n_class):
        super(Minionn_fivelayer, self).__init__()

        self.conv = ConvLayer(in_dim,
                              5,
                              5,
                              5,
                              zero_padding=2,
                              stride=2,
                              method='SAME')
        self.relu1 = Activators.ReLU()
        self.fc1 = FullyConnect(980, 100)
        self.relu2 = Activators.ReLU()
        self.fc2 = FullyConnect(100, n_class)
        self.logsoftmax = Logsoftmax()
Esempio n. 5
0
def Conv(filters,
         kernel_size,
         input_shape,
         strides=(1, 1),
         padding="VALID",
         activation='none'):
    return ConvLayer(filters, kernel_size, input_shape, strides, padding,
                     activation)
Esempio n. 6
0
    def __init__(self, input_width, input_height, channel_number,
                 learning_rate, cost_function):
        self.cost_function = cost_function
        self.predict_output_list = []
        self.conv1 = ConvLayer(input_width, input_height, channel_number, 3, 3,
                               64, 1, 1, ReluActivator(), learning_rate)

        # self.conv2 = ConvLayer(input_width, input_height, 64,
        #                   3, 3, 64, input_width // 2 + 1, 2, ReluActivator(), learning_rate)

        # self.conv2 = ConvLayer(input_width, input_height, 8,
        #                   3, 3, 8, 1, 1, ReluActivator(), learning_rate)

        self.conv3 = MaxPoolingLayer(input_width, input_height, 64, 3, 3, 1, 2)

        # self.conv4 = ConvLayer(input_width, input_height, 16,
        #                   3, 3, 16, 1, 1, ReluActivator(), learning_rate)

        self.conv5 = ConvLayer(input_width // 2, input_height // 2, 64, 3, 3,
                               128, 1, 1, ReluActivator(), learning_rate)

        self.conv6 = MaxPoolingLayer(input_width // 2, input_height // 2, 128,
                                     3, 3, 1, 2)

        self.conv7 = ConvLayer(input_width // 4, input_height // 4, 128, 3, 3,
                               256, 1, 1, ReluActivator(), learning_rate)

        self.conv8 = UpsamplingLayer(input_width // 4, input_height // 4, 256,
                                     3, 3, 128, 1, 1, learning_rate)

        self.conv9 = ConvLayer(input_width // 2, input_height // 2, 128, 3, 3,
                               32, 1, 1, ReluActivator(), learning_rate)

        self.conv10 = UpsamplingLayer(input_width // 2, input_height // 2, 32,
                                      3, 3, 32, 1, 1, learning_rate)

        # self.conv11 = ConvLayer(input_width, input_height, 8,
        #                   3, 3, 4, 1, 1, ReluActivator(), learning_rate)

        self.conv12 = ConvLayer(input_width, input_height, 32, 3, 3, 2, 1, 1,
                                NoneActivator(), learning_rate)
Esempio n. 7
0
    def __init__(self):
        super(Discriminator, self).__init__()
        # 输入1*28*28 MNIST
        # 1*28*28 -> 64*16*16
        self.conv1 = ConvLayer(nc,
                               ndf,
                               4,
                               4,
                               zero_padding=1,
                               stride=2,
                               method='SAME',
                               bias_required=False)
        self.lrelu1 = Activators.LeakyReLU(0.2)

        # 64*16*16 -> 128*8*8
        self.conv2 = ConvLayer(ndf,
                               ndf * 2,
                               4,
                               4,
                               zero_padding=1,
                               stride=2,
                               method='SAME',
                               bias_required=False)
        self.bn1 = BatchNorm(ndf * 2)
        self.lrelu2 = Activators.LeakyReLU(0.2)

        # 128*8*8 -> 256*4*4
        self.conv3 = ConvLayer(ndf * 2,
                               ndf * 4,
                               4,
                               4,
                               zero_padding=1,
                               stride=2,
                               method='SAME',
                               bias_required=False)
        self.bn2 = BatchNorm(ndf * 4)
        self.lrelu3 = Activators.LeakyReLU(0.2)

        # 256*4*4 -> 1*1
        self.conv4 = ConvLayer(ndf * 4,
                               1,
                               4,
                               4,
                               zero_padding=0,
                               stride=1,
                               method='VALID',
                               bias_required=False)
        self.sigmoid = Activators.Sigmoid_CE()
Esempio n. 8
0
class Discriminator(Module):
    def __init__(self):
        super(Discriminator, self).__init__()
        # 输入1*28*28 MNIST
        # 1*28*28 -> 64*16*16
        self.conv1 = ConvLayer(nc, ndf, 4,4, zero_padding=1, stride=2,method='SAME', bias_required=False)
        self.lrelu1 = Activators.LeakyReLU(0.2)

        # 64*16*16 -> 128*8*8
        self.conv2 = ConvLayer(ndf, ndf*2, 4,4, zero_padding=1, stride=2, method='SAME', bias_required=False)
        self.bn1 = BatchNorm(ndf*2)
        self.lrelu2 = Activators.LeakyReLU(0.2)

        # 128*8*8 -> 256*4*4
        self.conv3 = ConvLayer(ndf*2, ndf*4, 4,4, zero_padding=1, stride=2, method='SAME', bias_required=False)
        self.bn2 = BatchNorm(ndf*4)
        self.lrelu3 = Activators.LeakyReLU(0.2)

        # 256*4*4 -> 1*1
        self.conv4 = ConvLayer(ndf*4, 1, 4,4, zero_padding=0, stride=1, method='VALID', bias_required=False)
        self.sigmoid = Activators.Sigmoid_CE()

    def forward(self, x_input):
        l1 = self.lrelu1.forward(self.conv1.forward(x_input))

        l2 = self.lrelu2.forward(self.bn1.forward(self.conv2.forward(l1)))

        l3 = self.lrelu3.forward(self.bn2.forward(self.conv3.forward(l2)))
        
        l4 = self.conv4.forward(l3)
        # print('D l1 shape: ',l1.shape)
        # print('D l2 shape: ',l2.shape)
        # print('D l3 shape: ',l3.shape)
        # print('D l4 shape: ',l4.shape)
        output_sigmoid = self.sigmoid.forward(l4)
        return output_sigmoid
    
    def backward(self, dy):
        # print('dy.shape: ', dy.shape)
        dy_sigmoid = self.sigmoid.gradient(dy)
        # print('dy_sigmoid.shape: ', dy_sigmoid.shape)
        dy_l4 = self.conv4.gradient(dy_sigmoid)
        dy_l3 = self.conv3.gradient(self.bn2.gradient(self.lrelu3.gradient(dy_l4)))
        dy_l2 = self.conv2.gradient(self.bn1.gradient(self.lrelu2.gradient(dy_l3)))
        dy_l1 = self.conv1.gradient(self.lrelu1.gradient(dy_l2))
        # print('D_backward output shape: ',dy_l1.shape)
        return dy_l1
Esempio n. 9
0
    def __init__(self, in_dim, n_class):
        super(Lenet_numpy, self).__init__()
        self.conv1 = ConvLayer(in_dim, 6, 5,5, zero_padding=2, stride=1, method='SAME')
        self.conv2 = ConvLayer(6, 16, 5,5, zero_padding=0, stride=1, method='VALID')
        self.conv3 = ConvLayer(16, 120, 5,5, zero_padding=0, stride=1, method='VALID')

        self.maxpool1 = MaxPooling(pool_shape=(2,2), stride=(2,2))
        self.maxpool2 = MaxPooling(pool_shape=(2,2), stride=(2,2))
        self.relu1 = ReLU()
        self.relu2 = ReLU()
        self.relu3 = ReLU()
        self.relu4 = ReLU()
        self.fc1 = FullyConnect(120, 84)
        self.fc2 = FullyConnect(84, n_class)
        self.logsoftmax = Logsoftmax()
Esempio n. 10
0
class Lenet_numpy(Module):
    def __init__(self, in_dim, n_class):
        super(Lenet_numpy, self).__init__()
        self.conv1 = ConvLayer(in_dim, 6, 5,5, zero_padding=2, stride=1, method='SAME')
        self.conv2 = ConvLayer(6, 16, 5,5, zero_padding=0, stride=1, method='VALID')
        self.conv3 = ConvLayer(16, 120, 5,5, zero_padding=0, stride=1, method='VALID')

        self.maxpool1 = MaxPooling(pool_shape=(2,2), stride=(2,2))
        self.maxpool2 = MaxPooling(pool_shape=(2,2), stride=(2,2))
        self.relu1 = ReLU()
        self.relu2 = ReLU()
        self.relu3 = ReLU()
        self.relu4 = ReLU()
        self.fc1 = FullyConnect(120, 84)
        self.fc2 = FullyConnect(84, n_class)
        self.logsoftmax = Logsoftmax()

    def forward(self, x): # 存在问题是:同一个对象其实是不能多次使用的,因为每个对象都有自己的input和output,如果重复使用反向会错误
        in_size = x.shape[0]
        out_c1s2 = self.relu1.forward(self.maxpool1.forward(self.conv1.forward(x)))
        out_c3s4 = self.relu2.forward(self.maxpool2.forward(self.conv2.forward(out_c1s2)))
        out_c5 = self.relu3.forward(self.conv3.forward(out_c3s4))
        self.conv_out_shape = out_c5.shape

        out_c5 = out_c5.reshape(in_size, -1)
        out_f6 = self.relu4.forward(self.fc1.forward(out_c5))
        out_f7 = self.fc2.forward(out_f6)
        out_logsoftmax = self.logsoftmax.forward(out_f7)

        return out_logsoftmax
    
    def backward(self, dy):
        dy_logsoftmax = self.logsoftmax.gradient(dy)
        dy_f7 = self.fc2.gradient(dy_logsoftmax)
        dy_f6 = self.fc1.gradient(self.relu4.gradient(dy_f7))

        dy_f6 = dy_f6.reshape(self.conv_out_shape)

        dy_c5 = self.conv3.gradient(self.relu3.gradient(dy_f6))
        dy_c3f4 = self.conv2.gradient(self.maxpool2.gradient(self.relu2.gradient(dy_c5)))
        self.conv1.gradient(self.maxpool1.gradient(self.relu1.gradient(dy_c3f4)))
Esempio n. 11
0
class CNN1(object):
    def __init__(self, input_width, input_height, channel_number,
                 learning_rate, cost_function):
        self.cost_function = cost_function
        self.predict_output_list = []
        self.conv1 = ConvLayer(input_width, input_height, channel_number, 3, 3,
                               64, 1, 1, ReluActivator(), learning_rate)

        # self.conv2 = ConvLayer(input_width, input_height, 64,
        #                   3, 3, 64, input_width // 2 + 1, 2, ReluActivator(), learning_rate)

        # self.conv2 = ConvLayer(input_width, input_height, 8,
        #                   3, 3, 8, 1, 1, ReluActivator(), learning_rate)

        self.conv3 = MaxPoolingLayer(input_width, input_height, 64, 3, 3, 1, 2)

        # self.conv4 = ConvLayer(input_width, input_height, 16,
        #                   3, 3, 16, 1, 1, ReluActivator(), learning_rate)

        self.conv5 = ConvLayer(input_width // 2, input_height // 2, 64, 3, 3,
                               128, 1, 1, ReluActivator(), learning_rate)

        self.conv6 = MaxPoolingLayer(input_width // 2, input_height // 2, 128,
                                     3, 3, 1, 2)

        self.conv7 = ConvLayer(input_width // 4, input_height // 4, 128, 3, 3,
                               256, 1, 1, ReluActivator(), learning_rate)

        self.conv8 = UpsamplingLayer(input_width // 4, input_height // 4, 256,
                                     3, 3, 128, 1, 1, learning_rate)

        self.conv9 = ConvLayer(input_width // 2, input_height // 2, 128, 3, 3,
                               32, 1, 1, ReluActivator(), learning_rate)

        self.conv10 = UpsamplingLayer(input_width // 2, input_height // 2, 32,
                                      3, 3, 32, 1, 1, learning_rate)

        # self.conv11 = ConvLayer(input_width, input_height, 8,
        #                   3, 3, 4, 1, 1, ReluActivator(), learning_rate)

        self.conv12 = ConvLayer(input_width, input_height, 32, 3, 3, 2, 1, 1,
                                NoneActivator(), learning_rate)

    def train_forward(self, input_array, new_batch):
        if np.random.randint(2, size=1)[0] == 1 or new_batch == 1:
            self.input_array = input_array
            self.conv1.forward(input_array)
            self.conv1_output_array = self.conv1.output_array

            # self.conv2.forward(self.conv1_output_array)
            # self.conv2_output_array = self.conv2.output_array

            self.conv3.forward(self.conv1_output_array)
            self.conv3_output_array = self.conv3.output_array

            # self.conv4.forward(self.conv3_output_array)
            # self.conv4_output_array = self.conv4.output_array

            self.conv5.forward(self.conv3_output_array)
            self.conv5_output_array = self.conv5.output_array

            self.conv6.forward(self.conv5_output_array)
            self.conv6_output_array = self.conv6.output_array

            self.conv7.forward(self.conv6_output_array)
            self.conv7_output_array = self.conv7.output_array

            self.conv8.forward(self.conv7_output_array)
            self.conv8_output_array = self.conv8.output_array

            self.conv9.forward(self.conv8_output_array)
            self.conv9_output_array = self.conv9.output_array

            self.conv10.forward(self.conv9_output_array)
            self.conv10_output_array = self.conv10.output_array

            # self.conv11.forward(self.conv10_output_array)
            # self.conv11_output_array = self.conv11.output_array
        else:
            self.conv1.forward(input_array)

            # self.conv2.forward(self.conv1.output_array)

            self.conv3.forward(self.conv1.output_array)

            # self.conv4.forward(self.conv3.output_array)

            self.conv5.forward(self.conv3.output_array)

            self.conv6.forward(self.conv5.output_array)

            self.conv7.forward(self.conv6.output_array)

            self.conv8.forward(self.conv7.output_array)

            self.conv9.forward(self.conv8.output_array)

            self.conv10.forward(self.conv9.output_array)

            # self.conv11.forward(self.conv10.output_array)

        self.conv12.forward(self.conv10_output_array)
        if new_batch == 1:
            self.predict_output_list = []
        self.predict_output_list.append(self.conv12.output_array)

    def train_backward(self, actual_output_list):
        delta_array = self.cost_function(actual_output_list,
                                         self.predict_output_list)
        self.conv12.backward(delta_array)
        print(1)
        # self.conv11.backward(self.conv12.delta_array)
        # print(2)
        self.conv10.backward(self.conv12.delta_array)
        print(3)
        self.conv9.backward(self.conv10.delta_array)
        print(4)
        self.conv8.backward(self.conv9.delta_array)
        print(5)
        self.conv7.backward(self.conv8.delta_array)
        print(6)
        self.conv6.backward(self.conv5_output_array, self.conv7.delta_array)
        print(7)
        self.conv5.backward(self.conv6.delta_array)
        print(8)
        # self.conv4.backward(self.conv5.delta_array)
        # print(9)
        self.conv3.backward(self.conv1_output_array, self.conv5.delta_array)
        print(10)
        # self.conv2.backward(self.conv3.delta_array)
        # print(11)

        self.conv1.update(self.input_array, self.conv3.delta_array)
        # self.conv2.update(self.conv1_output_array, self.conv3.delta_array)
        # self.conv3.update(self.conv1_output_array, self.conv5.delta_array)
        # self.conv4.update(self.conv3_output_array, self.conv5.delta_array)
        self.conv5.update(self.conv3_output_array, self.conv6.delta_array)
        # self.conv6.update(self.conv5_output_array, self.conv7.delta_array)
        self.conv7.update(self.conv6_output_array, self.conv8.delta_array)
        self.conv8.update(self.conv7_output_array, self.conv9.delta_array)
        self.conv9.update(self.conv8_output_array, self.conv10.delta_array)
        self.conv10.update(self.conv9_output_array, self.conv12.delta_array)
        # self.conv11.update(self.conv10_output_array, self.conv12.delta_array)
        self.conv12.update(self.conv10_output_array, delta_array)

    def output(self, input_array):
        self.conv1.forward(input_array)

        # self.conv2.forward(self.conv1.output_array)

        self.conv3.forward(self.conv1.output_array)

        # self.conv4.forward(self.conv3.output_array)

        self.conv5.forward(self.conv3.output_array)

        self.conv6.forward(self.conv5.output_array)

        self.conv7.forward(self.conv6.output_array)

        self.conv8.forward(self.conv7.output_array)

        self.conv9.forward(self.conv8.output_array)

        self.conv10.forward(self.conv9.output_array)

        # self.conv11.forward(self.conv10.output_array)

        self.conv12.forward(self.conv10_output_array)

        return self.conv12.output_array
Esempio n. 12
0
def conv_test():
    bit_length = 32
    # (1,28,28)*(5,5,5)
    # x_numpy = np.random.randn(1,1,28,28).astype(np.float32)
    # w_numpy = np.random.randn(5,1,5,5).astype(np.float32)
    # b_numpy = np.random.randn(5).astype(np.float32)
    # # (1,28,28)*(5,5,5)
    # x_numpy_1 = np.random.randn(1,1,28,28).astype(np.float32)
    # x_numpy_2 = x_numpy-x_numpy_1
    # w_numpy_1 = np.random.randn(5,1,5,5).astype(np.float32)
    # w_numpy_2 = w_numpy-w_numpy_1
    # b_numpy_1 = np.random.randn(5).astype(np.float32)
    # b_numpy_2 = b_numpy-b_numpy_1

    ## (3,32,32)*(64,2,2)
    # x_numpy = np.random.randn(1,3,32,32).astype(np.float32)
    # w_numpy = np.random.randn(64,3,2,2).astype(np.float32)
    # b_numpy = np.random.randn(64).astype(np.float32)
    # x = torch.tensor(x_numpy, requires_grad=True)

    # x_numpy_1 = np.random.randn(1,3,32,32).astype(np.float32)
    # x_numpy_2 = x_numpy-x_numpy_1
    # w_numpy_1 = np.random.randn(64,3,2,2).astype(np.float32)
    # w_numpy_2 = w_numpy-w_numpy_1
    # b_numpy_1 = np.random.randn(64).astype(np.float32)
    # b_numpy_2 = b_numpy-b_numpy_1

    x_numpy = np.random.randn(1,32,32,32).astype(np.float32)
    w_numpy = np.random.randn(128,32,3,3).astype(np.float32)
    b_numpy = np.random.randn(128).astype(np.float32)
    x = torch.tensor(x_numpy, requires_grad=True)

    x_numpy_1 = np.random.randn(1,32,32,32).astype(np.float32)
    x_numpy_2 = x_numpy-x_numpy_1
    w_numpy_1 = np.random.randn(128,32,3,3).astype(np.float32)
    w_numpy_2 = w_numpy-w_numpy_1
    b_numpy_1 = np.random.randn(128).astype(np.float32)
    b_numpy_2 = b_numpy-b_numpy_1

    print('input_shape: ', x_numpy.shape)
    print('w_shape: ', w_numpy.shape)

    # padding=0, stride=2
    # cl1 = Conv_sec(1, 5, 5, 5, zero_padding=0, stride=2, method='SAME')
    # cl1 = Conv_sec(3, 64, 2, 2, zero_padding=0, stride=2, method='SAME')
    cl1 = Conv_sec(32, 128, 3, 3, zero_padding=0, stride=2, method='SAME')
    cl_ori = ConvLayer(1, 5, 5, 5, zero_padding=1, stride=2, method='SAME')
    cl_tensor = torch.nn.Conv2d(1, 5, kernel_size=5, stride=2, padding=1)
    ## 设置参数
    cl_ori.set_weight(Parameter(w_numpy, requires_grad=True))
    cl_ori.set_bias(Parameter(b_numpy, requires_grad=True))
    cl1.set_weight_1(Parameter(w_numpy_1, requires_grad=True))
    cl1.set_bias_1(Parameter(b_numpy_1, requires_grad=True))
    cl1.set_weight_2(Parameter(w_numpy_2, requires_grad=True))
    cl1.set_bias_2(Parameter(b_numpy_2, requires_grad=True))

    # print('param_error: \n', w_numpy-(w_numpy_1+w_numpy_2))
    # print('param_error: \n', cl_ori.weights.data-(cl1.weights_1.data+cl1.weights_2.data))

    '''前向传播'''
    # start_time_tensor = time.time()
    # conv_out = cl_tensor(x)
    # end_time_tensor = time.time()
    # start_time = time.time()
    # conv_out = cl_ori.forward(x_numpy)
    # end_time = time.time()

    test_num = 10
    time_avg = 0
    for i in range(test_num):
        start_time_sec = time.time()
        conv_out_1, conv_out_2 = cl1.forward(x_numpy_1, x_numpy_2)
        end_time_sec = time.time()
        time_avg+=(end_time_sec-start_time_sec)*1000
    print('time avg sec: \n', time_avg/test_num)
Esempio n. 13
0
class CNN(object):
    def __init__(self, input_width, input_height, channel_number,
                 learning_rate, cost_function):
        self.cost_function = cost_function
        self.predict_output_list = []
        self.conv1 = ConvLayer(input_width, input_height, channel_number, 3, 3,
                               16, 1, 1, ReluActivator(), learning_rate)

        self.conv3 = MaxPoolingLayer(input_width, input_height, 16, 3, 3, 1, 2)

        self.conv4 = ConvLayer(input_width // 2, input_height // 2, 16, 3, 3,
                               32, 1, 1, ReluActivator(), learning_rate)

        self.conv5 = MaxPoolingLayer(input_width // 2, input_height // 2, 32,
                                     3, 3, 1, 2)

        self.conv6 = ConvLayer(input_width // 4, input_height // 4, 32, 3, 3,
                               32, 1, 1, ReluActivator(), learning_rate)

        self.conv8 = UpsamplingLayer(input_width // 4, input_height // 4, 32)

        self.conv9 = ConvLayer(input_width // 2, input_height // 2, 32, 3, 3,
                               16, 1, 1, ReluActivator(), learning_rate)

        self.conv10 = UpsamplingLayer(input_width // 2, input_height // 2, 16)

        self.conv12 = ConvLayer(input_width, input_height, 16, 3, 3, 2, 1, 1,
                                TanhActivator(), learning_rate)

    def train_forward(self, input_array, new_batch):
        if np.random.randint(2, size=1)[0] == 1 or new_batch == 1:
            self.input_array = input_array
            self.conv1.forward(input_array)
            self.conv1_output_array = np.array(self.conv1.output_array)

            self.conv3.forward(self.conv1.output_array)
            self.conv3_output_array = np.array(self.conv3.output_array)

            self.conv4.forward(self.conv3.output_array)
            self.conv4_output_array = np.array(self.conv4.output_array)

            self.conv5.forward(self.conv4.output_array)
            self.conv5_output_array = np.array(self.conv5.output_array)

            self.conv6.forward(self.conv5.output_array)
            self.conv6_output_array = np.array(self.conv6.output_array)

            self.conv8.forward(self.conv6.output_array)
            self.conv8_output_array = np.array(self.conv8.output_array)

            self.conv9.forward(self.conv8.output_array)
            self.conv9_output_array = np.array(self.conv9.output_array)

            self.conv10.forward(self.conv9.output_array)
            self.conv10_output_array = np.array(self.conv10.output_array)

        else:
            self.conv1.forward(input_array)

            self.conv3.forward(self.conv1.output_array)

            self.conv4.forward(self.conv3.output_array)

            self.conv5.forward(self.conv4.output_array)

            self.conv6.forward(self.conv5.output_array)

            self.conv8.forward(self.conv6.output_array)

            self.conv9.forward(self.conv8.output_array)

            self.conv10.forward(self.conv9.output_array)

        self.conv12.forward(self.conv10.output_array)
        if new_batch == 1:
            self.predict_output_list = []
        conv12_output_array = np.array(self.conv12.output_array)
        self.predict_output_list.append(conv12_output_array)

    def train_backward(self, actual_output_list):
        delta_array = self.cost_function(actual_output_list,
                                         self.predict_output_list)
        self.conv12.backward(delta_array)
        self.conv10.backward(self.conv12.delta_array)
        self.conv9.backward(self.conv10.delta_array)
        self.conv8.backward(self.conv9.delta_array)
        self.conv6.backward(self.conv8.delta_array)
        self.conv5.backward(self.conv4_output_array, self.conv6.delta_array)
        self.conv4.backward(self.conv5.delta_array)
        self.conv3.backward(self.conv1_output_array, self.conv4.delta_array)

        self.conv1.update(self.input_array, self.conv3.delta_array)
        self.conv4.update(self.conv3_output_array, self.conv5.delta_array)
        self.conv6.update(self.conv5_output_array, self.conv8.delta_array)
        self.conv9.update(self.conv8_output_array, self.conv10.delta_array)
        self.conv12.update(self.conv10_output_array, delta_array)

    def output(self, input_array):
        self.conv1.forward(input_array)

        self.conv3.forward(self.conv1.output_array)

        self.conv4.forward(self.conv3.output_array)

        self.conv5.forward(self.conv4.output_array)

        self.conv6.forward(self.conv5.output_array)

        self.conv8.forward(self.conv6.output_array)

        self.conv9.forward(self.conv8.output_array)

        self.conv10.forward(self.conv9.output_array)

        self.conv12.forward(self.conv10_output_array)

        return self.conv12.output_array

    def save(self, path):
        fo = open(path, "w")
        for filter in self.conv1.filters:
            for i in range(0, filter.weights.shape[0]):
                for j in range(0, filter.weights.shape[1]):
                    for k in range(0, filter.weights.shape[2]):
                        fo.write(str(filter.weights[i, j, k]) + ' ')
            fo.write(str(filter.bias) + '\n')
        for filter in self.conv4.filters:
            for i in range(0, filter.weights.shape[0]):
                for j in range(0, filter.weights.shape[1]):
                    for k in range(0, filter.weights.shape[2]):
                        fo.write(str(filter.weights[i, j, k]) + ' ')
            fo.write(str(filter.bias) + '\n')
        for filter in self.conv6.filters:
            for i in range(0, filter.weights.shape[0]):
                for j in range(0, filter.weights.shape[1]):
                    for k in range(0, filter.weights.shape[2]):
                        fo.write(str(filter.weights[i, j, k]) + ' ')
            fo.write(str(filter.bias) + '\n')
        for filter in self.conv9.filters:
            for i in range(0, filter.weights.shape[0]):
                for j in range(0, filter.weights.shape[1]):
                    for k in range(0, filter.weights.shape[2]):
                        fo.write(str(filter.weights[i, j, k]) + ' ')
            fo.write(str(filter.bias) + '\n')
        for filter in self.conv12.filters:
            for i in range(0, filter.weights.shape[0]):
                for j in range(0, filter.weights.shape[1]):
                    for k in range(0, filter.weights.shape[2]):
                        fo.write(str(filter.weights[i, j, k]) + ' ')
            fo.write(str(filter.bias) + '\n')
        fo.close()

    def load(self, path):
        fi = open(path, 'r')
        data = fi.readlines()
        for l in range(0, 16):
            para_list = data[l].split()
            for i in range(0, self.conv1.filters[l].weights.shape[0]):
                for j in range(0, self.conv1.filters[l].weights.shape[1]):
                    for k in range(0, self.conv1.filters[l].weights.shape[2]):
                        self.conv1.filters[l].weights[i, j, k] = float(
                            para_list[i * 9 + j * 3 + k])
            self.conv1.filters[l].bias = float(para_list[-1])
        for l in range(16, 48):
            para_list = data[l].split()
            for i in range(0, self.conv4.filters[l - 16].weights.shape[0]):
                for j in range(0, self.conv4.filters[l - 16].weights.shape[1]):
                    for k in range(0, self.conv4.filters[l -
                                                         16].weights.shape[2]):
                        self.conv4.filters[l - 16].weights[i, j, k] = float(
                            para_list[i * 9 + j * 3 + k])
            self.conv4.filters[l - 16].bias = float(para_list[-1])
        for l in range(48, 80):
            para_list = data[l].split()
            for i in range(0, self.conv6.filters[l - 16].weights.shape[0]):
                for j in range(0, self.conv6.filters[l - 16].weights.shape[1]):
                    for k in range(0, self.conv6.filters[l -
                                                         16].weights.shape[2]):
                        self.conv6.filters[l - 16].weights[i, j, k] = float(
                            para_list[i * 9 + j * 3 + k])
            self.conv6.filters[l - 16].bias = float(para_list[-1])
        for l in range(80, 96):
            para_list = data[l].split()
            for i in range(0, self.conv9.filters[l - 80].weights.shape[0]):
                for j in range(0, self.conv9.filters[l - 80].weights.shape[1]):
                    for k in range(0, self.conv9.filters[l -
                                                         80].weights.shape[2]):
                        self.conv9.filters[l - 80].weights[i, j, k] = float(
                            para_list[i * 9 + j * 3 + k])
            self.conv9.filters[l - 80].bias = float(para_list[-1])
        for l in range(96, 98):
            para_list = data[l].split()
            for i in range(0, self.conv12.filters[l - 96].weights.shape[0]):
                for j in range(0,
                               self.conv12.filters[l - 96].weights.shape[1]):
                    for k in range(
                            0, self.conv12.filters[l - 96].weights.shape[2]):
                        self.conv12.filters[l - 96].weights[i, j, k] = float(
                            para_list[i * 9 + j * 3 + k])
            self.conv12.filters[l - 96].bias = float(para_list[-1])