17장. Batch Processing 과 YOLO 데이터 준비
YOLO 데이터셋의 짜임
학교 사물함을 떠올려 봅시다. 학생마다 번호가 같은 칸이 두 줄로 있어서, 위 칸에는 교과서, 아래 칸에는 체육복을 넣는다고 하면 "17번 학생의 체육복"은 바로 찾습니다. YOLO 데이터셋도 이렇게 짭니다. 그림은 images/ 칸에, 라벨은 labels/ 칸에 넣고, 같은 그림의 라벨은 확장자만 다른 같은 이름으로 둡니다.
그림의 맨 위가 데이터셋 폴더이고, 그 아래로 images/ 와 labels/ 가 갈라집니다. 둘 다 안에 train/ 과 val/ 이 있습니다. 보라 선은 images/train/part_002.png 의 라벨이 labels/train/part_002.txt 라는 짝을 보여 줍니다. 여기서 사물함 번호가 파일 이름, 위 칸과 아래 칸이 images/ 와 labels/ 입니다. data.yaml 은 사물함 앞의 안내판처럼 폴더의 자리와 클래스 이름을 적어 둡니다.
지킬 약속
| 약속 | 이렇게 한다 | 예 |
|---|---|---|
| 같은 이름 | 그림과 라벨은 확장자만 다르다 | part_002.png ↔ part_002.txt |
| 같은 자리 | images/ 를 labels/ 로 바꾼 자리에 라벨을 둔다 | images/val/… ↔ labels/val/… |
| 한 줄에 물체 하나 | 클래스번호 xc yc w h 를 빈칸으로 나눈다 | 1 0.506250 0.481250 0.112500 0.170833 |
| 클래스 번호 | 0 부터 센다. names 의 차례와 같다 | 0: bolt, 1: nut, 2: washer |
| 숫자 | 0~1 의 비율, 소수 여섯째 자리 | 0.333333 |
학습용과 검증용으로 나누기
왼쪽 카드의 학습용 데이터는 모델이 보고 배우는 연습 문제이고, 오른쪽 카드의 검증용 데이터는 배운 뒤에 처음 보는 모의고사입니다. 연습 문제를 그대로 모의고사로 내면 외운 것인지 이해한 것인지 알 수 없습니다. 그래서 같은 그림이 두 쪽에 함께 들어가면 안 됩니다. 이 장에서는 그림을 8:2 로 나누고, 다시 돌려도 같게 나뉘도록 씨앗을 고정합니다.
data.yaml
data.yaml 은 YAML 형식의 글자 파일입니다. 이름: 값 꼴로 적고, 들여쓰기로 아래 항목을 묶습니다.
| 항목 | 뜻 | 이 장의 값 |
|---|---|---|
path | 데이터셋 폴더 | out_ch17_yolo (data 폴더에서 실행할 때의 상대 경로) |
train | path 아래 학습용 그림 폴더 | images/train |
val | path 아래 검증용 그림 폴더 | images/val |
names | 클래스 번호와 이름 | 0: bolt, 1: nut, 2: washer |
# data.yaml 은 PyYAML 같은 패키지 없이 글자로 직접 쓸 수 있다
names = ["bolt", "nut", "washer"]
lines = ["path: out_ch17_yolo", "train: images/train", "val: images/val", "names:"]
lines += [f" {k}: {name}" for k, name in enumerate(names)]
print("\n".join(lines))
# 라벨 한 줄: 클래스 번호와 비율 넷을 빈칸으로 잇는다. :.6f 는 소수 여섯째 자리까지
cls, xc, yc, w, h = 1, 0.50625, 0.48125, 0.1125, 41 / 240
print(f"{cls} {xc:.6f} {yc:.6f} {w:.6f} {h:.6f}")f"{xc:.6f}" 의 .6f 는 "소수점 아래 여섯 자리의 실수(fixed-point)로" 라는 뜻입니다. 41 ÷ 240 = 0.1708333… 은 반올림해 0.170833 으로 적힙니다.
주의할 점
- 라벨 폴더의 이름은 반드시
labels입니다. YOLO 는 그림 경로의images를labels로 바꿔 라벨을 찾기 때문에, 다른 이름을 쓰면 라벨이 없는 것으로 봅니다. - 클래스 번호와
names의 차례가 어긋나면 모델이 볼트를 너트라고 배웁니다. 번호를 정한 표 하나를 모든 코드에서 같이 씁니다.