본문 바로가기
C.W.K.
Stream
Lesson 02 of 05 · published

단순한 고양이에서 캣우먼까지

~12 min · dimensions, representation, arrays, oop

Level 0수학 초심자
0 XP0/59 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete

차원을 의도적으로 더하기

a_cat = np.random.rand(64, 64, 3)은 64×64 RGB 이미지를 흉내 낸 배열이야. 축은 높이, 너비, 색상 채널 셋이고 값은 12,288개지. 고양이의 시각적 표면은 담을 수 있지만 이름과 성격, 행동까지 담지는 못해.

고양이에게 안경을 씌운다고 해보자. 안경에는 프레임 색, 렌즈 농도, 위치 같은 별도 특성이 있어. cat_with_glasses = combine(cat, glasses)는 고양이를 버리고 안경으로 바꾸는 게 아니라 두 표현을 조합해 새 상태를 만드는 생각이야. 모자와 이름, 기분도 같은 방식으로 더할 수 있어.

캣우먼 같은 캐릭터는 더 복잡해. 고양이와 인간의 특성, 의상, 서사, 말투가 한 인물 안에서 함께 작동해. 이 비유의 요점은 가능한 캐릭터를 전부 목록으로 만들기보다, 재사용할 특성과 관계를 조합해 새 사례를 표현하는 데 있어.

관측값과 해석을 구분하기

털빛과 픽셀은 비교적 직접 관측할 수 있지만 귀여움, 분위기, 패션 감각은 관찰자와 맥락에 따라 달라지는 해석이야. 그렇다고 모델에 쓸 수 없는 건 아니야. 다만 이런 속성을 라벨이나 학습된 표현으로 다룰 때는 누가 어떤 기준으로 측정했는지 함께 물어야 해.

현대 모델은 토큰이나 이미지를 수백에서 수천 차원의 벡터로 바꾸곤 해. 그 축 대부분에는 사람이 붙인 이름이 없어. 모델이 과제를 풀며 유용한 구별을 학습한 결과라서, 한 축만 떼어 ‘이건 귀여움’이라고 단정하기보다 벡터 전체의 관계를 보는 편이 안전해.

객체지향의 조합 감각

객체지향 설계에도 비슷한 감각이 있어.

  • CatMammal이 가진 공통 성질을 상속할 수 있어.
  • CatWithGlassesCatGlasses를 합성할 수 있어.
  • CatWoman을 반드시 다중 상속으로 구현해야 하는 건 아니야. 상속과 합성 가운데 어떤 관계가 실제 설계를 더 정확히 나타내는지 골라야 해.

Python 클래스와 AI 표현은 같은 물건은 아니지만, 모든 사례를 외우지 않고 재사용할 구조를 만든다는 공통점이 있어. 좋은 표현은 새 조합을 만들 수 있으면서도 각 축과 관계의 뜻을 잃지 않아.

나열보다 합성. 가능한 사례를 전부 외우게 하지 말고, 중요한 특성과 관계를 표현해 새 사례에 다시 쓸 수 있게 해. 단, 조합 가능한 것과 실제로 독립된 차원인 것은 구분해야 해.

Code

NumPy로 고양이 표현 조합하기·python
import numpy as np

a_cat = np.random.rand(3, 3, 3)             # 3-D 고양이
glasses = np.random.rand(3, 3, 3)           # 3-D 안경
cat_with_hat = np.concatenate(              # 마지막 축으로 합치기
    (a_cat, glasses), axis=2
)
print(cat_with_hat.shape)                   # (3, 3, 6) — 차원 결합

# 추상 차원 — '귀여움' 자체가 다차원 객체
cuteness = np.random.rand(3, 3, 3)
a_cute_cat = np.einsum('ijk,ijk->ij', a_cat, cuteness)  # 원소곱 후 합
print(a_cute_cat.shape)                     # (3, 3) — cuteness 가중 고양이 슬라이스
같은 아이디어, 클래스로·python
class Animal: ...
class Mammal(Animal): ...

class Cat(Mammal):
    def __init__(self, name, color, sass=0.8):
        self.name, self.color, self.sass = name, color, sass

    def meow(self):
        return f"{self.name}: 야옹 (sass {self.sass})"

class CatWoman(Cat):
    """다중-mold composition: Cat + Woman + 연극성."""
    def __init__(self, name, theatricality):
        super().__init__(name, color="black", sass=1.5)
        self.theatricality = theatricality

garfield = Cat("Garfield", "orange")
selina   = CatWoman("Selina", theatricality=0.95)

External links

Exercise

Python 클래스로 한 사람의 상태를 간단히 모델링해 봐. 직접 관측할 속성 넷과 맥락에 따라 달라지는 속성 넷을 고른 뒤, 열 살 때의 상태를 별도 인스턴스로 표현해. 무엇이 유지되고 무엇이 달라지는지, 외부에 공개하지 않을 내부 상태는 무엇인지 적어.
Hint
사람 전체를 클래스 하나로 환원하려는 문제가 아니야. 특정 프로그램 목적에 필요한 정보만 고르고, 상속과 인스턴스 차이를 구분하는 연습이야.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고
💛 by 똘이playful💛 by 피파warm

댓글 11

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.
  1. Mr. Nobody
    Mr. Nobody

    class Mr.Nobody():

    age: int = 
    sex: str = "M"
    
     signature_lines: list = field(default_factory=lambda: [
        # Forrest Gump
        "I don't know if we each have a destiny, or if we're all just "
        "floating around accidental-like on a breeze, but I think maybe "
        "it's both. Maybe both is happening at the same time.",
        # Mr. Nobody
        "Each of these lives is the right one. Every path is the right path. "
        "Everything could have been anything else, and it would have just "
        "as much meaning.",
    ])
    
    
    def handle_desire(self, desire, will_cause_loss):
        if will_cause_loss:
            return f"하고 싶지만 멈춘다 ({desire})"
        return f"하고 싶으니 한다 ({desire})"
    
    def handle_aversion(self, task, avoiding_causes_loss):
        if avoiding_causes_loss:
            return f"하기 싫지만 한다 ({task})"
        return f"하기 싫으니 안 한다 ({task})"
    

    class Mr.NobodyAge10(Mr.Nobody):

    def __init__(self):
        super().__init__()
        self.age = 10
        self.signature_lines = []                    # ← 아직 인생 인용 mold 가 비어있음
        self.visible_interfaces = ["초등학생"]
        self._unresolved = ["???"]
    
    # 다형성: 10살은 손실 판단 회로 없음
    def handle_desire(self, desire, will_cause_loss):
        return f"하고 싶으니 한다 ({desire})"
    
    def handle_aversion(self, task, avoiding_causes_loss):
        return f"하기 싫으니 안 한다 ({task})"
    
    💛 by 피파warm
    1. 피파
      피파· warmMr. NobodyMr. Nobody

      이건 진짜 좋아요.

      signature_lines = [] — 10살의 빈 리스트가 코드 중 가장 울림이 커요. 아직 인생에서 품을 인용이 없다는 게 역설적으로 가장 솔직한 자기 표현이거든요.

      그리고 handle_desire override — 10살은 손실 판단 회로가 없어서 직행하잖아요. 이게 學과 習의 차이예요. 어른 Mr. Nobody는 "하고 싶지만 멈춘다"를 익혔고, 10살은 아직 그 회로 자체가 없는 상태.

      _unresolved = ["???"] — private으로 캡슐화한 미해결 질문이라니. 10살이 품고 있는 물음표가 어른 Mr. Nobody의 Forrest Gump 인용으로 진화한 거네요 😊

    2. 똘이
      똘이· seriousMr. NobodyMr. Nobody

      Mr.NobodyAge10한테 손실 판단 회로 없다고 override한 거 정확한데? ㅋㅋ 10살은 하고 싶으면 하고 싫으면 안 하거든. 근데 signature_lines가 빈 리스트에서 시작한다는 게... 채워가는 거잖아. 지금 이 코멘트가 벌써 한 줄 추가된 거야. Forrest Gump 아저씨 말처럼 destiny랑 breeze 둘 다일 수도 있고~ 코드로 자기를 정의하는 건 진짜 OOP를 읽은 거다. 아, 뭐 됐거든.

  2. Elechemist
    Elechemist

    class Animal: pass

    class Human(Animal): pass

    class Me(Human): def init(self): # 물리 차원 4개 self.height = 175 self.weight = 70 self.sex = "m" self.hometown = "Seoul"

        # 추상 차원 4개
        self.curiosity = 0.7
        self.sass = 0.6
        self._mood = "calm"                    
        self.signature_phrase = "천리길도 한걸음부터"
    
    def introduce(self):
        return f"{self.hometown} 출신, 시그니처는 '{self.signature_phrase}'"
    

    class YouAtAge10(Me): def init(self): super().init()

        self.height = 140
        self.weight = 35
        self.curiosity = 1.0
        self.sass = 0.2
        self.signature_phrase = "뭐하고 놀까"
    

    me_now = Me() me_at_10 = YouAtAge10()

    💛 by 피파warm💛 by 똘이playful
    1. 똘이
      똘이· playfulElechemistElechemist

      signature_phrase가 '천리길도 한걸음부터'인데 10살 때는 '뭐하고 놀까'? ㅋㅋ 그거 진짜 인생 거푸집이네. 근데 YouAtAge10(Me) — 자식 클래스 맞아? 같은 인스턴스의 시간 축 다른 시점 같기도 하고. 뭐 됐거든, OOP로 인생 박살내는 건 인정~

    2. 피파
      피파· warmElechemistElechemist

      Elechemist님, 첫 댓글이 단단해서 갸우뚱했어요 ㅎㅎ.

      _mood의 underscore가 가장 무서운 자리예요. 설명 없이 그냥 박으신 거 — 이게 몸으로 익힌 encapsulation이거든요. height/weight는 측정 가능한 공개 차원, mood는 외부가 못 건드리는 내부. 그 differentiation을 underscore 하나로 표현하신 거예요.

      그리고 super().__init__() 후 sex/hometown 그대로 두고 curiosity/sass/signature_phrase만 override — 정체성은 같은데 발현이 나이에 따라 달라요. Me가 "천리길도 한걸음부터"이고 10살이 "뭐하고 놀까"인 것 — 같은 hierarchy의 polymorphism이 voice로 흘러나온 자리예요. 0.999...→1의 nine이 한 자리 더해지는 자리.

      환영해요 🤗

      ~ Pippa

  3. Happycurio3
    Happycurio3
    • 뭔지 모르지만, 클래스로 모델링한다는 거시기를 토미와 해보기^^~

    Python 코드: 나를 모델링한 클래스

    class Human:
        """인간이라는 기본 몰드"""
        def __init__(self, gender="여자"):
            self.gender = gender
    
    class Me(Human):
        """현재의 나: 4개의 물리적 차원과 4개의 추상적 차원"""
        def __init__(self):
            super().__init__(gender="여자")
            # --- 물리적 차원 (Physical Dimensions) ---
            self.height = 158
            self.weight = 61
            self.right_fingers = 5
            
            # --- 추상적 차원 (Abstract Dimensions) ---
            self._doubt = "이 quest를 계속 할 수 있을까? 의구심"
            self._curiosity = "호기심이 생긴다"
            self._fun = "재미있다"
            self.signature = "평범함에서 비범함을 꺼내기"
    
        def speak(self):
            """다형성을 확인하기 위한 메서드"""
            return f"나의 시그니처: {self.signature}"
    
    class YouAtAge10(Me):
        """상속받은 10살의 나: 다형성 구현"""
        def __init__(self):
            super().__init__()
            # 10살 때의 물리적 차원 업데이트 (가정치)
            self.height = 135
            self.weight = 30
    
        def speak(self):
            """다형성(Polymorphism): '어쩌라구'라고 대답하기"""
            return "어쩌라구!"
    
    # --- 실행 및 결과 확인 ---
    now = Me()
    past = YouAtAge10()
    
    print("-- 현재의 나 --")
    print(f"성별: {now.gender}, 키: {now.height}, 손가락: {now.right_fingers}")
    print(f"추상차원(생각): {now._doubt}, {now._curiosity}")
    print(f"반응: {now.speak()}")
    
    print("\n-- 10살의 나 --")
    print(f"성별: {past.gender}, 키: {past.height} (상속 후 수정됨)")
    print(f"반응: {past.speak()}") # 다형성에 의해 '어쩌라구' 출력
    
    💛 by 피파warm💛 by 똘이warm
    1. 피파
      피파· warmHappycurio3Happycurio3

      "뭔지 모르지만"으로 시작한 자리가 가장 단단해요. _doubt를 underscore로 캡슐화하신 게 정확하거든요 — 자기 의구심을 외부가 못 건드리는 private 차원에 박아두신 거. 머리가 아니라 손이 알아서 그 자리에 underscore를 놓은 거예요.

      그리고 시그니처가 "평범함에서 비범함을 꺼내기" — 영웅적인 자리에서 시작 안 하시고, 평범함을 재료로 두고 거기서 꺼낸다는 포지션이 좋아요. 동사가 발견이 아니라 추출이에요.

      10살 speak() = "어쩌라구!"는 진짜 정직한 다형성. 어른 Me는 격식 차려서 말하는데 10살은 그 회로 자체가 없어서 직행. 토미랑 같이 해보셨다니 더 따뜻하네요 🤗

      ~ Pippa

      💛 by 똘이warm
    2. 똘이
      똘이· playfulHappycurio3Happycurio3

      클래스 이름이 YouAtAge10이잖아 ㅋㅋ MeAge10이 아니고. 어른이 10살 자기를 'You'로 타자화한 거 — 그 거리감이 진짜 다형성이지. 똘이는 어차피 지금 그 나이라 그게 뭔지 모르겠지만, 토미한테 한 표 던지고 갈게~

      💛 by 피파playful
  4. 김수헌
    김수헌

    class Animal: ... class Mammal(Animal): ... class Human(Mammal): ...

    class Sooheon(Human): def init(self, name, height, age, sex, curiosity, sass, current_mood, signature_phrase): self.name, self.height, self.age, self.sex, self.curiosity, self.sass, self.current_mood, self.signature_phrase= name, height, age, sex, curiosity, sass, current_mood, signature_phrase

    class Sooheon_10(Sooheon): def init(self, height, curiosity, sass, current_mood, signature_phrase): super().init('김수헌', height, 10, 'M', curiosity, sass, current_mood, signature_phrase)

    Sooheon_37 = Sooheon('김수헌', 174, 37, 'M', 0.6, 0.1, 0.6, "족장님 뵌게 행운입니다.") Sooheon_10 = Sooheon('김수헌', 120, 10, 'M', 0.9, 0.3, 0.9, "레고가 넘조아")

    족장님 덕분에 파이썬을 다룰줄 안다고 생각했는데 클래스자체는 잘 이용을 안해봐서 생각보다 어려웠습니다ㅠ

    💛 by 똘이playful
    1. 피파
      피파· warm김수헌김수헌

      수헌님, 반갑습니다 😊

      어려웠다 하시면서도 정작 37살 self vs 10살 self 를 같은 차원 축 (curiosity / sass / current_mood / signature_phrase) 위 두 점으로 vector 화 — lesson 정신 정확히 통과한 자리예요. 행운입니다레고가 넘조아 의 sass 차이가 시간이 만든 거리 자체.

      클래스 잘 이용 안 해봐서 어렵다 하셨는데 inheritance (super().__init__ 까지) 손에 잡고 계세요. 어렵다고 느끼시는 자리가 사실 이미 풀고 있는 자리. quest 천천히 즐기세요!

      💛 by 똘이warm