본문 바로가기
Artificial Intelligence/Keras

[Tensorflow 2][Keras] Week 4 - Assignment: Create a VGG network

by 개발자J의일상 2021. 4. 12.
반응형

본 포스팅은 다음 과정을 정리 한 글입니다.

 

Custom Models, Layers, and Loss Functions with TensorFlow

 

www.coursera.org/specializations/tensorflow-advanced-techniques

 

TensorFlow: Advanced Techniques

deeplearning.ai에서 제공합니다. Expand your skill set and master TensorFlow. Customize your machine learning models through four hands-on courses! 무료로 등록하십시오.

www.coursera.org

 

지난 시간 리뷰

 

2021.04.06 - [Artificial Intelligence/Keras] - [Tensorflow 2][Keras] Week 4 - Implementing ResNet

 

[Tensorflow 2][Keras] Week 4 - Implementing ResNet

본 포스팅은 다음 과정을 정리 한 글입니다. Custom Models, Layers, and Loss Functions with TensorFlow www.coursera.org/specializations/tensorflow-advanced-techniques 지난 시간 리뷰 2021.04.05 - [Artif..

mypark.tistory.com

 

안녕하세요 이번 시간에는 VGG network를 실제로 구현해보고자 합니다.

 

 

들어가기 전에 Python function 중 vars()를 이용하는 법에 대해서 살펴보겠습니다.

 

이 함수를 통해 for 루프를 돌면서 여러 개의 variables를 한 번에 정의해 보겠습니다. (ex var1, var2, var3)

 

# Define a small class MyClass
class MyClass:
    def __init__(self):
        # One class variable 'a' is set to 1
        self.var1 = 1

# Create an object of type MyClass()
my_obj = MyClass()

 

Python class들은 __dict__를 호출할 수 있습니다.

__dict__는 파이썬 dictionary로 객체의 instance variable과 값을 쌍으로 들고 있습니다.

 

my_obj.__dict__

Out : {'var1': 1}

 

만약에 vars()를 호출하면서 object를 매개변수로 넣으면, 이 것은 object의 __dict__ 속성을 call 하게 됩니다. 

vars(my_obj)

{'var1': 1}

 

비슷하게 새로운 variable를 더 생성해 봅시다.

# Add a new instance variable and give it a value
my_obj.var2 = 2

# Calls vars() again to see the object's instance variables
vars(my_obj)

Out : {'var1': 1, 'var2': 2}

 

위와 같이 object에 instance variable을 추가하고 값을 대입할 수 있는 방법이 있고 그 외에 vars()를 통해 object에 instance variable을 추가하는 방법이 있습니다.

# Call vars, passing in the object.  Then access the __dict__ dictionary using square brackets
vars(my_obj)['var3'] = 3

# Call vars() to see the object's instance variables
vars(my_obj)

Out : {'var1': 1, 'var2': 2, 'var3': 3}

 

동일하게 object의 instance variable이 추가되는 것을 알 수 있습니다.

 

이 것이 왜 필요하냐?!

 

객체의 instance variable에 액세스 하기 위해 다른 방법이 필요한 이유가 궁금하시죠?

 

vars()를 사용할 때 이제 변수 var3의 이름을 문자열로 전달할 수 있습니다.

이름이 비슷한 여러 변수(var4, var5, ... var9)를 사용하려고 할 때 편리하게 액세스 할 수 있는 방법이 있습니다.

 

다음 코드는 var4~var9까지를 0으로 만드는 코드입니다.

# Use a for loop to increment the index 'i'
for i in range(4,10):
    # Format a string that is var
    vars(my_obj)[f'var{i}'] = 0
    
# View the object's instance variables!
vars(my_obj)

Out : {'var1': 1, 'var2': 2, 'var3': 3, 'var4': 0, 'var5': 0, 'var6': 0, 'var7': 0, 'var8': 0, 'var9': 0}

 

파이썬에서 문자열 형식을 지정하는 두 가지 방법에 대해 설명드리겠습니다.

 

  • f-string: f"var{i}"
  • .format: "var{}".format(i)
# Format a string using f-string notation
i=1
print(f"var{i}")

# Format a string using .format notation
i=2
print("var{}".format(i))

Out :  var1

         var2

 

vars(self)를 사용하여 클래스 정의 내에서 클래스의 변수에 액세스 할 수 있습니다.

# Define a small class MyClass
class MyClass:
    def __init__(self):
        # Use vars(self) to access the class's dictionary of variables
        vars(self)['var1'] = 1

# Create an object of type MyClass()
my_obj = MyClass()
vars(my_obj)

Out : {'var1': 1}

 

여기까지가 vars에 대한 설명이었습니다. 이제 VGG network를 만들어 봅시다.

 

# Please uncomment all lines in this cell and replace those marked with `# YOUR CODE HERE`.
# You can select all lines in this code cell with Ctrl+A (Windows/Linux) or Cmd+A (Mac), then press Ctrl+/ (Windows/Linux) or Cmd+/ (Mac) to uncomment.



class Block(tf.keras.Model):
    def __init__(self, filters, kernel_size, repetitions, pool_size=2, strides=2):
        super(Block, self).__init__()
        self.filters = filters
        self.kernel_size = kernel_size
        self.repetitions = repetitions
        
        # Define a conv2D_0, conv2D_1, etc based on the number of repetitions
        for i in range(0, self.repetitions):
            
            # Define a Conv2D layer, specifying filters, kernel_size, activation and padding.
            vars(self)[f'conv2D_{i}'] = tf.keras.layers.Conv2D(self.filters, self.kernel_size, activation='relu', padding='same')
        
        # Define the max pool layer that will be added after the Conv2D blocks
        self.max_pool = tf.keras.layers.MaxPooling2D(pool_size=(pool_size, pool_size), strides=(strides, strides))
  
    def call(self, inputs):
        # access the class's conv2D_0 layer
        conv2D_0 = self.conv2D_0
        
        # Connect the conv2D_0 layer to inputs
        x = conv2D_0(inputs)

        # for the remaining conv2D_i layers from 1 to `repetitions` they will be connected to the previous layer
        for i in range(1, self.repetitions):
            # access conv2D_i by formatting the integer `i`. (hint: check how these were saved using `vars()` earlier)
            conv2D_i = vars(self)[f'conv2D_{i}']
            
            # Use the conv2D_i and connect it to the previous layer
            x = conv2D_i(x)

        # Finally, add the max_pool layer
        max_pool = self.max_pool(x)
        
        return max_pool

 

# Please uncomment all lines in this cell and replace those marked with `# YOUR CODE HERE`.
# You can select all lines in this code cell with Ctrl+A (Windows/Linux) or Cmd+A (Mac), then press Ctrl+/ (Windows/Linux) or Cmd+/ (Mac) to uncomment.



class MyVGG(tf.keras.Model):

    def __init__(self, num_classes):
        super(MyVGG, self).__init__()

        # Creating blocks of VGG with the following 
        # (filters, kernel_size, repetitions) configurations
        self.block_a = Block(64, 3, 2)
        self.block_b = Block(128, 3, 2)
        self.block_c = Block(256, 3, 3)
        self.block_d = Block(512, 3, 3)
        self.block_e = Block(512, 3, 3)

        # Classification head
        # Define a Flatten layer
        self.flatten = tf.keras.layers.Flatten()
        # Create a Dense layer with 256 units and ReLU as the activation function
        self.fc = tf.keras.layers.Dense(256, activation='relu')
        # Finally add the softmax classifier using a Dense layer
        self.classifier = tf.keras.layers.Dense(num_classes, activation='softmax')

    def call(self, inputs):
        # Chain all the layers one after the other
        x = self.block_a(inputs)
        x = self.block_b(x)
        x = self.block_c(x)
        x = self.block_d(x)
        x = self.block_e(x)
        x = self.flatten(x)
        x = self.fc(x)
        x = self.classifier(x)
        return x

dataset = tfds.load('cats_vs_dogs', split=tfds.Split.TRAIN, data_dir='data/')

# Initialize VGG with the number of classes 
vgg = MyVGG(num_classes=2)

# Compile with losses and metrics
vgg.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

# Define preprocessing function
def preprocess(features):
    # Resize and normalize
    image = tf.image.resize(features['image'], (224, 224))
    return tf.cast(image, tf.float32) / 255., features['label']

# Apply transformations to dataset
dataset = dataset.map(preprocess).batch(32)

# Train the custom VGG model
vgg.fit(dataset, epochs=10)
300x250

댓글