Skip to content
 
 

Latest commit

 

History

27 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LeafScan — 엽채류 판별 모델 연구

엽채류 이미지에서 작물 종류와 생육단계를 판별하는 딥러닝 모델을 연구·개발하는 프로젝트입니다. 이 문서 하나로 설치부터 첫 실험까지 끝납니다.

이 프로젝트는 무엇인가

항목 내용
목적 엽채류 이미지에서 작물 종류와 생육단계를 판별하는 모델을 연구·개발
대상 작물 상추 · 케일 · 겨자채 · 근대 (4종)
생육단계 정식기 · 생육기 · 수확기 (3단계)
문제 유형 이미지 분류 — 백본 공유 멀티헤드 (작물 4 + 단계 3)
프레임워크 PyTorch + torchvision
산출물 학습된 모델 · 연구 기록 · 시각 자료 · 모델 번들

데이터 출처

AI 허브 — 수직농장 통합데이터(엽채류)

항목 내용
형식 이미지 tar + 어노테이션 JSON tar (이미지 1장당 JSON 1개)
구성 {작물}/{training|validation}/{labeled|source}/*.tar
규모 137.59 GB — 아카이브 1개당 177~500장
라벨 JSON 의 crops(작물)·growth_stage(생육단계) — 별도 라벨링 불필요

원본 데이터는 저장소에 커밋하지 않습니다. 용량이 크고 재배포 조건이 있으므로, AI 허브에서 각자 직접 내려받습니다 (03_팀_협업_규약.md §4). 내려받은 tar 를 어디에 두는지는 §4.1, 학습용 인덱스로 바꾸는 방법은 §4.2 에 있습니다.

데이터 구조·JSON 스키마·실측으로 확인한 함정 10선은 04_데이터_명세서.md 에 있습니다.

무엇을 만드는가 — 세 축

산출물은 "정확한 모델 하나"가 아니라 연구 과정 전체입니다.

축 목표
A. 재사용 가능한 뼈대 과제가 바뀌어도 살아남는 학습 하네스. 모델 교체가 config 한 줄
B. 연구 기록 어떤 모델·설정을 만져 정확도를 어떻게 올렸는지가 남습니다
C. 시각 자료 연구 과정에서 보여줄 수 있는 그림이 자동 축적됩니다

핵심 설계를 한 문장으로:

run 이 끝날 때 report.md 와 figures/ 가 자동으로 생기고, 모델은 config 한 줄로 바뀝니다.

어떻게 돌아가는가

lab_gui.py (Tkinter 콘솔)
   │  화면 값을 config.json 으로 저장하고 별도 프로세스를 띄웁니다
   ▼
train_worker.py ──> runs/exp_.../ ──> make_figures.py · make_report.py
   학습                결과 파일            그림 9종 · report.md

콘솔은 학습 로직을 소유하지 않습니다. 값을 config.json 으로 쓰고 프로세스를 띄운 뒤 결과 파일을 읽어 보여줄 뿐이므로, 콘솔 없이 터미널에서 같은 실험이 그대로 재현됩니다.

여러 모델을 같은 조건에서 비교할 때는 run_study.py 가 순차로 돌리고 STUDY.md 에 비교표를 남깁니다. 콘솔의 Study 실행 모드가 이것을 그대로 씁니다.

이 데이터의 함정 네 가지

실험을 시작하기 전에 알아야 합니다. 특히 N2 를 놓치면 그 뒤의 모든 실험이 무의미해집니다.

# 함정 내용
N1 클래스 불균형 수확기가 6% 수준 — 아카이브마다 편차가 극심합니다
N2 개체 단위 시계열 한 개체를 한 달간 27~40장 연속 촬영 → 무작위로 나누면 정확도 99% 같은 헛된 수치가 나옵니다
N3 아카이브별 단계 편중 한 아카이브에 한 단계만 있는 경우가 실제로 존재합니다
N4 생육정지 현상 정식기와 생육기의 외형이 겹쳐 이미지만으로는 원리적으로 구분 불가한 구간이 있습니다

그래서 정확도(accuracy)를 주 지표로 쓰지 않습니다. 생육기가 다수라 전부 생육기로 찍어도 높은 값이 나옵니다. 주 지표는 생육단계 macro-F1 과 정식기 recall 입니다.

문서 안내

문서 언제 읽나
README.md (이 문서) 처음 — 설치·첫 실행·사용법
01_기획서.md 왜 이렇게 하는가 — 목표·모델 전략·평가 지표·연구 계획
02_구조도.md 코드가 어떻게 짜여 있는가 — 계층·레지스트리·산출물 규약
03_팀_협업_규약.md 실험을 시작하기 전에 — run ID·분담·공유 규칙
04_데이터_명세서.md 데이터가 이상할 때 — 구조·JSON 스키마·분할 정책·함정 10선

빠른 시작

git clone https://github.com/PEANUTBUTTER1001/leafscan.git
cd leafscan
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install -r requirements.txt
python scripts/check_env.py
python lab_gui.py

PyTorch 는 GPU 환경에 따라 설치 명령이 다릅니다. §2단계 3 을 반드시 확인하세요.


목차 — 설치와 사용법

§1 → §2 → §3 까지 하면 학습이 한 번 돌아갑니다. 나머지는 필요할 때 찾아보면 됩니다.

§ 내용
1 사전 준비 — 무엇이 필요한가
2 설치 — 5단계
3 첫 실행 — 5분 안에 학습 한 번
4 실제 데이터 연결하기
5 콘솔 사용법
6 실험 한 사이클
7 결과 파일 읽는 법
8 자주 발생하는 문제
9 하지 말아야 할 것
10 도움 받기

1. 사전 준비

1.1 필요한 것

항목 권장 최소 확인 방법
OS Windows 10/11 macOS·Linux도 가능 —
Python 3.11 3.10 ~ 3.12 python --version
Git 최신 — git --version
GPU NVIDIA (VRAM 6GB↑) 없어도 됨 (CPU 학습 가능, 느림) nvidia-smi
RAM 16GB 8GB —

1.2 Python 설치 시 주의사항

Microsoft Store 버전 Python은 쓰지 말 것. Tkinter(콘솔 GUI)가 빠져 있어 lab_gui.py가 실행되지 않습니다.

python.org 공식 설치본을 쓰고, 설치 화면에서 아래 두 개를 반드시 체크합니다.

  • ☑ Add python.exe to PATH
  • ☑ tcl/tk and IDLE (Tkinter 포함)

2. 설치 — 5단계

2단계 1. 저장소 받기

저장소를 받을 위치로 이동합니다.

git clone https://github.com/PEANUTBUTTER1001/leafscan.git
cd leafscan

2단계 2. 가상환경 만들기

python -m venv .venv

활성화:

# Windows (PowerShell)
.venv\Scripts\Activate.ps1

# Windows (cmd)
.venv\Scripts\activate.bat

# macOS / Linux
source .venv/bin/activate

프롬프트 앞에 (.venv)가 붙으면 성공입니다.

PowerShell에서 "스크립트를 실행할 수 없습니다" 오류가 나면

Set-ExecutionPolicy -Scope CurrentUser RemoteSigned

를 한 번 실행하고 다시 시도합니다.

2단계 3. PyTorch 설치 — 가장 실수가 잦은 단계

먼저 내 GPU가 어떤 CUDA를 지원하는지 확인합니다.

nvidia-smi

출력 오른쪽 위의 CUDA Version: 12.x 를 봅니다. (이건 드라이버가 지원하는 최대 버전이며, 이보다 낮은 CUDA 빌드는 설치해도 동작합니다.)

그 다음 pytorch.org 에서 자기 환경에 맞는 명령을 복사해 실행합니다. 예시:

# CUDA 12.1 계열 GPU
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121

# GPU 없음 (CPU 전용)
pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu

⚠️ 그냥 pip install torch 하면 안 되나? 됩니다. 다만 환경에 따라 CPU 전용 버전이 설치될 수 있습니다. 그러면 GPU가 있어도 안 쓰고 학습이 10배 느려지는데, 에러가 안 나서 눈치채기 어렵습니다. 반드시 아래 2단계 5의 확인을 거치세요.

2단계 4. 나머지 패키지

pip install -r requirements.txt

포함되는 것: numpy, scikit-learn, matplotlib, Pillow (torch·torchvision 은 2단계 3 에서 이미 설치했습니다. mlflow·wandb 는 선택 — 없어도 학습은 정상 완주합니다.)

2단계 5. 설치 확인 — 반드시 할 것

python scripts/check_env.py

조용히 잘못될 수 있는 것들을 잡는 단계입니다. CPU 빌드가 깔렸거나 Tkinter 가 빠졌거나 한글 폰트가 없어도 에러 없이 진행되다가 나중에 문제가 드러납니다.

정상 출력 예:

[OK] Python 3.12.10
[OK] torch 2.13.0+cu132
[OK] torchvision 0.28.0+cu132
[OK] CUDA 사용 가능 — NVIDIA GeForce GTX 1650 (4.0GB)
[OK] Tkinter 사용 가능 (Tk 8.6)
[OK] matplotlib 한글 폰트 — Malgun Gothic
[OK] 필수 패키지 6종 확인

→ 준비 완료. `python lab_gui.py` 를 실행하세요.

문제가 있으면 [!!] 와 함께 해결 방법이 나옵니다.

[!!] CUDA 사용 불가 — CPU로 학습됩니다
     torch 가 CPU 빌드입니다 (2.4.1+cpu).
     GPU 를 쓰려면 README.md §2단계 3 을 다시 하세요.
[!!] Tkinter 없음 — 콘솔 GUI를 실행할 수 없습니다
     Microsoft Store 버전 Python일 가능성이 높습니다. README.md §1.2 참조.
     학습 자체는 train_worker.py 로 계속 쓸 수 있습니다.
구분 어떤 항목 종료 코드
문제 — 고쳐야 진행 가능 torch·torchvision 없음, 필수 패키지 누락 1
경고 — 학습은 가능 GPU 없음(CPU 학습), 한글 폰트 없음, Python 버전 범위 밖 0

GPU 가 없어도 됩니다. CUDA 항목의 [!!] 는 "GPU 를 못 쓴다"는 알림이지 실패가 아닙니다.


3. 첫 실행 — 5분

3.1 콘솔 켜기

python lab_gui.py

3.2 5분짜리 학습 돌려보기

  1. 실행 모드 가 단일 실행 인지 확인 (맨 위 · 기본값)
  2. ① 데이터 의 데이터셋을 fake 로 선택 — 인터넷·데이터 파일 없이 돌아갑니다
  3. ② 모델 구조 의 arch 를 simple_cnn 으로 선택 — 가장 빨리 끝납니다
  4. ③ 학습 설정 의 Epoch 슬라이더를 1 로 내립니다
  5. ④ 실행 의 가설 입력란에 아무거나 적기 (예: 설치 확인)
  6. ▶ 학습 실행 클릭

무슨 일이 일어나는가:

왼쪽 값 → runs/exp_.../config.json 으로 저장
        → train_worker.py 를 별도 프로세스로 실행
        → epoch마다 로그가 실시간으로 흐름
        → 끝나면 지표 카드·혼동행렬·손실곡선이 채워짐
        → figures/ 에 그림이 생기고 report.md 가 만들어짐

여기까지 되면 설치는 끝입니다.

3.3 GUI 없이 돌려보기

콘솔은 편의 도구일 뿐입니다. 같은 실험이 터미널에서 그대로 재현됩니다.

python train_worker.py --config runs/exp_260812_ab_01/config.json --out runs/exp_260812_ab_01

이게 이 프로젝트의 핵심 설계입니다. config.json이 실험의 유일한 원본이고, GUI는 그 파일을 만드는 편집기입니다.

3.4 바탕화면 아이콘 만들기 (Windows · 선택)

매번 터미널을 열고 python lab_gui.py를 치는 게 번거롭다면, 바탕화면 바로가기를 만들 수 있습니다.

저장소 폴더에서 바탕화면_아이콘_만들기.bat 을 더블클릭합니다.

정상 출력 예:

 바탕화면에 LeafScan Lab 아이콘을 만듭니다...


  [완료] 바탕화면에 아이콘을 만들었습니다.
  사용한 파이썬 : C:\Users\user\AppData\Local\Programs\Python\Python312\pythonw.exe
  바로가기 위치 : C:\Users\user\Desktop\LeafScan Lab.lnk

  작업 표시줄에 고정하려면 아이콘 우클릭 > '작업 표시줄에 고정' 을 선택하세요.

계속하려면 아무 키나 누르십시오 . . .

바탕화면에 LeafScan Lab 아이콘(leafscan.ico)이 생기고, 더블클릭하면 검은 콘솔 창 없이 콘솔 GUI가 바로 뜹니다. 작업 표시줄에 두려면 아이콘 우클릭 → 작업 표시줄에 고정.

⚠️ 가상환경(.venv)을 쓴다면 주의. 위 .bat은 시스템 PATH의 파이썬을 잡기 때문에, 패키지를 .venv에만 설치한 경우 아이콘을 눌러도 ModuleNotFoundError가 납니다. 해결 — .venv를 활성화한 PowerShell에서 스크립트를 직접 실행하면 그 가상환경의 파이썬으로 바로가기가 만들어집니다.

.venv\Scripts\Activate.ps1
.\make_shortcut.ps1

출력의 사용한 파이썬 경로에 .venv가 들어 있으면 제대로 된 것입니다.

아이콘 없이도 됩니다. 저장소 안의 LeafScan Lab.bat 을 더블클릭해도 같은 방식으로 콘솔이 뜹니다. 바로가기는 이 .bat이 하는 일을 바탕화면으로 꺼내 놓은 것뿐입니다.

바로가기를 지우고 싶으면 바탕화면 아이콘만 삭제하면 됩니다. 저장소에는 아무 영향이 없습니다.


4. 실제 데이터 연결하기

§3 의 더미 데이터로 학습이 한 번 돌았다면, 다음은 실제 데이터를 붙이는 것입니다. 여기까지가 준비이고, 콘솔 화면을 자세히 뜯어보는 것은 §5 에 있습니다. 화면 구성이 궁금하면 §5 를 먼저 읽어도 됩니다.

4.1 데이터 배치

데이터는 저장소에 커밋하지 않습니다 (.gitignore 대상). 저장소를 새로 clone하면 data/ 자체가 없으므로, 먼저 뼈대 폴더부터 만듭니다.

python scripts/setup_data_dirs.py

작물 4종 × {training,validation} × {labeled,source} = 16개 폴더(+_extracted/)가 한 번에 생성됩니다. 그 다음 공유 위치에서 받은 tar를 정해진 위치에 그대로 넣습니다. (받는 위치는 팀 채널 참조)

원본은 tar 아카이브이며 작물별 폴더로 나뉩니다.

data/
├─ lettuce/                    # 상추
│  ├─ training/
│  │  ├─ labeled/  TL_3.상추32.tar     ← 어노테이션 JSON
│  │  └─ source/   TS_3.상추32.tar     ← 이미지 JPG
│  └─ validation/
│     ├─ labeled/  VL_3.상추10.tar
│     └─ source/   VS_3.상추10.tar
├─ chard/                      # 근대
├─ kale/                       # 케일
└─ leaf_mustard/               # 겨자채

⚠️ labeled와 source의 끝 번호가 일치하는지 확인 합니다.

4.2 인제스트 — tar를 학습용 인덱스로

python scripts/prepare_dataset.py --data-root data --out data/index.csv

동작 설명:

① 아카이브 짝 검증   labeled 번호 == source 번호인지
② 추출              data/_extracted/ 로 (이미 있으면 건너뜀)
③ JSON 파싱·조인     파일명 stem 기준
④ 품질 검사          짝 없는 파일·손상 이미지 제외
⑤ 산출              index.csv · labels.json · MANIFEST.md

정상 출력 예:

[OK] lettuce/validation  VL_3.상추10 ↔ VS_3.상추10  177/177 일치
[!!] lettuce/training    TL_3.상추32 ↔ TS_3.상추42  교집합 0건
     → TS_3.상추32.tar 를 받아 주세요. 번호가 같아야 합니다.

원본 데이터에 짝이 깨진 아카이브가 섞여 있으면 인제스트가 중단 되며 아래와 같은 메시지가 나옵니다.

[중단] 짝이 맞지 않는 아카이브가 있습니다. 위 항목을 해결하거나
       --skip-broken 으로 해당 짝만 건너뛰고 진행하세요.

이때 건너뛰고 진행하고 싶으면 아래 명령을 실행합니다.

python scripts/prepare_dataset.py --data-root data --out data/index.csv --skip-broken

깨진 짝만 빼고 나머지로 index.csv 를 만듭니다. 몇 개가 빠졌는지 화면에 나옵니다.

[진행] --skip-broken: 깨진 짝 32개를 제외하고 계속합니다.
선택 언제
--skip-broken 으로 진행 지금 당장 학습을 돌려봐야 할 때. 대부분 여기에 해당합니다
tar 를 다시 받아 해결 제외된 양이 많아 학습 데이터가 부족할 때

빠진 데이터는 그냥 없는 셈이 됩니다. 학습이 틀어지지는 않지만 쓸 수 있는 장수가 줄어듭니다. 몇 쌍이 빠졌는지는 기억해 두고, 결과를 해석할 때 감안합니다. 제외 내역은 data/MANIFEST.md 에 남으므로 나중에 확인할 수 있습니다.

디스크 — tar와 추출본을 함께 보관하므로 원본 용량의 약 2배가 필요합니다. 부족하면 작물별로 나눠 진행합니다.

4.3 학습에 연결

콘솔 ① 데이터 에서 데이터셋을 index_csv 로 바꾸고, 그 아래 경로를 data/index.csv 로 지정합니다. 장수·클래스 구성은 학습을 시작하면 ⑧ 로그 영역 첫머리에 이렇게 찍힙니다.

분할 정책=resplit_all · 그룹중복 없음(0건) · train/val/test 그룹=85/19/19
  train: 16895장 · 단계비율 {'정식기': 0.274, '생육기': 0.663, '수확기': 0.063}
  val:    3377장 · 단계비율 {'정식기': 0.278, '생육기': 0.66,  '수확기': 0.062}

그룹중복 없음(0건) 이 아니면 즉시 중단합니다. 데이터 누수입니다(§4.4 아래 경고 참조). 학습을 걸기 전에 미리 규모와 분포를 보려면 §4.4 를 봅니다.

index.csv는 13개 컬럼이며 상세는 04_데이터_명세서.md §6.5. 학습에서 중요한 것은 세 가지입니다.

컬럼 의미
crop / stage 라벨 2종
group_id 개체 ID. 같은 개체가 train/val에 섞이는 것을 막습니다
split_source 원본이 training인지 validation인지

4.4 학습 전에 확인 사항

인제스트가 끝나면 학습을 걸기 전에 데이터가 어떻게 생겼는지부터 봅니다. 방법은 두 가지이고, 같은 index.csv 를 읽으므로 결과는 같습니다.

방법 1 — 콘솔에서 보기 (권장)

GUI 콘솔 ① 데이터 하단의 분포 보기 (학습 전 점검) 버튼을 누릅니다. 데이터셋이 index_csv 여야 하며, 학습 결과와 무관하게 동작하므로 학습 중에도 열립니다.

작물×단계 교차표까지 한 화면에 나옵니다.

규모      : 23,633장 · 개체 123개 · 아카이브 53개
개체당    : 최소 1장 · 중앙 208장 · 최대 504장

[작물 × 단계]
작물     생육기   정식기   수확기
---------------------------------
상추     15,665    6,490    1,478

단계 비율 : 생육기 66.3%  정식기 27.5%  수확기 6.3%

[split_source × 단계]  (분할 정책 결정 근거)
원본           생육기   정식기   수확기
---------------------------------------
training       13,550    5,588    1,300
validation      2,115      902      178

[!] 확인할 것 1건
  - 작물이 '상추' 하나뿐입니다 — 작물 분류는 고를 것이 하나라 정확도가 항상 100% 가 됩니다.
    생육단계 지표만 의미가 있습니다.

무엇을 보는가

줄 판단
규모 개체(group_id) 수가 충분한가. 개체가 적으면 분할 자체가 불안정합니다
개체당 편차가 큰가. 1장짜리 개체는 한쪽 split 에만 들어가 층화를 흔듭니다
[작물 × 단계] 특정 조합이 극단적으로 적은가. 그 조합은 학습도 평가도 안 됩니다
단계 비율 불균형 정도. 위 예시는 수확기가 6.3% 라 macro-F1 이 이 클래스에 좌우됩니다
[split_source × 단계] 제공된 분할을 쓸지(respect_provided) 다시 나눌지(resplit_all) 정하는 근거

맨 아래 [!] 확인할 것 은 아래 규칙에 걸린 사실만 알립니다. 어떻게 할지는 사람이 정합니다.

알림 조건
개체 수 부족 group_id 가 30개 미만 — 그룹 분할이 불안정
작물이 하나뿐 작물 분류의 선택지가 하나 — 정확도가 항상 100%
희소 단계 특정 단계가 전체의 5% 미만 — macro-F1 이 이 클래스에 좌우됨
희소 조합 작물×단계 조합이 100장 미만 — 평가가 불안정

방법 2 — 터미널에서 보기

python scripts/check_data.py

규모·개체·작물·단계 합계와 데이터 해시가 나옵니다. 교차표는 없습니다.

index : data\index.csv
hash  : sha256:afd2f4ae...
규모  : 23633장 · 개체 123개
작물  : {'상추': 23633}
단계  : {'정식기': 6490, '생육기': 15665, '수확기': 1478}

이쪽을 쓰는 이유는 hash 줄 하나입니다. 팀원과 이 값이 다르면 서로 다른 데이터로 실험한 것이라 결과를 나란히 놓고 비교할 수 없습니다 (03_팀_협업_규약.md).

방법 1 과 같은 표를 터미널에서 보려면 이렇게도 됩니다.

python -c "from core.data_summary import *; print(format_summary(summarize_index('data/index.csv')))"

그림으로 된 분포는 학습 후에 나옵니다. figures/data_distribution.png 는 run 이 끝날 때 metrics.json 의 분할 정보를 읽어 생성되므로 학습 전에는 볼 수 없습니다. 학습 전 점검은 위의 방법 1·2 로 합니다.

이 데이터에서 가장 조심할 것은 데이터 누수입니다. 한 개체를 약 한 달간 27~40장 연속 촬영해 이미지들이 매우 유사합니다. 무작위로 나누면 정확도 99% 같은 헛된 수치가 나옵니다. 분할은 반드시 group_id 기준으로 이뤄지며, 콘솔이 분할 후 그룹 중복 건수를 표시합니다. 0이 아니면 무언가 잘못된 것입니다.


5. 콘솔 사용법

5.1 화면 구조

좌측은 손(조작), 우측은 눈(결과).

┌──────────────────────────────────────────────────┐
│ 전역 바 : 기준 run 선택 · 실행 상태               │
├─────────────┬────────────────────────────────────┤
│ ① 데이터     │ ⑤ 지표 카드 4종 (기준 대비 델타)    │
│ ② 모델       │ ⑥ 혼동행렬 (head 탭 · 셀 클릭)      │
│ ③ 학습       │ ⑦ 오분류 샘플 그리드                │
│ ④ 가설·실행  │ ⑧ 손실 곡선 · 로그                  │
│              │ ⑨ 결론 입력                         │
└─────────────┴────────────────────────────────────┘

5.2 주요 조작

조작 설명
실행 모드 사이드바 맨 위. 단일 실행(기본) / Study 실행(여러 모델 순차 비교)
분포 보기 ① 데이터 맨 아래. 학습 전 데이터 점검 (§4.4) — 실행 중에도 열립니다
아키텍처 백본 모델 선택. 이것만 바꿔도 완전히 다른 실험
입력 해상도 224 기본. 낮추면 빠르지만 정확도가 떨어질 수 있음
빠른 학습 입력 해상도 옆 체크박스. 체크 시 원본을 256px 축소 캐시로 빠르게 학습 ↔ 해제(기본) 시 원본 그대로. 아래 상세
pretrained ImageNet 사전학습 가중치 사용. 거의 항상 켜는 게 유리
Learning rate 로그 슬라이더 — 극단값이 들어갈 수 없음
freeze epoch 초반 N epoch 동안 백본을 고정. 전이학습 2단계
head 가중치 crop과 stage 중 어디에 비중을 둘지
class weight 소수 클래스(정식기)를 얼마나 챙길지
기준 run 선택하면 모든 지표에 델타가 붙음
wandb 보기 우측 상단 버튼. 보고 있는 run → 실행 중 run → 프로젝트 대시보드 순으로 wandb 웹페이지를 엶. 아래 상세
threshold 슬라이더 즉시 반응. 재학습 없이 판정 기준만 바꿔봄
혼동행렬 셀 클릭하면 그 조합의 실제 오분류 이미지가 뜸

📊 wandb 실험 추적 (Weights & Biases)

학습이 wandb 서버에 실시간으로 기록되고, 우측 상단 "wandb 보기" 버튼으로 바로 열어볼 수 있습니다.

기록 시점 내용
epoch 마다 loss · val_loss · acc · val_acc + head 별 정확도 (val_acc_crop, val_acc_stage)
학습 종료 stage macro-F1 · 정식기 recall · crop accuracy 등 최종 요약 + metrics.json 첨부
Study 실행 study 이름으로 run 들이 그룹으로 묶여 모델 비교가 한 화면에

셋업 (PC 당 최초 1회):

pip install wandb
wandb login        # https://wandb.ai/authorize 의 API 키 입력 (화면에 안 보이는 게 정상)

알아둘 것:

  • 미설치·미로그인이어도 학습은 정상 완주합니다. 미로그인이면 로컬 wandb/ 폴더에 offline 기록되고, 나중에 wandb login 후 wandb sync wandb/offline-run-... 으로 올릴 수 있습니다.
  • 켜고 끄기: ③ 학습 설정 › 고급 › "wandb 실험 추적" 체크박스 (기본 켜짐).
  • 구현 상세와 문제 해결은 05_wandb_연동.md 참조.

⚡ 빠른 학습 (이미지 사전 축소 캐시)

② 모델 구조 › 입력 해상도 옆의 빠른 학습 체크박스로 이미지 준비 방식을 고릅니다.

상태 동작 언제 쓰나
✔ 체크 원본(915×1060급)을 최초 epoch 에 256px 로 축소해 캐시(data/_cache/)하고 이후 재사용 빠른 반복 실험. 원본 JPEG 디코딩이 epoch 시간의 병목이라 훨씬 빠름
☐ 해제 (기본) 캐시 없이 원본 이미지를 매번 그대로 디코딩해 학습 — 기존 방식 그대로 평상시·최종 검증 run (품질 우선)

알아둘 것:

  • 어느 쪽이든 모델에 들어가는 최종 입력은 위의 입력 해상도(기본 224) 설정을 따릅니다. 차이는 그 해상도로 줄이기 전의 출발 화질(256px 캐시 vs 원본)뿐입니다.
  • 체크 상태의 첫 실행은 캐시 생성 때문에 최초 epoch 이 느립니다. 두 번째 epoch 부터 빨라집니다.
  • 캐시는 data/_cache/ 폴더에만 생기고 원본 파일은 절대 건드리지 않습니다.
  • 두 모드는 픽셀 값이 미세하게 달라 지표도 미세하게 다를 수 있습니다. 비교 실험(Study) 안에서는 한 모드로 통일하세요.

Study 실행 모드

실행 모드 를 Study 실행 으로 바꾸면 여러 모델을 같은 조건에서 순서대로 학습합니다.

항목 설명
Study 이름 번호가 자동으로 매겨집니다 (study_01 → study_02 …). 단일 실행의 exp_001 과 같은 방식입니다
주제 붙이기 번호 뒤에 붙이면 됩니다 — study_02_lr. 번호만 읽으므로 다음 번호에 영향이 없습니다
재개 같은 이름을 다시 입력하면 완료된 모델은 건너뛰고 남은 것만 실행합니다. Study 가 끝나면 입력칸이 다음 번호로 바뀌므로, 이어서 하려면 이전 이름을 직접 넣습니다
비교 모델 최소 2개. simple_cnn 은 회귀 픽스처라 목록에 없습니다 (§01_기획서.md §4.1)
결과 모델마다 report.md·figures/ + 전체 STUDY.md (§7)

5.3 반응 속도별 구분

등급 소요 대상
즉시 (<50ms) 바로 threshold, 혼동행렬 셀 선택, head 탭
단시간 (초~분) 진행 표시 그림 재생성
장시간 (분~시간) 진행바 + 중단 가능 학습

조작 전에 이 구분을 확인하면 몇 시간을 아낍니다.

5.4 최종 테스트셋 평가

validation 결과로 확정한 모델을 재학습하거나 다시 선택하지 않고, 기존 best.pt를 고정된 분리 test split에 한 번 평가할 수 있습니다. 최종 테스트는 모델 선택·Study 순위 결정에 사용하지 않습니다.

GUI에서 실행

  1. 완료된 index_csv run을 상단 기준 run 목록에서 선택합니다. Study 멤버는 study_03/study_03__arch-resnet18처럼 표시됩니다.
  2. 결과 화면의 FINAL TEST 버튼을 누릅니다. 이 run 보기를 먼저 누르지 않아도 선택한 run이 평가 대상으로 사용됩니다.
  3. 기존 평가가 있으면 재평가 확인창에서 예를 선택합니다.
  4. 평가 중에는 스피너·경과시간·실시간 로그가 표시되며, ■ 테스트 중단으로 중단할 수 있습니다.

CLI에서 실행

python evaluate_test.py --run runs/study_03/study_03__arch-resnet18

재평가는 기존 결과를 덮어쓰지 않고 새 이력으로 저장합니다.

python evaluate_test.py `
  --run runs/study_03/study_03__arch-resnet18 `
  --reevaluate --reason "재현성 확인"

대상 run은 dataset=index_csv, status=done, best.pt, config.json, 고정 split.json, 원본 index.csv를 모두 갖춰야 합니다. exp_###처럼 학습 당시 고정 split.json이 없는 예전 run은 데이터 누수를 막기 위해 평가를 중단합니다.

결과물

평가가 끝나면 run 루트의 기존 report.md에 ## 10. 최종 테스트 평가가 추가되고, head별 지표가 표로 기록됩니다.

| Head | Accuracy | Macro-F1 | Weighted-F1 |
|---|---:|---:|---:|
| crop | 1.0 | 1.0 | 1.0 |
| stage | 0.8677 | 0.7984 | 0.8708 |

평가별 원본과 테스트 전용 그림은 기존 validation 산출물과 분리해 보관합니다.

runs/<run>/test_evaluations/<evaluation_id>/
├─ test_metrics.json
├─ evaluation_metadata.json
├─ logits_*.npy · labels_*.npy
└─ figures/
   ├─ confusion_*.png
   ├─ f1_per_class_*.png
   ├─ calibration_*.png
   └─ confidence_hist_*.png

best.pt, 기존 metrics.json, validation logits/labels·figures, split.json은 수정하거나 덮어쓰지 않습니다. 별도 evaluation 폴더에는 report.md를 만들지 않고, run 루트의 report.md가 최신 평가를 요약합니다.


6. 실험 한 사이클

① 가설을 적는다        "class weight를 켜면 정식기 recall이 0.62 이상 될 것"
② 값을 조정한다        class weight: 없음 → 자동
③ 실행한다            결과가 나올 때까지 다른 일을 해도 된다
④ 자동 관찰을 읽는다   report.md §6 — 사람이 놓치기 쉬운 사실을 짚어줌
⑤ 원인을 추적한다      혼동행렬 진한 셀 클릭 → 오분류 이미지 확인
⑥ 결론을 적는다        "가설대로 올랐으나 오분류가 한 방향에 몰림. 라벨 문제로 의심"
⑦ 다음 실험을 정한다   report.md §8 후보 중 채택

6.1 가설을 반드시 적어야 하는 이유

3주 뒤에는 본인도 왜 그 실험을 했는지 기억하지 못합니다. 이 프로젝트의 산출물은 모델 하나가 아니라 연구 과정 전체이므로, 가설이 없는 run은 숫자 더미가 됩니다.

가설이 비어 있으면 실행 시 확인 대화상자가 뜹니다. 형식은 자유이고 한 줄이어도 됩니다.

좋은 예 나쁜 예
"정식기가 10%뿐이라 학습 신호가 부족해 보임. class weight로 보정하면 recall이 오를 것" "테스트"
"resnet50이 과적합되는 듯. augmentation을 강으로 올리면 val_loss 상승이 늦춰질 것" "돌려봄"

6.2 결론도 반드시 적습니다

결론이 비면 index.csv와 RESEARCH_LOG.md에 ⚠️ 미작성으로 표시됩니다. 3~5줄이면 충분합니다.


7. 결과 파일 읽는 법

runs/exp_260812_ab_01/
├─ report.md          ← ★ 먼저 여기를 본다
├─ figures/           ← 그림 9장
├─ config.json          설정 (실험의 원본)
├─ diff.json            부모 run과 뭐가 달랐는지
├─ metrics.json         지표 원본 (기계용)
├─ train.log            로그 원문
├─ env.json             환경 (재현용)
├─ logits_*.npy         예측값 (threshold 재계산용)
└─ best.pt              모델 가중치
파일 언제 보나
report.md 항상 여기부터. 사람이 읽으라고 만든 문서
figures/ 자료가 필요할 때 — 이미 만들어져 있습니다
train.log 학습이 실패했을 때
diff.json "이전 실험과 뭐가 달랐지?"
env.json 결과가 남과 다를 때

Study 실행 결과도 같습니다. 모델마다 report.md 와 figures/ 가 따로 생기고, 그 위에 비교 결과가 얹힙니다.

runs/study_02_backbone/
├─ STUDY.md                              ← ★ 비교 결론 (모델 간 순위)
├─ index.csv                               이 study 의 모델 목록·지표 한눈에
├─ figures/                                비교 그림 4종
├─ study_02_backbone__arch-resnet18/     ← 모델 하나 = 단일 실행과 같은 구조
│  ├─ report.md                          ←   이 모델만의 리포트
│  └─ figures/                                이 모델만의 그림 8종
└─ study_02_backbone__arch-convnext_tiny/
   └─ …
무엇이 궁금한가 어디를 보나
어느 모델이 좋았나 STUDY.md · figures/cost_accuracy.png
그 모델이 왜 그랬나 멤버 폴더의 report.md — 클래스별 F1·혼동행렬·자동 관찰
특정 모델의 오분류 패턴 멤버 폴더의 figures/confusion_stage.png

멤버 리포트는 모델이 하나 끝날 때마다 만들어집니다. 5개짜리 Study 라면 3번째 모델이 도는 중에 이미 앞선 2개의 리포트를 열어볼 수 있습니다.

7.1 지표 읽는 법

지표 의미 주의
stage macro-F1 주 지표 이 값으로 판단합니다
정식기 recall 소수 클래스를 얼마나 놓치지 않는가 이 프로젝트의 실질 난이도
accuracy 전체 정답률 ⚠️ 믿지 말 것. 전부 생육기로 찍어도 60%
미판정률 판정을 보류한 비율 threshold와 함께 봄

왜 accuracy를 안 보나 — 생육기가 60%다. 아무 생각 없이 전부 생육기라고 답하는 모델도 accuracy 60%가 나옵니다. macro-F1은 클래스별 성능을 평균하므로 이런 속임수가 통하지 않습니다.


8. 자주 발생하는 문제

8.1 설치·환경

증상 원인 해결
python: command not found PATH 미등록 Python 재설치 시 "Add to PATH" 체크
Activate.ps1 실행할 수 없음 PowerShell 실행 정책 Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
ModuleNotFoundError: torch 가상환경 미활성화 프롬프트에 (.venv)가 있는지 확인
ModuleNotFoundError: tkinter Microsoft Store Python python.org 공식 설치본 + tcl/tk 체크
학습이 유난히 느림 CPU 빌드 torch python scripts/check_env.py로 확인 → §2단계 3 재실행
scripts/check_env.py에서 CUDA 불가 드라이버 구버전 또는 CPU 빌드 nvidia-smi 확인 → 드라이버 업데이트 또는 torch 재설치
그림의 한글이 □로 깨짐 한글 폰트 없음 scripts/check_env.py 가 확인해 줍니다. Windows 는 Malgun Gothic 이 기본 탑재, 그 외에는 나눔고딕을 설치하세요
아이콘 만들기가 [실패] 파이썬을 찾을 수 없습니다 PATH 미등록 Python 재설치 시 "Add to PATH" 체크 (§1.2)
아이콘 만들기가 [실패] lab_gui.py 가 이 폴더에 없습니다 .bat을 저장소 밖에서 실행 저장소 폴더 안의 .bat을 그대로 더블클릭
바탕화면 아이콘을 눌러도 창이 안 뜸 바로가기가 시스템 파이썬을 가리킴 (.venv에만 설치) .venv 활성화 후 .\make_shortcut.ps1 재실행 (§3.4)

8.2 학습 중

증상 원인 해결
인제스트가 "교집합 0건"으로 중단 labeled/source 묶음 번호 불일치 같은 명령에 --skip-broken 을 붙여 다시 실행하면 깨진 짝만 빼고 진행합니다 (§4.2). 데이터를 온전히 쓰려면 같은 번호의 tar 를 받습니다 (§4.1)
인제스트 중 디스크 부족 tar + 추출본 = 원본 2배 작물별로 나눠 진행하거나 공간 확보
학습 시작 시 "이미지를 찾을 수 없음" 추출 경로 문제 / 인제스트 미실행 python scripts/check_data.py
CUDA out of memory 배치가 큼 / 모델이 무거움 배치를 절반으로. 그래도 안 되면 해상도 160으로. 콘솔의 권장 배치 참고
Windows에서 무한 대기 / 프로세스 폭증 num_workers > 0 Windows는 num_workers=0부터 시작
loss가 NaN lr이 너무 큼 lr을 1/10로. ConvNeXt는 특히 낮게
loss가 전혀 안 줄어듦 lr이 너무 작거나 optimizer 문제 자동 관찰이 🔴 학습이 진행되지 않음으로 잡아줍니다
정확도가 이상하게 높음 (99%+) 데이터 누수 — 같은 개체가 train/val에 섞임 분할 로그의 그룹 중복 건수가 0인지 확인. 0이 아니면 group_id 설정 문제
val_loss만 계속 오름 과적합 epoch을 줄이거나 augmentation 강화. early stop이 자동 중단
학습이 갑자기 죽음 OOM 또는 데이터 파일 손상 train.log 마지막 부분 확인

8.3 결과

증상 원인 해결
그림이 안 생김 matplotlib 오류 수동 재생성: python make_figures.py --run runs/exp_... (학습 결과는 무사합니다)
report.md가 없음 리포트 생성 실패 python make_report.py --run runs/exp_...
혼동행렬이 비어 있음 logits_*.npy 미생성 학습이 정상 종료됐는지 status.json 확인
델타가 안 나옴 기준 run 미선택 전역 바에서 기준 run 선택
남과 결과가 미묘하게 다름 GPU·라이브러리 버전 차이 env.json 대조. 정상적인 현상이며 경향이 같으면 문제 없음

9. 하지 말아야 할 것

금지 왜
runs/ 폴더를 임의로 삭제 연구 기록이 사라집니다. 정리가 필요하면 팀과 상의
data/를 Git에 커밋 저장소가 수 GB로 불어납니다. .gitignore에 이미 있습니다
best.pt·*.npy를 Git에 커밋 같은 이유. 커밋 대상은 config·metrics·report·figures뿐
가설 없이 실행 나중에 그 run이 왜 있는지 아무도 모릅니다
학습 중 콘솔 강제 종료 체크포인트가 손상될 수 있습니다. 중단 버튼을 쓸 것
config.json을 손으로 고쳐 재실행 가능은 하지만, 어떤 값이 실제로 쓰였는지 추적이 흐려집니다. 콘솔에서 조정
test set을 보고 설정 선택 성능이 부풀려집니다. val로만 판단
다른 사람 run을 덮어쓰기 run ID 규칙(03_팀_협업_규약.md)을 지킬 것
여러 학습을 한 PC에서 동시 실행 GPU 메모리 경쟁으로 둘 다 느려지거나 OOM
경로에 한글·공백 일부 라이브러리에서 오류

10. 도움 받기

10.1 문제가 생겼을 때 확인 순서

1. python scripts/check_env.py      환경 문제인가?
2. runs/.../train.log 마지막 40줄   무슨 에러인가?
3. §8 자주 발생하는 문제            이미 알려진 문제인가?
4. runs/.../env.json                내 환경이 남과 다른가?
5. 팀에 문의

10.2 문의할 때 함께 보낼 것

항목 이유
python scripts/check_env.py 출력 환경 파악
train.log 마지막 40줄 실제 에러
config.json 어떤 설정이었는지
무엇을 하려다 언제 발생했는지 재현 조건

10.3 더 읽을 것

문서 내용
01_기획서.md 이 프로젝트가 무엇을 왜 하는가
02_구조도.md 코드가 어떻게 구성돼 있는가
03_팀_협업_규약.md 실험을 시작하기 전에 반드시 읽을 것 — run ID·분담·공유 규칙
04_데이터_명세서.md 데이터가 이상할 때 — 구조·JSON 스키마·분할 정책·함정 10선

About

엽채류 이미지에서 작물 종류와 생육단계를 판별하는 딥러닝 모델을 연구·개발하는 프로젝트

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages