프로젝트

Cycle GAN을 이용한 인공지능 네트워크 설계

수달하나 2021. 4. 9. 21:09

Cycle GAN을 통해 낮의 이미지를 밤으로 밤의 이미지를 낮으로 변환하는 네트워크를 설계한다.

 

인공 신경망에서는 벡터의 형태로 입력된 데이터를 전달 받고 각각의 입력에 웨이트(Weight)라는 가중치를 곱하고 합산, 이후 바이어스 까지 더하는 과정을 통해 실제 뉴런과 비슷한 인공 신경망을 구성하게 되고 이러한 여러 개의 인공 신경망들을 겹쳐서 많은 층을 만들어 내는 과정을 통해 네트워크를 설계하면 아래와 같은 딥러닝 네트워크(Deep Neural Network)가 구성되게 된다.  

 

 

딥러닝 네트워크(Deep Neural Network)

 

이러한 딥러닝 네트워크를 이미지 변환을위한 네트워크로 변환하기 위해 합성 곱 신경망(Convolution Network)이라는 개념을 통해서 네트워크를 변환시킨다.

 

합성곱 신경망(Convolution Network)

 

일반적 GAN 은 Generator를 통해 실제 이미지를 생성하고 Discriminator를 통해 이미지를 식별하는 역할을 한다. 하지만 Cycle GAN의 경우엔 일반 GAN 모델을 응용하여 2개의 네트워크를 동시에 학습시키는 네트위크 구조이고 서로다른 두 이미지를 통해 양뱡향 학습을 진행하게 된다. 

 

GAN(Generative Adversarial Networks)

 

Cycle GAN

def GAN_model(generatorA2B, generatorB2A, discriminatorA, discriminatorB, train_optimizer, lambda_cyc = 10, lambda_idt = 5):
        
    image_A = Input(shape=(128, 128, 3))
    image_B = Input(shape=(128, 128, 3))

    fake_image_B = generatorA2B(image_A)
    fake_image_A = generatorB2A(image_B)

    reconstructed_image_A = generatorB2A(fake_image_B)
    reconstructed_image_B = generatorA2B(fake_image_A)

    identity_image_A = generatorB2A(image_A)
    identity_image_B = generatorA2B(image_B)

    decisionA = discriminatorA(fake_image_A)
    decisionB = discriminatorB(fake_image_B)

    gan_model = Model(inputs = [inA, inB], outputs = [decisionA, decisionB, reconstructed_image_A, reconstructed_image_B, identity_image_A, identity_image_B])
    gan_model.compile(loss= ['mse', 'mse', 'mae', 'mae', 'mae', 'mae'], loss_weights= [1, 1, lambda_cyc, lambda_cyc, lambda_idt, lambda_idt],
                                optimizer = train_optimizer)
    
    return gan_model

전체 네트워크를 정의후 Generator와 Discriminator를 구축한다.

 

Generator 설계

def generator_network(resnet_blocks=10):
    
    input_layer = Input(shape=(128,128,3))

    layer_1 = Conv2D(filters=64, kernel_size=7, strides=1, padding="same")(input_layer)
    layer_1 = InstanceNormalization(axis=1)(layer_1)
    layer_1 = Activation("relu")(layer_1)

    layer_2 = Conv2D(filters=128, kernel_size=3, strides=2, padding="same")(layer_1)
    layer_2 = InstanceNormalization(axis=1)(layer_2)
    layer_2 = Activation("relu")(layer_2)

    layer_3 = Conv2D(filters=256, kernel_size=3, strides=2, padding="same")(layer_2)
    layer_3 = InstanceNormalization(axis=1)(layer_3)
    layer_3 = Activation("relu")(layer_3)

    layer_4 = layer_3
    for i in range(resnet_blocks):
        layer_4 = resnet_block(layer_4)
    
    layer_5 = Conv2DTranspose(filters=128, kernel_size=3, strides=2, padding='same', use_bias=False)(layer_4)
    layer_5 = InstanceNormalization(axis=1)(layer_5)
    layer_5 = Activation("relu")(layer_5)

    layer_6 = Conv2DTranspose(filters=64, kernel_size=3, strides=2, padding='same', use_bias=False)(layer_5)
    layer_6 = InstanceNormalization(axis=1)(layer_6)
    layer_6 = Activation("relu")(layer_6)

    layer_7 = Conv2D(filters=3, kernel_size=7, strides=1, padding="same")(layer_6)
    
    output_layer = Activation('tanh')(layer_7)

    model = Model(inputs=[input_layer], outputs=[output_layer])
    
    return model

 

Resnet_block

def resnet_block(layer):

    layer_1 = Conv2D(filters=256, kernel_size=3, strides=1, padding="same")(layer)
    layer_1 = InstanceNormalization(axis=1)(layer_1)
    layer_1 = Activation('relu')(layer_1)

    layer_2 = Conv2D(filters=256, kernel_size=3, strides=1, padding="same")(layer_1)
    layer_2 = InstanceNormalization(axis=1)(layer_2)

    return Add()([layer_1, layer_2])

 

Discriminator 설계

def discriminator_network():

    input_layer = Input(shape=(128, 128, 3))

    layer_1 = ZeroPadding2D(padding=(1, 1))(input_layer)

    layer_2 = Conv2D(filters=64, kernel_size=4, strides=2, padding="valid")(layer_1)
    layer_2 = LeakyReLU(alpha=0.2)(layer_2)

    layer_3 = ZeroPadding2D(padding=(1, 1))(layer_2)

    layer_4 = layer_3
    
    for i in range(1, 4):
        layer_4 = Conv2D(filters=2 ** i * 64, kernel_size=4, strides=2, padding="valid")(layer_4)
        layer_4 = InstanceNormalization(axis=1)(layer_4)
        layer_4 = LeakyReLU(alpha=0.2)(layer_4)
        layer_4 = ZeroPadding2D(padding=(1, 1))(layer_4)

   
    layer_5 = Conv2D(filters=1, kernel_size=4, strides=1, activation="sigmoid")(layer_4)

    output_layer = layer_5

    model = Model(inputs=[input_layer], outputs=[output_layer])
    
    return model