Pointcept:SmallObjectAnalysis
PointGroup 작은 객체 미검출 원인 분석 절차
배경
- Pointcept의 PointGroup(
PG-v1m1, SpUNet backbone)으로 instance segmentation 진행 중 - 최초 100장에서 품질이 낮아 약 600장의 PointCloud를 추가하여 훈련
- 데이터를 늘렸음에도 작은 객체가 여전히 잡히지 않음
결론 요약
데이터를 늘려도 작은 객체가 안 잡히는 경우, 원인은 대개 "데이터 양"이 아니라 아래 셋 중 하나이다.
- 파이프라인에 박힌 크기 필터
- semantic 브랜치의 누락
- offset 회귀의 대형 객체 편향
이 셋을 분리해서 확인하는 순서로 진행한다.
구조적 원인: 코드에 박힌 크기 필터
기준 파일:
-
configs/scannet/insseg-pointgroup-v1m1-0-spunet-base.py -
pointcept/models/point_group/point_group_v1m1_base.py -
pointcept/engines/hooks/evaluator.py
PointGroup 코드에는 작은 객체를 걸러내는 지점이 최소 네 곳 있다. 전부 grid_size=0.02 복셀 단위이다.
| 지점 | 기본값 | 효과 |
| | 0.02 | 2cm 복셀화. 작은 객체는 점 수가 급감 |
| | 50 | 50점 미만 클러스터는 생성되지 않음 |
| | 100 | 100점 이하 proposal 폐기 ( |
| evaluator | 100 | 100점 미만 예측은 평가에서 제외 ( |
즉 복셀화 후 100점 이하가 되는 객체는 모델이 맞춰도 출력되지 않고, 출력돼도 평가되지 않는다. 데이터를 6배 늘려도 이 벽은 그대로이다.
그 외 구조적 요인
- 클러스터링은
segment_pred가 같은 점끼리만 묶는다. semantic 브랜치가 작은 클래스를 벽/바닥으로 분류하면 instance 단계로 아예 진입하지 못한다. - offset loss는 점 단위 평균이라 큰 객체가 gradient를 지배한다. 작은 객체의 중심 예측은 노이즈가 커서
cluster_thresh=1.5(3cm) 안에서 이웃 객체와 병합되거나 쪼개지기 쉽다.
진행 순서
1. 데이터 통계
- 클래스별 인스턴스 수, 인스턴스당 점 수 분포를 GridSample 0.02 적용 후 기준으로 산출
- 100점 미만 인스턴스 비율 = 구조적으로 검출 불가능한 비율
- 추가한 600장의 라벨 품질 확인
- 작은 객체가 일관되게 라벨링되었는지
- instance id가 scene 내에서 유일한지
- 원본 100장과 센서/점 밀도가 같은지
2. Semantic 상한 확인
- 검증 셋에서 클래스별 semantic IoU 확인
- 작은 클래스의 IoU가 낮으면 instance 문제가 아니라 semantic 문제
- 처방: class-weighted CE, 작은 객체 포함 scene 오버샘플링,
grid_size축소
3. 오라클 실험으로 브랜치 분리
| 실험 | AP가 크게 오르면 |
| GT semantic + 예측 offset으로 클러스터링 | semantic 브랜치 문제 |
| 예측 semantic + GT centroid로 클러스터링 | offset 브랜치 문제 |
둘 다 오르지 않으면 필터 또는 라벨 문제이다.
4. 필터 완화 실험
재훈련 없이 test만 다시 실행하면 된다.
| 파라미터 | 기본값 | 완화값 |
| | 50 | 10 |
| | 100 | 20 |
| evaluator | 100 | 20 |
AP25가 회복되면 모델은 이미 잡고 있는데 필터가 버리고 있었다는 뜻이다.
5. 실패 유형 분류
작은 객체 GT 각각에 대해 예측을 대조하여 네 가지로 태깅한다.
- semantic 누락
- 이웃 객체에 병합
- 여러 조각으로 분리
- 크기 필터로 폐기
이 분포가 최종 처방을 결정한다.
6. 훈련 상태 점검
- 100장 → 700장이면 같은 800 epoch라도 iteration이 7배
- 학습 곡선과 train 셋 AP를 함께 확인
- train에서도 작은 클래스가 안 잡히면 underfit 또는 라벨 문제
- train에서는 잡히는데 val에서 안 잡히면 일반화 문제
처방 후보
-
grid_size0.02 → 0.01 (메모리 2~4배 증가, 작은 객체에 가장 직접적) - offset loss를 인스턴스 단위로 정규화하거나 작은 인스턴스에 가중치 부여
- semantic CE에 class weight, 작은 객체 포함 scene 반복 샘플링
-
SphereCrop sample_rate=0.8이 작은 객체를 잘라내는지 확인 - PointGroup 자체의 한계라면 query 기반인 SGIFormer 검토
-
configs/scannetpp/insseg-sgiformer-v1m1-0-ptv3-base.py
-