5-2의 숙제는 "손잡이(잠재 변수)[주]는 어디서 오나"였다. 이번에는 데이터만 보고 손잡이를 찾는다. 막대 인형 장면 600개로 숫자 1,196개를 k개로 접는 인코더와, k개를 다시 1,196개로 펼치는 디코더를 만든다. 숫자 16개로 접었다 펴도 동작의 99.8%가 돌아온다. 그리고 그 접힌 숫자로 떨림을 지우고, 가려진 팔꿈치를 채우고, 5-1의 투기 탐지를 적은 데이터로 더 정확하게 하고, 5-2의 생성을 손잡이 없이 해낸다.
5-2의 생성기 D는 손잡이 세 개(속도·위치·크기)를 미리 알고 있어서 이겼다. 실제 데이터에는 손잡이가 붙어 오지 않는다. 이번 미션은 장면 600개만 보고 손잡이를 스스로 찾는 것이다.
왼쪽 원본을 인코더가 숫자 k개(가운데 보라 막대)로 접고, 디코더가 다시 1,196개로 펼친다(오른쪽). 병목 크기 k를 줄여 가며 어디까지 접을 수 있는지 보자.
| 병목 k | 압축 비율 | 설명한 분산 | 복원 오차 (RMSE) | 뼈 길이 오차 |
|---|---|---|---|---|
| 1 | 1,196배 | 85.72% | 0.1021 | 6.16% |
| 2 | 598배 | 95.07% | 0.0598 | 7.65% |
| 3 | 398.7배 | 97.84% | 0.0395 | 2.78% |
| 5 | 239.2배 | 99.02% | 0.0266 | 1.95% |
| 8 | 149.5배 | 99.46% | 0.0195 | 1.86% |
| 16 | 74.8배 | 99.80% | 0.0123 | 1.50% |
| 32 | 37.4배 | 99.90% | 0.0088 | 1.43% |
시험 장면에는 포즈 추정의 떨림(σ = 0.008)이 섞여 있다. k = 32의 오차 0.0088은 그 떨림 크기와 거의 같다. 그 아래로는 동작이 아니라 떨림을 외우게 된다.
장면 600개를 모아 "동작이 가장 크게 달라지는 방향"을 차례로 찾았다(주성분 분석, PCA). 인코더는 장면에서 평균 장면을 빼고 이 방향 k개에 비춰 숫자 k개를 얻는다. 디코더는 평균 장면에 방향 k개를 그 숫자만큼 더한다. 더하기와 곱하기뿐인 가장 단순한 오토인코더다. 신경망으로 만든 오토인코더는 층과 활성함수를 써서 휘어진 관계까지 담는다(3-7). 이 페이지의 방향 16개는 코드 1이 계산한 값을 그대로 실었다.
장면 600개를 손잡이 1·2로 찍은 지도다. 점을 눌러 장면을 고르고, 아래 손잡이 네 개를 돌려 보자. 손잡이에는 이름이 없다. 무엇이 바뀌는지 보고 직접 이름을 붙여 보자.
같은 종류의 장면은 지도에서 가까이 모인다. 아무도 "이건 던지기"라고 알려 주지 않았는데, 접기만 했는데도 그렇다. 손잡이 값은 학습 장면들의 표준편차(σ) 단위다. ±2σ 밖은 학습 데이터에 거의 없던 영역이라 펼친 모양이 어색해진다.
| 손잡이 | 가장 크게 움직이는 곳 | 관찰해서 붙인 별명 | 장면별 평균 (코드 1) |
|---|---|---|---|
| 1 (움직임의 85.7%) | 모든 관절의 x, 장면 후반 | "끝날 때 어디에 있나" — 통 앞에 남는가, 오른쪽으로 걸어 나가는가 | 넣기 −15.3 · 던지기 +8.3 · 지나가기 +6.4 · 떨어뜨리기 +6.7 |
| 2 (9.4%) | 오른손목·팔꿈치와 발목의 x, 장면 초반 | "처음에 어디서, 오른팔을 어느 쪽에 두고 시작하나" | 지나가기 −4.4 · 손 흔들기 +4.1 |
| 3 (2.8%) | 오른손목·팔꿈치·머리의 y | "팔을 드는가, 허리를 숙이는가" | 손 흔들기 +2.6 · 줍기 −2.1 |
| 4 (1.2%) | 오른손목과 발목의 x, 장면 중반 | "가운데 시간의 팔·다리 좌우 흔들림" | 줍기 +1.3 · 던지기 −0.9 |
5-2의 손잡이(속도·위치·크기)는 사람이 장면을 만들 때 정한 것이었다. 여기의 손잡이는 데이터가 가장 크게 달라지는 방향을 차례로 뽑은 것이다. 그래서 이름이 없고, 손잡이 하나에 여러 뜻이 섞여 있다(손잡이 1은 위치이면서 "걸어 나갔나"이기도 하다). 대신 사람이 아무것도 알려 주지 않아도 찾을 수 있다. 이것이 잠재 공간이다.
실제 포즈 추정은 관절 점이 떨리고, 팔이 몸에 가리면 점을 놓친다. 깔때기는 "사람 동작처럼 생긴 것"만 통과시키므로, 접었다 펴면 떨림은 걸러지고 빈칸은 그럴듯하게 채워진다.
떨림 σ = 0.01이면 오차 0.0100 → 0.0082, σ = 0.03이면 0.0300 → 0.0090, σ = 0.05면 0.0501 → 0.0104. 떨림이 클수록 효과가 크다. 떨림은 방향이 제멋대로라 깔때기의 방향 16개에 거의 걸리지 않기 때문이다.
보이는 칸만으로 잠재 숫자 16개를 최소제곱으로 맞춘 뒤 디코더로 펼치면, 빈칸까지 채워진다. 위치 오차는 "어깨와 손목의 중간점으로 때우기" 0.0230 대 "디코더로 채우기" 0.0108, 약 2.1배 정확하다. 5-1에서 말한 "팔이 몸에 가리면 관절을 못 찾는다"를 이렇게 메운다.
5-1에서 "좌표를 그대로 학습하면 데이터가 훨씬 많이 필요하다"고 했다. 이번에는 관절과 캔의 좌표(1,288개)를 먼저 인코더로 접고, 접힌 숫자 k개로 가장 단순한 로지스틱 회귀를 학습한다.
| 학습 장면 (종류당) | 1,288개 그대로 + MLP | k = 8로 접고 + 로지스틱 회귀 | k = 16으로 접고 + 로지스틱 회귀 |
|---|---|---|---|
| 25 (전체 150) | 96.7% | 95.0% | 99.7% |
| 50 (전체 300) | 97.0% | 95.3% | 100.0% |
| 100 (전체 600) | 98.0% | 98.0% | 100.0% |
k = 16 + 로지스틱 회귀: 종류당 25개(전체 150개)만으로 시험 300개 중 299개를 맞혔다. 숫자 16개 속에 "캔이 끝에 어디 있나"와 "사람이 어디로 갔나"가 함께 접혀 있어서, 직선 하나로도 가를 수 있게 된 것이다.
k = 8은 모자라다: 캔의 마지막 위치처럼 작은 움직임은 9번째 이후 방향에 들어 있어, 8개로 접으면 일부가 빠진다. 무조건 많이 접는 것이 답은 아니다.
5-1의 92.3%와 다른 이유: 5-1은 "물체 없음"을 좌표 −9로 표시했고, 여기서는 (0, 0)으로 표시했다. 입력 표시만 바꿔도 MLP가 98%까지 오른다. 이 표의 세 열은 모두 같은 입력으로 비교했다.
인코더는 이름표 없이 장면만 보고 만들었다(600개를 모두 썼지만 투기·정상 정답은 보지 않았다). 그렇게 얻은 "동작의 요약"은 잡음이 걸러지고 숫자가 적어서, 정답이 붙은 장면이 적어도 분류기가 헤매지 않는다. 이름표 없는 데이터로 표현을 먼저 배우고, 적은 정답으로 마무리하는 방식은 오늘날 큰 모델 학습의 기본 흐름과 같다. 단, 이 숫자는 합성 데이터 결과다. 실제 영상에서는 이보다 낮다.
5-2의 감독관이 다시 왔다. 이번 생성기 E는 사람이 정한 손잡이를 모른다. 잠재 지도에서 던지기들이 모인 자리(평균과 표준편차)를 보고 새 점 16개를 뽑아 디코더로 펼친다.
| 생성기 | 손잡이를 미리 아나 | 뼈 길이 오차 | 떨림 | 손목 최대 속도 | 다양성 | 새로움 |
|---|---|---|---|---|---|---|
| A 평균 하나 | — | 1.7% | 0.0045 | 1.36 | 0.000 | 0.033 |
| B 좌표마다 주사위 | — | 44.2% | 0.2659 | 10.00 | 0.149 | 0.109 |
| C 하나 골라 복사 | — | 4.7% | 0.0300 | 2.75 | 0.125 | 0.000 |
| D 손잡이 3개 뽑기 | 안다 (사람이 정함) | 0.0% | 0.0125 | 2.71 | 0.123 | 0.022 |
| E 잠재 16개에서 뽑기 | 모른다 (데이터가 찾음) | 3.7% | 0.0122 | 1.76 | 0.114 | 0.047 |
E가 해낸 것: 손잡이를 모르고도 B처럼 부서지지 않는다(뼈 오차 44.2% → 3.7%, 떨림 0.27 → 0.012). 다양하고(0.114), 베끼지도 않았다(0.047).
E가 못 한 것: 손목 최대 속도가 1.76으로, 던지는 힘이 빠졌다. 잠재 공간에서 평균 근처를 뽑고 직선 방향들을 더하기만 하니, 빠르게 휘두르는 짧은 순간이 뭉개진다. 뼈 길이도 진짜(0%)만큼 정확하지는 않다.
인코더·디코더는 탐지와 생성 양쪽을 끌어올렸다. 그래도 남은 것이 있다.
두 코드 모두 Colab에 기본으로 설치된 라이브러리만 쓴다. "노트북(.ipynb) 내려받기" 후 Colab에서 파일 → 노트북 업로드로 열거나, 복사해서 새 노트북 칸에 붙여 넣는다.
장면 600개로 encode·decode를 만들고, k별 복원 오차, 떨림 지우기, 가려진 팔꿈치 채우기(fill)를 잰다. 이 페이지의 방향 16개가 여기서 나왔다. 내 데이터로 바꾸려면 S 자리에 (장면 수, 숫자 수) 모양의 내 데이터를 넣는다. 센서·로그 데이터도 같은 방식으로 접을 수 있다.
5-1의 투기 탐지를 "그대로 MLP" 대 "접고 로지스틱 회귀"로 학습 장면 수를 바꿔 비교하고, 5-2의 감독관 채점으로 생성기 E를 잰다. 섹션 5·6의 표가 이 출력에서 바로 만들어진다.
ChatGPT, Qwen, Claude 같은 AI 도우미에 붙여 넣는 프롬프트다. "복사"를 누르면 프롬프트 뒤에 고른 코드가 함께 붙는다. 〔 〕 안을 내 상황으로 바꿔 쓰면 된다.
AI의 답은 출발점일 뿐이다. 제안된 논문·수치·라이브러리 함수는 반드시 원문과 공식 문서로 확인한다. 실제 사람의 동작 데이터를 쓸 때는 촬영 동의와 데이터셋의 이용 조건을 먼저 확인한다.
본문의 노란 점선 밑줄과 같은 사전이다. 섹션 이름을 누르면 처음 나온 곳으로 간다.
비유는 이해의 첫걸음이지만 오해의 씨앗도 된다. 사람의 지각과 견준 비유에는 강도를 표시했다. 직접 실제로 같은 일을 한다는 근거가 있음 · 부분 일부 성질만 닮음 · 없음 대응하는 것이 알려지지 않음
| 개념 | 일상 비유 | 사람의 지각 비유 | 비유가 틀리는 지점 |
|---|---|---|---|
| 인코더·디코더 | 여행 가방에 옷을 접어 넣었다가 숙소에서 펴기 | 부분 긴 춤 동작을 "왼발, 박수, 돌기"처럼 몇 마디로 기억했다가 다시 추기 | 옷은 접어도 그대로지만, 깔때기는 작은 주름(떨림)을 버린다. 버린 것은 다시 펼쳐도 돌아오지 않는다 |
| 병목 크기 k | 요약문의 글자 수 제한 | 없음 | 요약은 사람이 중요한 것을 고르지만, 이 깔때기는 "크게 달라지는 것"을 고른다. 작지만 중요한 차이(캔의 마지막 위치)를 놓칠 수 있다 |
| 잠재 공간 | 음식점을 "가격 · 매운 정도" 두 축의 지도에 찍기 | 없음 | 음식점 지도의 축은 사람이 정하지만, 잠재 공간의 축은 데이터가 정하고 이름이 없다 |
| 가림 복원 | 지워진 글자를 앞뒤 문맥으로 짐작해 읽기 | 부분 가려진 팔도 몸 전체의 자세로 짐작하는 사람의 지각 | 짐작은 학습한 동작의 범위 안에서만 맞는다. 처음 보는 자세면 아는 자세 쪽으로 틀리게 채운다 |
| 잠재 공간에서 뽑기 | 지도에서 "이 동네 근처"를 찍어 가 보기 | 없음 | 지도의 빈 땅(학습 데이터가 없던 곳)을 찍으면 이상한 곳에 도착한다 |
E-1 저자 소개 · E-2 학술 레퍼런스 · E-3 그림과 숫자의 출처
강사, 실무 OJT 담당자, 튜터를 위한 운영 안내다. 시간은 예상치이므로 실제 수업에 맞춰 조정한다.
| 대상 | 5-1·5-2를 마친 대학생·직장인. 센서·영상·로그처럼 크고 잡음 많은 데이터를 다루는 실무자 |
|---|---|
| 선수 지식 | 5-2의 "동작은 표다"와 생성기 채점, 벡터의 내적(같은 자리끼리 곱해 더하기) |
| 학습 목표 | ① 인코더·디코더와 병목 k의 뜻을 깔때기 그림으로 설명한다 ② 접었다 펴기가 떨림 제거·가림 복원·적은 데이터 학습·생성에 각각 어떻게 쓰이는지 예를 든다 ③ 선형 인코더의 한계와 VAE가 필요한 이유를 말한다 |
| 예상 시간 | 읽기 35~45분 · 애니메이션 시연 25분 · Colab 실습 30분 (코드 1 10분, 코드 2 실행 1분 + 해석 19분) |
도입 5분(섹션 1, 5-2의 숙제) → 섹션 2 깔때기 k 줄이기 12분 → 섹션 3 손잡이 돌리기 10분 → 섹션 4 떨림·가림 8분 → 섹션 5·6 표 읽기 10분 → 확인 문제 5분.
섹션 2 15분 → 우리 데이터(센서, 로그)의 "숫자 수"와 "실제로 독립적인 숫자 수" 토론 15분 → 섹션 4·5로 잡음 제거·적은 정답 학습 사례 20분 → 코드 1에 우리 데이터 넣기 30분 → 섹션 7 한계 정리 10분.
입문자는 섹션 2·4만. 중급자는 코드 1의 encode·decode를 손으로 따라가게 한 뒤, 섹션 3의 손잡이 1이 왜 "끝날 때의 위치"인지 Vt[0]을 그려 확인하게 한다.
| 섹션 | 멈춰서 물어볼 질문 | 조작 팁 |
|---|---|---|
| 2 깔때기 | "숫자 몇 개면 던지기가 던지기처럼 보일까?" | k = 1 → 3 → 8로 올리며 오른쪽 결과를 본다 |
| 3 잠재 지도 | "아무도 알려 주지 않았는데 왜 같은 종류끼리 모였을까?" | 빨간 점(던지기) 하나를 고르고 손잡이 1을 −2σ로 돌린다 |
| 4 떨림·가림 | "깔때기는 떨림과 동작을 어떻게 구별할까?" | σ = 0.05와 팔꿈치 가리기를 함께 켠다 |
| 5 투기 탐지 | "k = 8은 왜 k = 16보다 못할까?" | 표의 25개 줄을 먼저 읽는다 |
| 6 생성 | "E는 D보다 무엇을 덜 알고, 무엇을 덜 잘하나?" | "다시 만들기"를 눌러 손목 최대 속도 칸을 본다 |
| 오해 | 바른 설명 | 보여 줄 장면 |
|---|---|---|
| 압축하면 정보가 줄어 성능이 떨어진다 | 버리는 것이 주로 잡음이면 오히려 좋아진다. 떨림 제거, 적은 데이터 학습이 그 예다 | 섹션 4, 섹션 5 |
| k는 클수록 좋다 | k가 크면 떨림까지 담는다. 작으면 중요한 작은 움직임을 놓친다. 목적에 맞게 고른다 | 섹션 2 표의 k = 32, 섹션 5의 k = 8 |
| 잠재 숫자마다 사람이 이해할 뜻이 있다 | 방향은 데이터가 정하고 이름이 없다. 별명은 사람이 나중에 붙인 해석이다 | 섹션 3 표 |
| 오토인코더는 신경망이어야 한다 | 가장 단순한 선형 오토인코더는 PCA와 같은 일을 한다. 신경망은 휘어진 관계까지 담는다 | 섹션 2 아래 풀이 |
| 잠재 공간의 아무 점이나 뽑으면 그럴듯한 동작이 나온다 | 학습 데이터가 있던 근처만 그렇다. 그 공간을 고르게 만드는 것이 VAE의 일이다 | 섹션 3 ±2σ 밖, 섹션 6 |
1,196 ÷ 16 = 74.75, 약 74.8배. 코드 1에서 설명한 분산은 99.80%다.
인코더: z = (x·v₁, x·v₂) = (3, −2). 디코더: 3v₁ − 2v₂ = (3, −2, 0). 세 번째 값 0.4는 두 방향에 걸리지 않아 사라진다. 이것이 "떨림이 지워지는" 원리다.
팔꿈치는 굽어 있어서 중간점보다 바깥에 있다. 디코더는 장면 600개에서 배운 "이 자세면 팔꿈치는 대개 여기"라는 관계(방향 16개)를 써서 보이는 다른 관절들과 함께 맞춘다. 코드 1에서 오차가 0.0230 → 0.0108로 줄었다.
인코더는 동작의 구조(무엇이 함께 움직이나)만 배워 1,288개를 16개 요약으로 바꿨다. 요약은 잡음이 적고 숫자가 적어서, 정답이 붙은 장면이 150개뿐이어도 단순한 분류기가 헤매지 않는다.
잠재 공간에서 던지기들의 평균 근처를 뽑고, 디코더가 방향들을 직선으로 더하기만 하기 때문이다. 타이밍이 조금씩 다른 빠른 휘두름은 직선 방향 몇 개로 표현되지 않아 뭉개진다. 비선형 디코더나 시간 축을 다루는 모델이 필요하다.
코드 1에서 가리는 관절을 오른팔꿈치에서 왼무릎(9번 → 10번 관절)으로 바꾸고, 가리는 구간을 21프레임에서 40프레임으로 늘린다. 디코더로 채우기의 오차가 어떻게 변하는지 표로 보고한다.
학습에 없는 동작 "넘어지기"(pose 함수에 lean을 1.4까지 키우는 장면)를 만들어, 여섯 종류 장면보다 복원 오차가 얼마나 큰지 잰다. 복원 오차로 "처음 보는 동작" 경보를 만들 수 있는지 기준값과 함께 제안한다.
| 입문자 | 섹션 2의 k 버튼과 섹션 4의 세 그림만으로도 "접었다 펴면 걸러진다"를 얻는다 |
|---|---|
| 심화 | 코드 1의 선형 인코더를 Keras 오토인코더(1,196 → 64 → 16 → 64 → 1,196)로 바꿔 복원 오차와 생성기 E의 손목 속도를 비교하게 한다 |
| 다음 편 | 5-4 단어에서 동작으로 — 말도 같은 지도 위의 점으로 만든다 |
「5-3 인코더·디코더」 편을 끝까지 읽었어요. 연구실 식구들이 한마디씩 정리해 드립니다.