본문 바로가기

인공지능(AI) 이론과 코드/4. 딥러닝

[Class 상속의 개념] super().__init__() 의 원리와 이해

CNN(Convolution Neural Network)은 이미지 분류에 많이 사용하는 컨볼루션 연산 기반의 인공지능 모델입니다.

CNN을 응용한 여러 모델 중 ResNet 이 있습니다.

 

ResNet은 이미지 천 만장을 학습하여 이미지 15만장으로 인식률을 겨루는 이미지 넷 대회에서 2015년 우승한 후 그 성능을 인정받아 널리 쓰이기 있습니다.

 

https://www.image-net.org/challenges/LSVRC/index.php

 

ImageNet

Competition The ImageNet Large Scale Visual Recognition Challenge (ILSVRC) evaluates algorithms for object detection and image classification at large scale. One high level motivation is to allow researchers to compare progress in detection across a wider

www.image-net.org

 


 

다음은 ResNet 의 모델 아키텍처입니다.

class ResNet(nn.Module):
    def __init__(self, num_classes=10):
        super(ResNet, self).__init__()
        self.in_planes = 16

        self.conv1 = nn.Conv2d(3, 16, kernel_size=3,
                               stride=1, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(16)
        self.layer1 = self._make_layer(16, 2, stride=1)
        self.layer2 = self._make_layer(32, 2, stride=2)
        self.layer3 = self._make_layer(64, 2, stride=2)
        self.linear = nn.Linear(64, num_classes)

    def _make_layer(self, planes, num_blocks, stride):
        strides = [stride] + [1]*(num_blocks-1)
        layers = []
        for stride in strides:
            layers.append(BasicBlock(self.in_planes, planes, stride))
            self.in_planes = planes
        return nn.Sequential(*layers)

    def forward(self, x):
        out = F.relu(self.bn1(self.conv1(x)))
        out = self.layer1(out)
        out = self.layer2(out)
        out = self.layer3(out)
        out = F.avg_pool2d(out, 8)
        out = out.view(out.size(0), -1)
        out = self.linear(out)
        return out

위의 코드에서 세 번째 줄에 보면

super(ResNet, self).__init__() 부분이 등장합니다. 오늘은 이 부분을 자세히 알아보겠습니다.

 

 


다음과 같이 Coffee 클래스에 Espresso 속성이 있고, Coffee 클래스를 상속받아 Starbucks 클래스를 만듭니다. 그다음에 Starbucks로 인스턴스를 만들고 Espresso속성에 접근해봅니다.

 

class Coffee:
    def __init__(self):
        print('Coffee __init__')
        self.Espresso = '에스프레소 1샷'
 
class Starbucks(Coffee):
    def __init__(self):
        print('Starbucks __init__')
        self.Americano = '따뜻한 아메리카노 4.5 '
 
My_Coffee = Starbucks()
print(My_Coffee.Espresso)
print(My_Coffee.Americano)    # 부모 클래스의 속성을 출력하려고 하면 에러가 발생함

 

실행을 해보면 에러가 발생합니다. 왜냐하면 부모 클래스 Coffee __init__ 메서드가 호출되지 않았기 때문입니다. 실행 결과를 잘 보면 'Starbucks__init__'만 출력되었습니다.

즉, Coffee __init__ 메서드가 호출되지 않으면 self.Espresso= '에스프레소 1샷'도 실행되지 않아서 속성이 만들어지지 않습니다.

Starbucks __init__
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-14-6024eca21fc8> in <module>
     10 
     11 My_Coffee = Starbucks()
---> 12 print(My_Coffee.Espresso)
     13 print(My_Coffee.Americano)    # 부모 클래스의 속성을 출력하려고 하면 에러가 발생함

AttributeError: 'Starbucks' object has no attribute 'Espresso'

이때는 super()를 사용해서 부모 클래스의 __init__ 메서드를 호출해줍니다. 다음과 같이 super() 뒤에 .뒤에.(점)을 붙여서 메서드를 호출하는 방식입니다.

 

class Coffee:
    def __init__(self):
        print('Coffee __init__')
        self.Espresso = '에스프레소 1샷'
 
class Starbucks(Coffee):
    def __init__(self):
        print('Starbucks __init__')
        super().__init__()  # super()로 부모 클래스의 __init__ 메서드 호출
        
        self.Americano = '따뜻한 아메리카노 4.5 '
 
My_Coffee = Starbucks()
print(My_Coffee.Espresso)
print(My_Coffee.Americano)

이제는 결과가 에러 없이 출력됩니다.

Starbucks __init__
Coffee __init__
에스프레소 1샷
따뜻한 아메리카노 4.5

실행을 해보면 부모 클래스 Coffee의 속성인 Espresso가 잘 출력됩니다. super().__init__()와 같이 부모 클래스 Coffee __init__ 메서드를 호출해주면 부모 클래스가 초기화되어서 속성이 만들어집니다. 실행 결과를 보면 'Starbucks__init__' 'Coffee __init__'이 모두 출력되었습니다.

 

 


[예외 경우] pass

 

만약 자식 클래스에서 __init__ 메서드를 생략한다면 부모 클래스의 __init__이 자동으로 호출되므로 super()는 사용하지 않아도 됩니다.

 

class Person:
    def __init__(self):
        print('Person __init__')
        self.hello = '안녕하세요.'
 
class Student(Person):
    pass
 
My_Coffee = Starbucks()
print(My_Coffee.Espresso)

이처럼 자식 클래스에 __init__ 메서드가 없다면 부모 클래스의 __init__이 자동으로 호출되므로 부모 클래스의 속성을 사용할 수 있습니다.

Coffee __init__
에스프레소 1샷

 


 

[참고] super(자식 클래스, self). 메서드

super는 다음과 같이 자식 클래스와 self를 넣어서 현재 클래스가 어떤 클래스인지 명확하게 표시하는 방법도 있습니다. 물론 super()와 기능은 같습니다.

class Starbucks(Coffee):
    def __init__(self):
        print('Starbucks __init__')
        super(Starbucks, self).__init__()     # super(자식클래스, self)로 부모클래스의 메서드 호출
        self.Espresso = '에스프레소 1샷'
        
My_Coffee = Starbucks()
print(My_Coffee.Espresso)

실행 경과, 'Starbucks__init__'과 'Coffee __init__'이 모두 출력되었습니다.

Starbucks __init__
Coffee __init__
에스프레소 1샷

 

실습하실 수 있게 주피터 노트북을 첨부합니다.

[Class 상속의 개념] super().__init__() 의 원리와 이해_20220224.ipynb
0.01MB

 

 

 

https://www.kaggle.com/c/imagenet-object-localization-challenge/data

 

ImageNet Object Localization Challenge | Kaggle

 

www.kaggle.com

반응형
LIST