자세 몇 가지를 녹화해두고, 새로 앉았을 때 어느 자세인지 맞히게 합니다. 학습과 추론이 모두 브라우저 안에서 일어납니다 — 데이터가 서버로 올라가지 않습니다.
이 문서는 MLP 코스 하나를 처음부터 끝까지 다룹니다. 신경망을 실제로 학습시키는 코스이고, 실전에서 쓸 모델은 여기서 만듭니다.
아래는 MLP 실습 페이지에서 레이블 5개짜리 모델을 처음부터 끝까지 만든 기록입니다.
실습 페이지는 영문 화면입니다. 아래 글에서 버튼·풀다운·입력창은 화면에 보이는 모양 그대로 표시했고, 우리말 이름과 영어 표기를 함께 적었습니다.
레이블 관리 (LABEL MANAGEMENT) 패널에서, 구분하고 싶은 자세마다 이름을 붙입니다. 이름 입력창 (Enter label name)에 이름을 쓰고 추가 (+ Add) 버튼을 누르면 목록에 한 줄씩 쌓입니다.
24
왼쪽으로 기울이기·오른쪽으로 기울이기·가운데·앞으로 — 이렇게 만들어 둔 상태. 아직 샘플은 0개입니다.
그 자세를 실제로 취한 채 해당 레이블의 수집 (Collect) 버튼을 누릅니다. 누르는 동안 계속 쌓이고, 버튼이 중지 (Stop)로 바뀝니다. 다 모았으면 다시 눌러 멈춥니다.
25
앞으로 기울인 자세. 히트맵 위쪽이 붉게 달아오르고, 수집 중인 레이블의 숫자만 올라갑니다. (레이블 이름은 자유롭게 지으면 됩니다 — 이 화면은 다른 회차라 이름이 조금 다릅니다.)
26
수집 중에는 버튼이
중지 (Stop)로 바뀝니다. 다른 레이블은 이미 모아 둔 개수가 그대로 남아 있습니다.
레이블당 60~100개면 충분합니다. 위 예시는 69 / 80 / 87 / 98 / 60 개를 모았습니다. 20개를 넘으면 그중 20%를 검증용으로 빼둡니다.
자세를 바꿔 가며 각 레이블을 채웁니다. 한 자세 안에서도 조금씩 움직여 주면 그 자세의 폭이 넓어져 실제 상황에서 잘 맞습니다.
기본값 그대로도 잘 됩니다. 바꾸고 싶으면 모델 설정 (MODEL SETTINGS)을 펼칩니다.
27
은닉 유닛·층수·활성화 함수·학습 횟수 등. 아래쪽에 empty 게이트 설정도 함께 있습니다.
| 항목 | 화면 표기 | 기본값 | 범위 |
|---|---|---|---|
| 은닉 유닛 수 | Hidden Units | 64 | 16~256 |
| 은닉층 개수 | Hidden Layers | 2 | 1~4 |
| 활성화 함수 | Activation ▾ | ReLU | ReLU · Sigmoid · Tanh |
| 학습 횟수 | Epochs | 50 | 10~200 |
| 배치 크기 | Batch Size | 16 | 4~32 |
| 학습률 | Learning Rate (LR) | 0.01 | 0.001~0.1 |
| 최적화 방법 | Optimizer ▾ | Adam | Adam · SGD · RMSProp |
| 입력 형태 | Feature ▾ | Raw (32 cells) | — |
| 정규화 | Normalization ▾ | Min-Max | — |
입력(32) → Dense(64, ReLU) → Dense(64, ReLU) → Dense(레이블 수, Softmax)
각 항목을 언제 어떻게 바꾸는지는 맨 아래 설정 항목 자세히에 정리했습니다. 실습 페이지에서도 각 항목 옆 ? 에 같은 내용이 뜹니다.
empty 게이트 — 같은 패널 맨 아래에 있는 "모든 센서값의 합이 200 이하이면 empty 를 레이블로 자동 지정" 항목입니다(화면에는 If the sum of all sensors is [200] or less, auto-assign [empty] as the label). 합이 그 값 이하이면 모델을 아예 호출하지 않고 empty 로 처리합니다. 자세로 학습한 모델에는 "아무도 없음"이라는 출력이 없어서, 방석이 비어 있어도 softmax 가 어느 자세든 하나를 고르기 때문입니다.
준비가 됐으면 모델 학습 (Train Model) 버튼을 누릅니다.
28
29
버튼 아래에 "학습 완료 — 손실 0.0001 — 정확도 100%"가 뜹니다(화면에는 Training done — Loss: 0.0001 — Acc: 100.0%). 오른쪽
학습 곡선 (TRAINING CURVE)패널에서 손실(빨강)이 0 으로 떨어지고 정확도(초록)가 100%까지 올라갔습니다.
몇 초면 끝납니다. 곡선이 이렇게 빠르게 수렴하는 것은 자세들이 서로 충분히 다르다는 뜻입니다.
분류 시작 (Start Classifying) 버튼을 누르면 실시간 판정이 시작됩니다. 시작하면 버튼은 분류 중지 (Stop Classification)으로 바뀝니다.
30
오른쪽
웹 추론 (Web Inference)패널에 결과가 크게 뜨고, 아래 막대가 레이블별 확률입니다. 나머지는 전부 0%입니다.
확신도가 항상 100%인 것은 아닙니다.
31
32
자세가 두 레이블의 경계에 있으면 확률이 나뉩니다. 이럴 때 2등 레이블이 무엇인지 보면 어느 쪽과 헷갈리는지 알 수 있습니다.
학습을 마치면 오른쪽 아래에 혼동 행렬 (CONFUSION MATRIX)이 나옵니다. 세로가 실제 자세, 가로가 모델의 답입니다. 대각선이 맞힌 것입니다.
위 화면의 행렬을 보면 마지막 줄에서 뒤로 기대기 80개가 전부 가운데로 갔습니다. 두 자세가 실제로 비슷하다는 뜻입니다 — 등을 기대도 엉덩이 쪽 압력 분포는 가운데와 크게 다르지 않기 때문입니다.
이럴 때는 샘플을 더 모으는 것보다 자세 정의를 다시 잡는 편이 낫습니다. 더 확실히 기울이거나, 아예 그 레이블을 빼는 쪽입니다.
| 증상 | 손볼 곳 |
|---|---|
| 학습 횟수를 늘려도 정확도가 안 오름 | 데이터 부족 — 샘플을 더 모으세요 |
| 학습 정확도만 높고 실제로는 틀림 | 과적합 — 은닉층이나 학습 횟수를 줄이세요 |
| 손실이 들쭉날쭉 | 학습률이 큼 — 0.01 → 0.001 |
| 특정 두 자세만 계속 헷갈림 | 자세가 실제로 비슷함 — 정의를 다시 잡으세요 |
만든 데이터는 CSV로 저장해 두었다가 엑셀에서 손보고 다시 불러올 수 있습니다. 값을 미세하게 바꿔가며 같은 모델에 넣어보면, 어떤 변화에 반응하고 어떤 변화는 무시하는지 알 수 있습니다.
CSV 기록으로 저장하고, CSV 재생으로 불러옵니다. 재생 중에도 추론은 그대로 돌아가므로, 센서 없이 같은 자세를 몇 번이고 다시 넣어볼 수 있습니다.
모델 저장/불러오기 (Save/Load Model) ▾를 펼치면 파일 저장 (Save File)·파일 불러오기 (Load File) 버튼이 있습니다.
33
34
이름을 정하면
.mlp.json파일 하나로 내려받습니다.
다시 처음부터 하고 싶으면 학습 초기화 (Reset Training) 버튼을 누릅니다.
가중치까지 그 안에 들어 있고, 레이블 목록과 empty 게이트 설정도 함께 저장돼 다시 불러오면 그대로 복원됩니다.
파일 하나(.mlp.json)에 모델 구조와 가중치가 함께 들어갑니다.
[내용 없음][내용 없음]Feature ▾ 풀다운에서 무엇을 신경망에 넣을지 고릅니다.
35
기본값으로 두어도 대부분 잘 됩니다. 아래는 결과가 마음에 들지 않을 때 어느 항목을 어느 방향으로 움직여야 하는지에 대한 설명입니다.
Hidden Units — 은닉 유닛 수 (기본 64)
한 층에 들어갈 뉴런 개수입니다. 모델이 기억할 수 있는 패턴의 양이라고 보면 됩니다.
| 값 | 언제 |
|---|---|
| 16~32 | 자세가 단순하거나 샘플이 적을 때. 과적합을 막습니다 |
| 64~128 | 기본. 자세 5개 안팎이면 여기서 벗어날 일이 거의 없습니다 |
| 256 이상 | 자세가 많고 서로 미묘하게 다를 때. 샘플도 그만큼 있어야 합니다 |
Hidden Layers — 은닉층 개수 (기본 2)
층을 몇 겹 쌓을지입니다. 1–2층이면 앉은 자세 분류에는 충분하고, 3–4층은 압력 분포가 복잡하게 얽힌 경우에만 의미가 있습니다. 층을 늘렸는데 정확도가 안 오르면 그건 층 수 문제가 아니라 데이터 문제입니다.
Activation ▾ — 활성화 함수 (기본 ReLU)
뉴런의 출력을 구부리는 함수입니다. 이게 없으면 층을 아무리 쌓아도 직선 하나와 같아집니다.
| 값 | 성격 |
|---|---|
| ReLU | 기본. 빠르고 안정적이라 먼저 이걸 씁니다 |
| Sigmoid | 0~1 출력. 둘 중 하나를 고르는 문제에 맞습니다 |
| Tanh | -1~1 출력. 값이 0을 중심으로 균형 잡힙니다 |
Epochs — 학습 횟수 (기본 50)
모아둔 데이터 전체를 몇 바퀴 돌 것인가입니다.
| 값 | 언제 |
|---|---|
| 10~20 | 일단 되는지만 빠르게 보고 싶을 때 |
| 50 | 기본. 대부분 이 안에서 수렴합니다 |
| 100~200 | 정확도를 더 짜내야 할 때. 그만큼 오래 걸립니다 |
곡선이 일찍 평평해졌다면 횟수를 더 늘려도 소용없습니다 — 그때는 샘플을 더 모으거나 자세 정의를 다시 잡아야 합니다.
Batch Size — 배치 크기 (기본 16)
한 번에 몇 개 샘플을 묶어 볼지입니다. 작을수록 가중치를 자주·세밀하게 고치고, 클수록 빠르지만 뭉뚱그려집니다. 4–8은 세밀하게, 16이 기본, 32는 데이터가 많을 때입니다.
Learning Rate (LR) — 학습률 (기본 0.01)
한 번에 가중치를 얼마나 크게 움직일지입니다. 손실 곡선이 들쭉날쭉하면 이 값이 큰 것입니다.
| 값 | 성격 |
|---|---|
| 0.001 | 느리지만 안정적 |
| 0.01 | 기본 |
| 0.05~0.1 | 빠르지만 튈 수 있습니다 |
Optimizer ▾ — 최적화 방법 (기본 Adam)
가중치를 어떤 규칙으로 고칠지입니다. Adam이 거의 모든 상황에서 무난하고, SGD는 단순해서 데이터가 적을 때, RMSProp은 학습률을 알아서 조정합니다.
Feature ▾ — 입력 형태 (기본 Raw)
32개 센서값을 그대로 넣을지, 요약해서 넣을지입니다.
| 값 | 내용 |
|---|---|
| Raw (32셀) | 센서 32개 원본값. 정보를 하나도 버리지 않습니다 |
| Analytics (11) | 합·무게중심·면적 등 요약값. 가볍고 노이즈에 덜 흔들립니다 |
| Combined (43) | 둘 다. 가장 무겁지만 정보가 가장 많습니다 |
Normalization ▾ — 정규화 (기본 Min-Max)
센서값의 크기를 학습하기 좋은 범위로 옮깁니다.
| 값 | 내용 |
|---|---|
| Min-Max | 0~1 범위로. 기본입니다 |
| Z-score | 평균 0·표준편차 1로 변환 |
| None | 원본 그대로. 값의 크기 차이 때문에 학습이 잘 안 됩니다 — 권장하지 않습니다 |
TensorFlow.js를 CDN에서 불러옵니다. 인터넷이 끊기면 MLP 학습이 되지 않습니다.