feat(prediction): DAR-03 탐지 튜닝 v2 (pair/매칭/G-02/G-03) #56

병합
htlee feature/dar03-tuning-v2 에서 develop 로 10 commits 를 머지했습니다 2026-04-16 11:07:47 +09:00
소유자

변경 사항

  • G-02 금어기 + G-03 미등록 어구 탐지 신설 — fishery_permit_cn 기반 permit_periods 파싱 + fishery_code 허용 어구 매핑
  • NAME_FUZZY 매칭 — 선박명 정규화(공백/대소문자/NO. 마커) + name_en 전용 fuzzy lookup. 매칭률 9.1% → 53.1%
  • pair_trawl tier 분류 — STRONG/PROBABLE/SUSPECT 3단계 + reject 사유 카운터. candidates 0→1,668, detected 0→57
  • pair join key → time_bucket — raw timestamp 우연 일치 불가 → 5분 리샘플 bucket 기준 inner join
  • pair base 확장 — 중국 MID 412/413/414 조업 속력대 전체 + pool 55k
  • match_ais_to_registry 범위 확장 — vessel_dfs 500척 → vessel_store._tracks 전체 중국 선박
  • 서버 스크립트 — diagnostic/hourly 에 tier/match_method/G-02/G-03/reject 추적

검증 결과 (redis-211 배포)

지표 이전 현재
매칭률 9.1% 53.1%
pair candidates 0 1,668
pair detected 0 57 (PROBABLE 9 + SUSPECT 50)
G-03 미등록 어구 0 37건
G-02 금어기 0 0 (정상: 현재 GN/FC 허가기간 내)
G-05 drift 303 274 (정상 범위)

테스트

  • prediction 로컬 스모크 테스트 (G-02/G-03/정규화/period 파싱)
  • redis-211 배포 후 실 사이클 검증 (10:58 사이클)
  • ZONE 내 매칭선박 G-02 정상 미발동 확인 (GN/FC 허가기간 내)
## 변경 사항 - **G-02 금어기 + G-03 미등록 어구 탐지 신설** — fishery_permit_cn 기반 permit_periods 파싱 + fishery_code 허용 어구 매핑 - **NAME_FUZZY 매칭** — 선박명 정규화(공백/대소문자/NO. 마커) + name_en 전용 fuzzy lookup. 매칭률 9.1% → 53.1% - **pair_trawl tier 분류** — STRONG/PROBABLE/SUSPECT 3단계 + reject 사유 카운터. candidates 0→1,668, detected 0→57 - **pair join key → time_bucket** — raw timestamp 우연 일치 불가 → 5분 리샘플 bucket 기준 inner join - **pair base 확장** — 중국 MID 412/413/414 조업 속력대 전체 + pool 55k - **match_ais_to_registry 범위 확장** — vessel_dfs 500척 → vessel_store._tracks 전체 중국 선박 - **서버 스크립트** — diagnostic/hourly 에 tier/match_method/G-02/G-03/reject 추적 ## 검증 결과 (redis-211 배포) | 지표 | 이전 | 현재 | |---|---|---| | 매칭률 | 9.1% | **53.1%** | | pair candidates | 0 | **1,668** | | pair detected | 0 | **57** (PROBABLE 9 + SUSPECT 50) | | G-03 미등록 어구 | 0 | **37건** | | G-02 금어기 | 0 | 0 (정상: 현재 GN/FC 허가기간 내) | | G-05 drift | 303 | 274 (정상 범위) | ## 테스트 - [x] prediction 로컬 스모크 테스트 (G-02/G-03/정규화/period 파싱) - [x] redis-211 배포 후 실 사이클 검증 (10:58 사이클) - [x] ZONE 내 매칭선박 G-02 정상 미발동 확인 (GN/FC 허가기간 내)
htlee added 10 commits 2026-04-16 11:07:27 +09:00
- SIMILARITY_OBSERVE 0.50 → 0.45 (pool 확대 후 recall 확보)
- min_common_samples 6 → 4 (비분류 선박 샘플 부족 보정)
- base_mmsis에 조업 속력대(1.5~5.0kn) 중국 412* 전체 추가
  (classifications 500척만으로 bbox 기점 부족 → 실제 공조 페어 누락)

검증 목표: 10분 사이클에서 pair_detected ≥ 1
_normalize_vessel_name()로 선박번호 suffix(호/號/号/NoN/#N) +
공백/구두점 제거 후 upper() 통일. EXACT 실패 시 FUZZY 단계로
매칭 시도. 동명이 후보 2개 이상이거나 이미 다른 MMSI 할당된 vid는
제외하여 중복 방지.

- match_ais_to_registry: NAME_EXACT → NAME_FUZZY (confidence 0.80)
- track_gear_identity: parent_name 매칭에도 FUZZY 적용
- _name_fuzzy_map 캐시로 1회 lookup

검증 목표: fleet_vessels.mmsi 매칭률 8.7% → 30%+
V029 fishery_permit_cn 스키마를 입력으로 하여 보류 중이던 G-02/G-03
판정 함수를 신설. classify_gear_violations() 시그니처에 permit_periods,
registered_fishery_code, observation_ts 매개변수 추가.

- G-02 (CLOSED_SEASON_FISHING, score 18): 관측 시각이 fishing_period_1/2
  허가 기간 밖이면 금어기 조업
- G-03 (UNREGISTERED_GEAR, score 12): 감지 어구가 fishery_code 허용 어구
  집합(PT→TRAWL/PT-S, GN→GILLNET, PS→PURSE, OT→TRAWL, FC→금지)에 없음
- fleet_tracker: _parse_period_range() 'YYYY/MM/DD - YYYY/MM/DD' 파서 +
  get_permit_periods() + get_registered_fishery_code()
- violation_classifier: CLOSED_SEASON_FISHING / UNREGISTERED_GEAR judgment →
  ILLEGAL_GEAR 카테고리 매핑

데이터 부재(permit_periods 빈 값, fishery_code 미등록) 시 판정 보류 → False.
검증 목표: 1시간 내 G-02/G-03 각 ≥ 1건
버그: vessel_store._tracks 는 raw_sog 만 보유 → _trajectory_similarity 가
sog/cog 컬럼 부재로 항상 0 반환 → candidates=0.

df_targets(select_analysis_targets 결과, 412* 전체 8k+ 에 sog/cog 계산)
를 mmsi 별로 groupby 하여 pool_tracks dict 생성. base 확장 필터의
sog 컬럼도 동일하게 적용.

첫 사이클 로그: base=512, pool=54825 → candidates=0 (2026-04-16 09:25).
수정 후 재검증 예정.
- pair_trawl._ensure_sog_cog(): _trajectory_similarity 진입 시 sog/cog 없으면
  vessel_store._compute_sog_cog() 로 haversine 계산 (tracks + timestamp 만 있으면 OK)
- pool 을 vessel_store._tracks 전체(55k)로 원복: 한국 440xxx/러시아 273xxx 페어 탐색 가능
- base 필터 중국 MID 확장: 412 → 412/413/414 (본토/홍콩/마카오)
- df_targets groupby 우회 제거 (불필요한 결합)
두 가지 근본 버그를 동시에 해결:

1. Join key 버그 — raw AIS timestamp(ms 단위) inner join 은 두 선박 간 우연히
   일치하는 확률이 거의 0. vessel_store._tracks 의 time_bucket(5분 리샘플)
   컬럼을 우선 사용. _pair_join_key() 헬퍼로 fallback 지원.

2. AND 게이트 0건 문제 — 스펙 100%(2h 연속 + 500m + SOG 2-4 + sog_delta 0.5 +
   cog 10°)를 전부 요구하면 실제 공조 페어를 놓침. Tier 분류로 재설계:
   - STRONG  : 스펙 100% (24 cycles, 기존 조건)
   - PROBABLE: 800m / SOG 1.5-5 / sog_delta 1.0 / cog 20° / 12 cycles + 0.6 ratio
   - SUSPECT : 동일 완화 조건 / 6 cycles + 0.3 ratio (플래그만)
   G-06 판정은 STRONG/PROBABLE 만. SUSPECT 는 약한 신호로 노출.

거부 사유 카운터(REJECT_COUNTERS) + tier 카운트를 사이클별 로그 출력.
'조건이 엄격한건지 실제 페어가 없는건지' 원인 구분 가능.

피드백 메모리: feedback_detection_tier.md
scheduler.py features write 확장:
- pair_tier (STRONG/PROBABLE/SUSPECT)
- pair_type, pair_reject_reason
- similarity, confidence
- registered_fishery_code
→ SUSPECT tier 까지 raw_pair 로 보존하여 통계 집계 가능

diagnostic-snapshot.sh (5분 주기):
- 4-4.1 pair_trawl tier 분포 + avg_sync_min
- 4-4.2 reject 사유 journal 로그 tail
- 4-4.3 G-02 금어기 상세 (observed_at, fishery_code)
- 4-4.4 G-03 미등록 어구 상세 (detected/registered/allowed)
- 7.5-2b match_method 분포 (EXACT vs FUZZY)
- 7.5-2c fishery_code × match_method 교차

hourly-analysis-snapshot.sh (1시간 주기):
- P3.5 match_method 분포 + avg_confidence
- P3.6 fishery_code × match_method 교차
- D3.6 pair_tier 분포 + avg_sync_min + avg_sep_nm
- D3.7 G-02/G-03 건수 + gear_judgment 분포
- D3.8 reject 사유 1시간 journal 집계
버그 원인: 초기 정규화가 선박번호(suffix)까지 제거 → '浙岭渔20865' → '浙岭渔' 로
축약 → 동명이 수십 개 발생 → len(unassigned)>1 조건에 전부 탈락 → FUZZY=0건.

중국/한국 어선명은 업체명+선박번호가 고유 식별자이므로 숫자 자체는 보존해야 함.
정규화는 공백/구두점/대소문자/'NO.' 마커만 통일:
  'ZHE LING YU 20865' ↔ 'zhelingyu20865' ↔ 'ZHE-LING-YU-20865' 모두 일치

FUZZY 매칭 key 는 name_en 만 등록 (AIS 보고 이름이 영문이 주류).
버그: all_ais 를 vessel_dfs(classification 통과 500척)만 대상으로 구성 →
허가선 906척 중 실제 AIS 존재 866척(upper bound 95.8%) 임에도 매칭률
9.4% 에 머물렀던 진짜 원인.

수정: vessel_store._tracks 전체에서 중국 MID(412/413/414) 활성 선박을
대상으로 match_ais_to_registry 호출. 매칭률 upper bound 95.8% 까지 회복 기대.

검증: 이번 AIS 실제 샘플 조사로 판명:
- AIS 고유 정규화 이름 411,908 개
- 허가선 정규화 이름 904 개
- 교집합 866 개 (95.8%)
→ 정규화 로직은 정상 작동. 문제는 호출 범위였음.
claude-bot 이 변경사항을 승인하였습니다. 2026-04-16 11:07:46 +09:00
claude-bot left a comment
멤버

MR 승인 (via /mr skill)

MR 승인 (via /mr skill)
htlee merged commit 25de59be12 into develop 2026-04-16 11:07:47 +09:00
htlee 삭제된 브랜치 feature/dar03-tuning-v2 2026-04-16 11:07:47 +09:00
"로그인하여 이 대화에 참여"
No reviewers
레이블 없음
마일스톤 없음
담당자 없음
참여자 2명
알림
마감일
기한이 올바르지 않거나 범위를 벗어났습니다. 'yyyy-mm-dd'형식을 사용해주십시오.

마감일이 설정되지 않았습니다.

의존성

No dependencies set.

Reference: gc/kcg-ai-monitoring#56
No description provided.