|
|
# kr_lp_pgnet — 프로젝트 핸드오프
|
|
|
|
|
|
한국 자동차 번호판 검출 + OCR을 위한 PaddleOCR PGNet 학습 프로젝트.
|
|
|
|
|
|
---
|
|
|
|
|
|
## 30초 요약
|
|
|
|
|
|
- **목표**: PGNet 한 모델로 한국 LP 4종 (자가용/영업/전기/화물) 검출+인식 → ONNX export
|
|
|
- **현재 상태 (2026-05-08)**: Step1 pretrain **학습 중** (50 epoch, eta ~11시간, run id `l0eqqbrb`)
|
|
|
- **다음 단계**: 학습 완료 후 → Step2 fine-tune (실차 데이터) → ONNX export
|
|
|
- **운영 원칙**: 로컬 Mac은 코드 작성·git만, 모든 실행(학습·합성·검증)은 외부 GPU 서버에서
|
|
|
|
|
|
---
|
|
|
|
|
|
## 환경
|
|
|
|
|
|
### 1. 로컬 Mac (코드 작성 전용)
|
|
|
- 작업 디렉토리: `/Users/songhyeonsu/Documents/GIT/cuuva_AI/kr_lp_pgnet/`
|
|
|
- **금지사항** (메모리 `feedback_local_no_runtime.md`):
|
|
|
- Python 패키지 설치 (`pip install ...`)
|
|
|
- 외부 자산 git clone (qjadud 등)
|
|
|
- 합성기·학습·평가 실행
|
|
|
- **허용**: 코드/yaml/sh 작성·수정, 우리 repo git commit/push
|
|
|
|
|
|
### 2. 외부 GPU 서버
|
|
|
- **SSH**: `ssh cuuva@192.168.10.189` (사내망 전용, key 인증)
|
|
|
- **호스트**: Ubuntu 25.10, RTX 5090 32GB, NVIDIA driver 590.48.01, CUDA 13.1
|
|
|
- **레이아웃**:
|
|
|
```
|
|
|
/home/cuuva/workspace/
|
|
|
├── PaddleOCR/ # git clone release/2.7
|
|
|
├── kr_lp_pgnet/ # 이 repo (사내망 GitLab에서 clone)
|
|
|
├── train_data/
|
|
|
│ ├── kr_lp_synth/ # Step1 학습용 (50k, 본격)
|
|
|
│ ├── kr_lp_synth_v2/ # 400장 (dry-run용)
|
|
|
│ ├── kr_lp_synth_smoke/ # 40장 (smoke test)
|
|
|
│ ├── region_check_y/ # 영업용 region 16종 검증
|
|
|
│ └── region_check_g/ # 친환경 region 16종 검증
|
|
|
└── wheels/
|
|
|
└── paddlepaddle_gpu-3.3.0.dev20251209-cp310-...whl # sm_120 wheel
|
|
|
```
|
|
|
|
|
|
### 3. 학습 컨테이너 `kr_lp_pgnet`
|
|
|
- 베이스: `ubuntu:24.04`
|
|
|
- 옵션: `--gpus all --shm-size=8g --restart unless-stopped`
|
|
|
- bind mount: 호스트 `/home/cuuva/workspace` ↔ 컨테이너 `/workspace`
|
|
|
- 설치된 것: Python 3.10 (deadsnakes), paddlepaddle-gpu 3.3.0.dev (sm_120), cuDNN 9.17, numpy 1.26, opencv 4.10+, wandb 0.26, PaddleOCR + 의존성
|
|
|
- 재셋업: `bash scripts/recreate_container.sh` (한 줄로 전부)
|
|
|
|
|
|
### 4. 파일 서버 컨테이너 `kr_lp_http`
|
|
|
- 합성 결과 시각 확인용
|
|
|
- URL: **http://192.168.10.189:8889/**
|
|
|
- 마운트: `/home/cuuva/workspace/train_data` (read-only)
|
|
|
- 시작 명령:
|
|
|
```bash
|
|
|
docker run -d --name kr_lp_http -v /home/cuuva/workspace/train_data:/data:ro \
|
|
|
-p 8889:8889 --restart unless-stopped python:3.11-slim \
|
|
|
python3 -m http.server 8889 --bind 0.0.0.0 --directory /data
|
|
|
```
|
|
|
|
|
|
### 5. 다른 컨테이너 `my-vision-container` (우리 일과 무관, 그대로 두기)
|
|
|
- 4주 전 시작, 8888 포트로 Jupyter 노출
|
|
|
- 우리 paddle wheel 설치 중 cuda-bindings/nccl 충돌로 **torch import 깨진 상태**
|
|
|
- 복구는 사용자가 원할 때 본인 방식으로 `docker rm -f 983b0a026d7b && docker run ...` (`/workspace`는 bind mount라 데이터 안전)
|
|
|
|
|
|
---
|
|
|
|
|
|
## 저장소
|
|
|
|
|
|
- **Git remote**: `http://192.168.10.110/TTA/kr_lp_pgnet.git` (사내 GitLab/Gitea)
|
|
|
- **HTTP 인증**: 서버에서 평소 git push/pull 정상 (사용자 설정됨)
|
|
|
- **브랜치**: `main`만 사용
|
|
|
- **로컬 사용자 정보**: `hunsoo0823@naver.com` / `songhyeonsu`
|
|
|
|
|
|
## wandb
|
|
|
|
|
|
- **Entity**: `hssong_cuuva` (개인 계정)
|
|
|
- **Project**: `kr_lp_pgnet`
|
|
|
- **현재 본격 학습 run**: `step1-pretrain` (id `l0eqqbrb`)
|
|
|
- **dashboard**: https://wandb.ai/hssong_cuuva/kr_lp_pgnet
|
|
|
- **이 run 직접 URL**: https://wandb.ai/hssong_cuuva/kr_lp_pgnet/runs/l0eqqbrb
|
|
|
- **로그인**: 컨테이너 안 `/root/.netrc`에 저장됨 (`recreate_container.sh`가 자동 보존)
|
|
|
|
|
|
---
|
|
|
|
|
|
## 디렉토리 구조 (이 repo)
|
|
|
|
|
|
```
|
|
|
kr_lp_pgnet/
|
|
|
├── README.md
|
|
|
├── ONBOARDING.md # 이 문서
|
|
|
├── configs/
|
|
|
│ └── kr_lp_pgnet.yml # PGNet 학습 설정 (epoch 50, batch 16, pad_num 67)
|
|
|
├── dict/
|
|
|
│ └── kr_lp_dict.txt # 문자 사전 67자
|
|
|
├── data_gen/
|
|
|
│ ├── README.md # 자산 라이센스 / 사용법 / 알려진 제약
|
|
|
│ ├── setup_assets.sh # qjadud 자산 git clone
|
|
|
│ └── generate_synthetic.py # 합성기 (4 plate types, brightness, type weights)
|
|
|
├── scripts/
|
|
|
│ ├── recreate_container.sh # 컨테이너 재생성 (shm 8g, gpus all)
|
|
|
│ ├── setup_server.sh # 컨테이너 안 환경 셋업 (idempotent)
|
|
|
│ └── run_step1.sh # Step1 학습 실행
|
|
|
└── tools/
|
|
|
└── region_check.py # REGION_MAP 시각 검증용
|
|
|
```
|
|
|
|
|
|
---
|
|
|
|
|
|
## 진행 상태 (체크리스트)
|
|
|
|
|
|
### ✅ 완료
|
|
|
1. **환경 셋업** — repo, GitLab remote, 서버 컨테이너, paddle sm_120 wheel, cuDNN 9.17, PaddleOCR release/2.7
|
|
|
2. **dict + config** — 67자 (숫자 10 + 자가용 32 + 영업용 4 + 렌터카 3 + 배달 1 + 지역명 17), `pad_num=67`, `max_text_length=10`, `valid_set=partvgg`, `infer_visual_type=CN`
|
|
|
3. **합성기** — 4 plate type (520×110 / 355×155 / 336×170×2), 한영자판 매핑, REGION_MAP(추정), 도로 분포 가중치 (Type1 80%/Type2 5%/Type3 10%/Type4 5%), random_bright
|
|
|
4. **wandb 연동** — Global.use_wandb=True + project=kr_lp_pgnet
|
|
|
5. **50k 합성 완료** — train 47500 / test 2500, type 분포 도로 현실 일치
|
|
|
|
|
|
### 🔄 진행 중
|
|
|
- **Step1 pretrain 학습** — 50 epoch, batch 16, num_workers 8, 50k synthetic data
|
|
|
- 시작: 2026-05-08 07:58
|
|
|
- ips 58~59 samples/s
|
|
|
- 진행: epoch 1/50 ~step 2110 (확인 시점 기준)
|
|
|
- eta: ~11시간
|
|
|
- loss: 1234 → 63 (감소 추세 정상)
|
|
|
- 체크포인트 저장 경로: `/workspace/PaddleOCR/output/kr_lp_pgnet/{latest,best_accuracy}/`
|
|
|
|
|
|
### 📋 다음 단계
|
|
|
1. **Step1 완료 평가** — `eval f_score_e2e` 확인, 추론 결과 시각 검증 (synth test set + 임의 LP 이미지)
|
|
|
2. **Step2 fine-tune** — 실제 한국 LP 사진 데이터 수집·라벨링·fine-tune (자산이 못 만든 글자 보충: 하, 호, 배, 세종)
|
|
|
3. **ONNX export** — `paddle2onnx`로 변환 → 추론 검증
|
|
|
4. **(선택) 더 강한 augmentation** — config에 IaaAugment 추가 (rotate/perspective/blur)
|
|
|
5. **(선택) REGION_MAP 정확 검증** — region_check_y/g 시각 확인 후 매핑 정정
|
|
|
|
|
|
---
|
|
|
|
|
|
## 자주 쓰는 운영 명령
|
|
|
|
|
|
### 학습 모니터링
|
|
|
```bash
|
|
|
# 학습 프로세스 살아있는지
|
|
|
ssh cuuva@192.168.10.189 'docker exec kr_lp_pgnet pgrep -af tools/train.py | wc -l'
|
|
|
|
|
|
# 학습 로그 (eval tqdm 줄 제외)
|
|
|
ssh cuuva@192.168.10.189 \
|
|
|
'docker exec kr_lp_pgnet bash -c "grep -v \"it/s\" /workspace/PaddleOCR/output/kr_lp_pgnet/run.log | tail -5"'
|
|
|
|
|
|
# GPU 사용량
|
|
|
ssh cuuva@192.168.10.189 'docker exec kr_lp_pgnet nvidia-smi --query-gpu=memory.used,utilization.gpu --format=csv'
|
|
|
```
|
|
|
|
|
|
### 학습 끊김 대응 (NVML stale 등)
|
|
|
```bash
|
|
|
# 1. 컨테이너 재시작 (NVML 풀기)
|
|
|
ssh cuuva@192.168.10.189 'docker restart kr_lp_pgnet'
|
|
|
|
|
|
# 2. 이어서 학습 (latest 체크포인트에서 재개)
|
|
|
ssh cuuva@192.168.10.189 'docker exec -d kr_lp_pgnet bash -c "
|
|
|
cd /workspace/PaddleOCR
|
|
|
nohup python3.10 tools/train.py -c configs/e2e/kr_lp_pgnet.yml \
|
|
|
-o Global.checkpoints=./output/kr_lp_pgnet/latest \
|
|
|
> output/kr_lp_pgnet/run.log 2>&1 &
|
|
|
"'
|
|
|
```
|
|
|
|
|
|
### 학습 중단
|
|
|
```bash
|
|
|
ssh cuuva@192.168.10.189 'docker exec kr_lp_pgnet pkill -f "tools/train.py"'
|
|
|
```
|
|
|
|
|
|
### 합성 추가 생성
|
|
|
```bash
|
|
|
ssh cuuva@192.168.10.189 'docker exec kr_lp_pgnet python3.10 \
|
|
|
/workspace/kr_lp_pgnet/data_gen/generate_synthetic.py \
|
|
|
--out_dir /workspace/train_data/kr_lp_synth_extra \
|
|
|
--num 10000 --types 1,2,3,4 \
|
|
|
--dict /workspace/kr_lp_pgnet/dict/kr_lp_dict.txt'
|
|
|
```
|
|
|
|
|
|
### 컨테이너 완전 재셋업 (드물게)
|
|
|
```bash
|
|
|
ssh cuuva@192.168.10.189 'bash ~/workspace/kr_lp_pgnet/scripts/recreate_container.sh'
|
|
|
```
|
|
|
|
|
|
### 파일 서버 재시작
|
|
|
```bash
|
|
|
ssh cuuva@192.168.10.189 'docker restart kr_lp_http'
|
|
|
```
|
|
|
|
|
|
---
|
|
|
|
|
|
## 알려진 이슈 / 의사결정 기록
|
|
|
|
|
|
### 시스템
|
|
|
- **NVML stale 재발 가능성**: 컨테이너 오래 돌면 `nvidia-smi`가 `Failed to initialize NVML` 에러. 호스트는 멀쩡, 컨테이너 재시작 한 번으로 풀림. 학습 시작 직전 한 번 재시작했으니 한동안은 안전할 가능성.
|
|
|
- **shm 부족 → DataLoader BUS error**: `--shm-size=8g` 필수 (해결됨).
|
|
|
- **OOM at batch 32**: PGNet 가변 input 사이즈가 peak에 32GB 초과. **batch 16 확정**.
|
|
|
- **cuDNN 9.17 강제**: paddle sm_120 wheel은 9.17로 빌드됐는데 paddle deps는 9.13 install. `pip install 'nvidia-cudnn-cu13>=9.17'`로 덮어쓰지 않으면 conv2d에서 `cublasLtCreate` 심볼 로드 실패 후 process abort. setup_server.sh에 반영됨.
|
|
|
- **paddle wheel 출처**: 비공식 [horhe-dvlp/paddlepaddle-sm120-wheels](https://github.com/horhe-dvlp/paddlepaddle-sm120-wheels) v3.3.0-dev (Python 3.10, CUDA 13.0). 공식은 sm_120 미지원.
|
|
|
|
|
|
### 데이터
|
|
|
- **자산 출처**: [qjadud1994/Korean-license-plate-Generator](https://github.com/qjadud1994/Korean-license-plate-Generator) (MIT). 폰트 대신 글자 PNG 사용 → 폰트 라이센스 회피.
|
|
|
- **자산이 만들 수 없는 글자 3개**: `하`, `호`, `배` — 합성 데이터에 안 등장. Step2 fine-tune의 실차 데이터로 보충 가정.
|
|
|
- **REGION_MAP 추정**: 자산 region PNG (A.jpg ~ P.jpg) → 한국 광역지자체 매핑은 일반 컨벤션 기반 추정값. `A='서울'` 한 개만 시각 검증됨. 나머지는 `tools/region_check.py` 실행 후 시각 확인하여 정정 필요.
|
|
|
- **세종 지역 빠짐**: 자산 region 16개라 17개 광역지자체 중 1개(추정 세종) 누락.
|
|
|
- **plate 배경 정확도**: 자가용은 정확, 영업용·전기차는 한국 표준과 약간 차이 (특히 전기차는 자산이 흰바탕+파란띠가 아니라 파란 두 줄). Step2 필수.
|
|
|
|
|
|
### 합성 분포 (한국 도로 추정)
|
|
|
| Type | 형태 | 비율 |
|
|
|
|---|---|---|
|
|
|
| 1 | 신형 가로 1줄 (자가용 흰) | 80% |
|
|
|
| 2 | 구형 가로 1줄 (흰, 작음) | 5% |
|
|
|
| 3 | 두 줄 노랑 (영업용 구형) | 10% |
|
|
|
| 4 | 두 줄 파/녹 (친환경 추정) | 5% |
|
|
|
|
|
|
---
|
|
|
|
|
|
## 학습 결과 평가 방법 (Step1 끝나면)
|
|
|
|
|
|
```bash
|
|
|
# 1. wandb dashboard에서 eval/f_score_e2e 추이 확인
|
|
|
# https://wandb.ai/hssong_cuuva/kr_lp_pgnet/runs/l0eqqbrb
|
|
|
|
|
|
# 2. best_accuracy 체크포인트로 평가 (paddle 명시 평가)
|
|
|
ssh cuuva@192.168.10.189 'docker exec kr_lp_pgnet bash -c "
|
|
|
cd /workspace/PaddleOCR
|
|
|
python3.10 tools/eval.py -c configs/e2e/kr_lp_pgnet.yml \
|
|
|
-o Global.checkpoints=./output/kr_lp_pgnet/best_accuracy
|
|
|
"'
|
|
|
|
|
|
# 3. 임의 이미지 추론
|
|
|
ssh cuuva@192.168.10.189 'docker exec kr_lp_pgnet bash -c "
|
|
|
cd /workspace/PaddleOCR
|
|
|
python3.10 tools/infer_e2e.py -c configs/e2e/kr_lp_pgnet.yml \
|
|
|
-o Global.infer_img=./train_data/kr_lp_synth/test/images/000000.jpg \
|
|
|
Global.pretrained_model=./output/kr_lp_pgnet/best_accuracy \
|
|
|
Global.load_static_weights=False
|
|
|
"'
|
|
|
```
|
|
|
|
|
|
## ONNX export (Step2 끝난 후)
|
|
|
```bash
|
|
|
# inference model export
|
|
|
ssh cuuva@192.168.10.189 'docker exec kr_lp_pgnet bash -c "
|
|
|
cd /workspace/PaddleOCR
|
|
|
python3.10 tools/export_model.py -c configs/e2e/kr_lp_pgnet.yml \
|
|
|
-o Global.pretrained_model=./output/kr_lp_pgnet/best_accuracy \
|
|
|
Global.save_inference_dir=./inference/kr_lp_pgnet_infer
|
|
|
"'
|
|
|
|
|
|
# paddle2onnx
|
|
|
ssh cuuva@192.168.10.189 'docker exec kr_lp_pgnet bash -c "
|
|
|
python3.10 -m pip install paddle2onnx
|
|
|
paddle2onnx --model_dir /workspace/PaddleOCR/inference/kr_lp_pgnet_infer \
|
|
|
--model_filename inference.pdmodel --params_filename inference.pdiparams \
|
|
|
--save_file /workspace/kr_lp_pgnet/kr_lp_pgnet.onnx \
|
|
|
--opset_version 13
|
|
|
"'
|
|
|
```
|
|
|
|
|
|
---
|
|
|
|
|
|
## 메모리 (project + feedback)
|
|
|
|
|
|
이 프로젝트 관련 사용자 기억은 Claude Code memory에 저장돼 있음:
|
|
|
- `project_kr_lp_pgnet.md` — 프로젝트 개요·분업 구조·아키텍처
|
|
|
- `feedback_local_no_runtime.md` — 로컬 Mac은 코드 작성 전용, 실행 금지
|
|
|
|
|
|
이 두 메모리는 새 Claude Code 세션에서도 자동 로드됨 (메모리 디렉토리: `/Users/songhyeonsu/.claude/projects/-Users-songhyeonsu-Documents-GIT-cuuva-AI/memory/`).
|