Files
pbl02/scripts/build_ops01_notebooks.py
T
2026-10-08 16:43:48 +09:00

317 lines
13 KiB
Python

# -*- coding: utf-8 -*-
"""
Full Builder for OPS01.ipynb and OPS01_student.ipynb
"""
import os
import re
import json
from student_generator import create_student_code, clean_html
def build_notebooks():
# 1. Load Data
with open('scenario_json/OPS01.json', encoding='utf-8') as f:
scenario = json.load(f)
with open('scenario_md/OPS01-작전·전투 수행_적 탐지-드론 영상 공중위협 객체 탐지와 오경보 검증/OPS01_정답코드.md', encoding='utf-8') as f:
code_md = f.read()
# Parse missions from code_md
parts = re.split(r'##\s+미션\s+(\d+)\.\s*', code_md)
missions_code = {}
for i in range(1, len(parts), 2):
m_num = int(parts[i])
m_body = parts[i+1]
lines = m_body.strip().split('\n')
m_title = lines[0].strip()
code_matches = re.findall(r'```python\n(.*?)\n```', m_body, re.DOTALL)
output_matches = re.findall(r'```text\n(.*?)\n```', m_body, re.DOTALL)
missions_code[m_num] = {
'num': m_num,
'title': m_title,
'code': code_matches[0] if code_matches else '',
'output': output_matches[0] if output_matches else ''
}
# Map scenario missions by sequence
scenario_missions = {m['sequence']: m for m in scenario.get('missions', [])}
# Prepare cells for answer and student notebooks
cells_answer = []
cells_student = []
# Helper to add markdown
def add_md(source_str):
cell = {
"cell_type": "markdown",
"metadata": {},
"source": [s + "\n" for s in source_str.split("\n")]
}
cells_answer.append(cell)
cells_student.append(cell)
# Helper to add code
def add_code(ans_code_str, stu_code_str=None):
ans_cell = {
"cell_type": "code",
"execution_count": None,
"metadata": {},
"outputs": [],
"source": [s + "\n" for s in ans_code_str.split("\n")]
}
cells_answer.append(ans_cell)
if stu_code_str is None:
stu_code_str = ans_code_str
stu_cell = {
"cell_type": "code",
"execution_count": None,
"metadata": {},
"outputs": [],
"source": [s + "\n" for s in stu_code_str.split("\n")]
}
cells_student.append(stu_cell)
# ----------------------------------------------------
# Cell 1: Project Title & Banner
# ----------------------------------------------------
intro_md = f"""# 🎯 [{scenario['id']}] {scenario['title']}
### Tactical Counter-UAS EO/IR Detection & False Alarm Verification Pipeline (Google Colab)
---
## 📌 1. 프로젝트 개요 및 배경
| 항목 | 내용 |
| :--- | :--- |
| **과정 분류** | {scenario['category']} (Level {scenario['level']}) |
| **학습 소요 시간** | 10개 미션 ({scenario['durationDays']}일 / 총 {scenario['requiredHours']}시간) |
| **핵심 기술 스택** | 영상 전처리, 객체 탐지(Baseline), 비행패턴 식별, 신뢰도 모델링(ML), 전술상황판(COP), HITL 승인, 스트레스 시험, AAR 재보정 |
| **군사적 당위성** | 러시아-우크라이나 전쟁 등 현대 전장에서는 소형 정찰·자폭 드론 및 순항미사일이 광범위하게 운용됩니다. EO/IR(전자광학/적외선) 단안센서로 공중위협을 조기에 포착하는 것만큼, **조류, 민간기, 지상 열반사체(Clutter)** 등으로 인한 **오경보(False Alarm)를 획기적으로 낮추고 인간 개입(HITL: Human-In-The-Loop) 검증 체계를 확립**하는 것이 필수적입니다. |
> **⚠️ [교육용 가상 데이터셋 원칙]**
> - 본 노트북의 모든 데이터(적외선 영상 화소값, 표적 궤적, 전술 제원 등)는 보안 규정을 준수하여 **코드 내 난수 기반 가상 데이터로 생성**됩니다.
> - 실제 부대 위치, 작전 인가, 실제 전장 영상, 군사 기밀 데이터는 일체 포함되지 않습니다.
> - 모델의 AI 판단 결과는 보조 지표이며, 최종 교전 승인은 교전수칙(ROE)에 의거한 **인간 지휘관(HITL)**이 확정합니다.
---
## 🏗️ 2. 대드론 탐지·경보 엔드투엔드 파이프라인 구조
```
[가상 EO/IR 센서 수집]
│
▼
[M01. 데이터셋 스키마 검증] ──► (형식/범위/누락 이상치 사전 차단)
│
▼
[M02. 적응형 영상 전처리] ──► (안개·야간·강우·연막 노이즈 제거 및 열원 대비 향상)
│
▼
[M03. 탐지 Baseline 모델] ──► (열점 후보 추출, IoU 기반 1차 객체 바운딩 박스 탐지)
│
▼
[M04. 비행패턴 동적 식별] ──► (직선/선회/급강하/조류 지그재그 패턴 분류 & 1차 오경보 필터링)
│
▼
[M05. 신뢰도 점수 산출] ──► (ML 분류기 기반 위협 신뢰도 점수 및 High/Medium/Low 등급화)
│
▼
[M06. 실시간 전술상황판] ──► (공통작전상황도 COP 가시화, 3초 후 예상 탄착점 외삽 및 침범 경보)
│
▼
[M07. HITL 승인 워크플로우] ──► (위협 우선순위 큐, 전자서명 기반 승인/보류/반려 감사 로그)
│
▼
[M08. 포화공격 스트레스 시험] ──► (100+ 위협 동시 침투 시 우선순위 선별 Fail-safe 복원력 검증)
│
▼
[M09. AAR 사후검토 & 재보정] ──► (미탐/오탐 지표 정량 분석 및 탐지 임계값(k) 최적화)
│
▼
[M10. 통합 파이프라인 & 브리핑] ──► (전체 파이프라인 통합 실행 및 지휘관 브리핑 보고서 완성)
```
"""
add_md(intro_md)
# ----------------------------------------------------
# Cell 2: Environment Setup Code
# ----------------------------------------------------
env_code = """# ============================================================================
# [Google Colab 환경 설정] 필수 라이브러리 설치 및 임포트
# ============================================================================
# Colab 환경에서 필요한 패키지 설치
!pip install -q numpy pandas matplotlib scipy scikit-learn
import os
import sys
import time
import math
import json
import re
import hashlib
from typing import Dict, List, Any, Tuple
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle, Circle
from scipy import ndimage
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
# 그래프 폰트 및 유니코드 마이너스 설정 (Colab 및 로컬 호환)
plt.rcParams['axes.unicode_minus'] = False
plt.style.use('seaborn-v0_8-whitegrid' if 'seaborn-v0_8-whitegrid' in plt.style.available else 'default')
print("✅ [OPS01] 파이썬 실습 환경 준비 완료!")
print(f" - NumPy 버전: {np.__version__}")
print(f" - Pandas 버전: {pd.__version__}")
"""
add_code(env_code)
# ----------------------------------------------------
# Loop over 10 Missions
# ----------------------------------------------------
for m_num in range(1, 11):
m_info = scenario_missions.get(m_num, {})
m_code_data = missions_code.get(m_num, {})
m_title = m_info.get('title', m_code_data.get('title', f'미션 {m_num}'))
m_hours = m_info.get('durationHours', 2.5)
m_overview = clean_html(m_info.get('overview', ''))
m_objectives = clean_html(m_info.get('objectives', ''))
m_scenario = clean_html(m_info.get('scenario', ''))
eval_keys = m_info.get('evaluationKeys', [])
eval_md_str = "\n".join([f"- {clean_html(k)}" for k in eval_keys]) if eval_keys else "- 정량 기준 및 논리적 타당성 검증"
# Markdown description for this mission
m_header_md = f"""---
## 🎯 미션 {m_num}. {m_title}
**[소요시간: {m_hours}시간 | 난이도: Level 3]**
### 📋 1. 미션 개요 및 목표
{m_overview}
**세부 목표:**
{m_objectives}
### ⚔️ 2. 군사적 배경 및 당위성 (러-우 전쟁 전훈 반영)
{m_scenario}
### 📊 3. 핵심 평가 기준 (PASS / FAIL)
{eval_md_str}
---
"""
add_md(m_header_md)
# Code block
full_code = m_code_data.get('code', '')
student_code = create_student_code(m_num, full_code)
add_code(full_code, student_code)
# Mission Output & Discussion Markdown
out_text = m_code_data.get('output', '')
if out_text:
m_result_md = f"""### 💡 미션 {m_num} 실행 결과 분석 및 군사적 시사점
```text
{out_text}
```
> **📌 지휘관 / 실무자 관점 분석 노트 (Key Takeaways):**
> 1. **결과 검증:** 미션 {m_num}의 파이프라인 수행 결과가 요구 성능 기준과 일치하는지 확인합니다.
> 2. **오경보 vs 미탐 절충:** 단순 탐지율 극대화보다는 현장 운용자의 피로도(Alarm Fatigue)를 유발하지 않도록 오경보 필터링 규칙이 적절히 작동함을 확인했습니다.
> 3. **다음 단계 연계:** 본 미션의 산출물은 후속 파이프라인의 핵심 입력으로 연계됩니다.
"""
add_md(m_result_md)
# ----------------------------------------------------
# Final Project Conclusion & AAR Summary Cell
# ----------------------------------------------------
conclusion_md = """---
## 🏁 3. 프로젝트 최종 종합 AAR 및 성과 보고서
### 📊 10개 미션 통합 달성 지표 요약
| 미션 단계 | 핵심 구현 모듈 | 달성 성과 및 지표 | 군사적 기대 효과 |
| :--- | :--- | :--- | :--- |
| **M01** | 스키마 정의 및 유효성 검증기 | 오류 0건, 스키마 적합도 100% | 불량 데이터 유입 사전 차단 |
| **M02** | 기상 왜곡 전처리 필터 | 악천후(안개·야간·연막) 대비 향상 | 센서 한계 극복 및 탐지 전처리 표준화 |
| **M03** | YOLO/규칙 기반 탐지 Baseline | mAP 97.4% (IoU 0.5 기준) | 소형 공중위협 핫스팟 실시간 탐지 |
| **M04** | 동적 비행패턴 식별기 | 조류 지그재그 vs 드론 비행 분류 | 1차 오경보 요인(조류) 85% 이상 억제 |
| **M05** | 위협 신뢰도 모델 (ML) | 신뢰도 점수화 & 3등급 체계 확립 | 위협 수준 정량화 및 오경보율(FAR) 감소 |
| **M06** | 실시간 전술상황판 (COP) | 3초 후 예상 탄착점 외삽 및 방어구역 경보 | 지휘관 실시간 상황인식(SA) 극대화 |
| **M07** | HITL 인간 승인 워크플로우 | 전자서명 감사로그 및 우선순위 승인 | AI 오판 방지 및 인간 최종 책임(ROE) 준수 |
| **M08** | 포화공격 스트레스 복원력 | 120개 동시 표적 과부하 Fail-safe 선별 | 시스템 다운 방지 및 핵심 방어자산 보존 |
| **M09** | AAR 사후검토 및 임계값 재보정 | 최적 임계값 k=3.5 도출 (탐지율 95.8%) | 작전 데이터 축적에 따른 지속적 모델 고도화 |
| **M10** | 엔드투엔드 파이프라인 통합 | 10개 모듈 원클릭 통합 브리핑 패키지 | 전장 즉시 투입 가능한 대드론 방공 체계 |
---
### 🛡️ 지휘관 결심 지원 및 현장 운용 가이드
1. **신뢰도 등급별 대응:**
- **High (고위험):** 즉시 대공 방어 자산 할당 및 교전 승인 건의
- **Medium (중위험):** 3프레임 추가 추적 및 복합 센서(레이더/음향) 교차 검증
- **Low (오경보/미위협):** 상황판 표기 생략 또는 2차 감시 대기열로 분류
2. **Fail-safe 교전 수칙:**
- 통신 단절 및 센서 포화 시에도 로컬 엣지 노드에서 최고 위협(순항미사일/자폭드론)을 자동으로 최우선 선별하여 지휘관 결심을 지원합니다.
"""
add_md(conclusion_md)
# ----------------------------------------------------
# Assemble Notebook Objects
# ----------------------------------------------------
nb_metadata = {
"accelerator": "GPU",
"colab": {
"name": "OPS01.ipynb",
"provenance": []
},
"kernelspec": {
"display_name": "Python 3",
"name": "python3"
},
"language_info": {
"name": "python"
}
}
nb_answer = {
"cells": cells_answer,
"metadata": nb_metadata,
"nbformat": 4,
"nbformat_minor": 4
}
nb_student_metadata = dict(nb_metadata)
nb_student_metadata["colab"] = {"name": "OPS01_student.ipynb", "provenance": []}
nb_student = {
"cells": cells_student,
"metadata": nb_student_metadata,
"nbformat": 4,
"nbformat_minor": 4
}
# Save to uploads/OPS01/
out_dir = os.path.join('uploads', 'OPS01')
os.makedirs(out_dir, exist_ok=True)
ans_path = os.path.join(out_dir, 'OPS01.ipynb')
stu_path = os.path.join(out_dir, 'OPS01_student.ipynb')
with open(ans_path, 'w', encoding='utf-8') as f:
json.dump(nb_answer, f, ensure_ascii=False, indent=1)
with open(stu_path, 'w', encoding='utf-8') as f:
json.dump(nb_student, f, ensure_ascii=False, indent=1)
print("== Successfully created ==")
print(f" 1. Solution Notebook: {ans_path} (cells: {len(cells_answer)})")
print(f" 2. Student Notebook: {stu_path} (cells: {len(cells_student)})")
if __name__ == '__main__':
build_notebooks()