Files
HC900-Crawler/docs/작업지시서-학습형제어-다음단계.md
windpacer 1bc46b1eb0 feat: 6-1차 컬럼 학습형 제어 오프라인 분석 (생산맵·shadow·startup)
신암정유 6-1차 측류 솔벤트 컬럼(C-6111) 실데이터로 오퍼레이터 모방 제어 분석:

- 데이터 추출기 tag_frame() (field_hist WIDE 포맷 디코드) + 운전모드 분류
- ① 생산맵: 스팀유량=f(피드,제품,목표T_C) 운전점 GBM R²0.99 (steam/feed≈0.73)
- shadow 백테스트: in-envelope 오퍼레이터 OP 94% 모방, OOD 게이트→폴백
- 롤링 재학습: 새 로드레짐 적응 (5월 OP MAE 3.9→1.2%)
- 캠페인내 트림: 컬럼 자기제어, 피드백 미미 → 전향 맵이 제어 지배
- ② START-UP 절차: 레시피 + 제품컷인 트리거(reb-A 84.5℃, ΔT 2℃, 조건기반)

문서: 설계·진행 플랜 + 남은 작업(형제확장·shutdown·assist·live포팅) 작업지시서.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 17:33:17 +09:00

8.9 KiB

작업지시서 — 학습형 제어 다음 단계 (6-1차 이후)

작성 2026-06-05. 전체 설계·진행로그는 docs/학습형제어-오퍼레이터모방-플랜.md(특히 §0 오리엔테이션, §15 데이터, §16 분석). 메모리: learned-control-operator-imitation.md. 이 문서는 남은 4개 작업의 실행 지시서.


0. 현재까지 (필독 컨텍스트)

완료(6-1차 컬럼 C-6111, 오프라인 분석 완주):

  • ① 생산제어: 전향맵 스팀유량=f(피드,제품,목표T_C) GBM R²0.99 (본질 steam/feed≈0.73) + shadow 94% 모방 + 롤링/OOD 안전 + 캠페인내 피드백 트림은 미미(컬럼 자기제어).
  • ② START-UP: 레시피(진공→스팀승온→전환류 라인아웃→제품컷인→피드램프) + ★컷인 트리거 reb-A 84.6±0.5℃ & ΔT(A-D) 1.9±0.4℃(조건기반).

환경/자산:

  • DB: field_hist (별도 DB, PG16 컨테이너 iiot-timescaledb, localhost:5432, postgres/postgres). shinam 실데이터 2026-02~06 30초. WIDE 포맷(§15.215.3 디코드).
  • Python: mcp-server/.venv/bin/python (psycopg3=psycopg, pandas, sklearn1.8, matplotlib. psycopg2·pyarrow 없음 → pickle 사용).
  • 코드: scripts/analysis/c6111_*.py재사용 추출기 tag_frame(conn, role_map) (c6111_extract.py), SteamPredictor(c6111_shadow.py).
  • C-6111 토폴로지: 기존 hc900.ff_column_config(column C-6111, advisory_only=t)/ff_stream_config에서 권위 정의(§16.1).

핵심 gotcha:

  • 컬럼 디코드: ptname→ptlist.pid→mapping(tid,oit)→cont{tbl}.col{oit:02d}, 시간축 dtat.
  • 운전점 집계가 필수: 정상상태 98%라 점단위 회귀는 음의 R² → 6h 중앙값으로 집계해야 맞음(§16.6).
  • OOD 게이트 필수: 새 로드레짐은 외삽 실패 → 롤링 재학습 + OOD→오퍼레이터 폴백(§16.7~8).
  • pandas df.product는 메서드와 충돌 → df["product"]. col은 0패딩(col03). pd.read_sql는 psycopg3에 경고만(동작OK).

작업 1 — (4) 6-2·8·9·10 형제 컬럼 확장 [우선순위 1]

목적: 동일 코드가 형제 측류 솔벤트 컬럼(6-2, 8, 9, 10차)에 그대로 도는지 검증 + startup 샘플 보강.

선행 확인:

  1. 형제 컬럼 토폴로지 출처: ff_column_configC-6111(6-1)만 있을 가능성 → 6-2/8/9/10은 태그 네이밍 규칙으로 ROLES 유도.
    • 6-1 규칙(끝자리 역할): feed=FICQ-6101, reflux=FICQ-6113, light(D)=6114, heavy(B)=6116, product(P)=6118, steam밸브=TICA-6111A.OP, steam유량=FIQ-6115, 민감단=TI-6111C, 진공=PICA-6111, DP=PI-6111B, 온도프로파일 TI-6111A/B/C/D.
    • 일반화: 차수·train 접두 {P}1 (6-1=61, 6-2=62, 8=81, 9=91, 10=101). 즉 6-2=FICQ-6201/6213/6214/6216/6218, TICA-6211A 등.
  2. 반드시 ptlist로 검증: 각 형제의 실제 태그가 같은 끝자리 규칙인지 쿼리로 확인(8/9/10은 다를 수 있음).

단계:

  1. c6111_extract.pyROLES함수 roles_for(prefix)로 파라미터화(예: prefix="62"→ FICQ-6201…). asset도 해당 차수(/ASSETS/P6는 6-1·6-2 공통, 8/9/10은 /ASSETS/P8/9/10).
  2. ptlist로 각 컬럼 ROLES 자동검증(미해결 태그 경고). 끝자리 규칙이 다르면 컬럼별 매핑표 작성.
  3. 추출→운전모드 분류(c6111_extract) → 생산맵(c6111_prodmap) → shadow/롤링(c6111_shadow/rolling) → startup(c6111_startup)을 컬럼 인자로 일괄 실행하는 run_column.py 래퍼 작성.
  4. 컬럼별 산출: steam/feed비, 맵 R², shadow 일치율, startup 컷인 트리거.

산출물: 형제별 결과표(steam/feed, R², 컷인트리거) + 통합 startup 트리거(샘플↑로 reb-A/ΔT 변동성 재추정).

검증기준: 각 형제 생산맵 R²>0.95(운전점), shadow in-envelope 일치율>85%. startup 컷인 트리거가 6-1과 정합(같은 솔벤트 유형이면 유사 예상).

주의: 8/9/10은 컬럼 크기·운전조건 다를 수 있음 → steam/feed비·트리거가 6-1과 다르면 그게 정상(컬럼별 학습). 죽은 플랜트 3·4차 제외. 5차는 유형 미확인(§15.9).


작업 2 — ③ SHUTDOWN 절차 [우선순위 2]

목적: 안전 정지 절차 학습(startup의 역순). few-shot.

선행: c6111_startup.py를 템플릿으로. SHUTDOWN = 제품 컷오프(product >100→0 하강엣지) 기준.

단계:

  1. detect_cutins를 미러링한 detect_cutoffs 작성: product 하강엣지(>100→<50)이고 직후 steam도 내려감(shutdown 진입) 탐지.
  2. 컷오프 정렬 후 역시퀀스 추출: 생산 → 피드 감소제품 컷오프 → 전환류 복귀? → 스팀 차단진공 해제 → 냉각.
  3. 단계 타이밍 + 트리거: "언제 피드 줄이기 시작? 제품 컷오프 시 컬럼상태? 스팀 차단 순서?" 추출.
  4. startup 에피소드 목록(02-15, 04-30, 05-02, 05-13 등)에 대응하는 shutdown이 직전에 있음(같은 에피소드의 앞부분) → 재활용.

산출물: SHUTDOWN 레시피(단계 시퀀스+타이밍+트리거) + 플롯(컷오프 정렬 중첩).

검증기준: 깨끗한 shutdown ≥3건에서 시퀀스 일관. 안전 관점(급격 차단 없이 순차 감소) 확인.

주의: shutdown은 안전 최우선 — 급격 진공해제/스팀차단 순서가 장비보호에 중요. 데이터의 순서·rate를 그대로 보존.


작업 3 — (2) operator-assist 패키징 [우선순위 3, 현장투입 1단계]

목적: ①의 예측기를 "권장 OP + 신뢰도" 자문 출력으로 패키징(write 안 함). 현장 신뢰구축 단계.

선행: SteamPredictor(c6111_shadow.py) + OOD 게이트 + 롤링 재학습 로직.

단계:

  1. 예측 서비스화(Python 먼저): predict(live_tags) → {rec_OP, confidence(in/OOD), rec_steam_flow}.
    • 입력 평활(인과 trailing), 운전점맵 예측→밸브역특성→OP, envelope 체크.
    • 롤링 재학습 스케줄(일/주 단위, expanding 또는 trailing window).
  2. 모드 인지: 현재 운전모드(PROD/LINEOUT/STARTUP…) 분류(c6111_extract.classify_phases) → PROD에서만 ① 맵 조언, STARTUP이면 ② 레시피(컷인 게이트) 조언.
  3. 출력 UI: 기존 ...AdvisorService/FF 자산(FeedforwardSupervisor, FfTrackingStore) 패턴으로 화면에 "권장 OP=X% (신뢰: 구간내/범위밖)" 표시 + 오퍼레이터 실조작 병행 로깅(비교).
  4. shadow 로깅: 권장 vs 실제 OP 차이 누적 → 신뢰 리포트.

산출물: 자문 API/서비스 + 화면 + 권장-vs-실제 로그/리포트.

검증기준: 신뢰구간에서 권장 OP가 오퍼레이터와 ±2% 이내 90%+(§16.7 재현). OOD 시 "범위밖→수동" 정확 표시.

주의: 절대 write 금지(advisory_only). OOD·비-PROD에선 조언 보류(폴백). hunting 공포 고려 — 조언도 gentle(작은 변화).


작업 4 — (5) live C# shadow 포팅 [우선순위 4, 실플랜트 연결]

목적: 검증된 예측기를 C# 크롤러에 포팅, 플랜트6 live(gRPC) 에 shadow 연결.

선행: 작업3 로직 확정. 플랜트6 HC900 통신 살아있음(live값 가공이라도 경로 테스트 가능, §0.2). ff_column_config C-6111 advisory_only=t 이미 설정.

단계:

  1. 모델 산출물 export: Python에서 학습한 steam맵(GBM)·밸브역특성·envelope를 경량 포맷(JSON 계수/룩업 또는 ONNX)으로 export. (선형근사 steam≈0.73·feed+보정이면 C#에서 직접 계산 가능 — 단순화 권장.)
  2. C# Infrastructure/Control에 예측기: 기존 FeedforwardSupervisor/FeedRampAdvisor 옆에 SteamAdvisor 추가. gRPC 실시간 태그(피드 FICQ-6101, 제품 6118, T_C TI-6111C, reb-A, 진공 등) 읽어 권장 OP 산출.
  3. 운전모드 분류 + OOD C#에 포팅(임계 §16.3-2, envelope §16.7).
  4. shadow 로깅: FfTrackingStore에 권장 vs 실제 OP 기록. 화면 노출(advisory).
  5. 롤링 재학습: 주기적 Python 재학습→계수 갱신 파이프(또는 C#서 온라인 회귀).

산출물: C# SteamAdvisor 서비스(advisory) + live shadow 로그 + UI.

검증기준: live 태그로 권장 OP 산출·표시 동작. (live 데이터가 가공이라 정확도보다 경로·안전(OOD폴백)·로깅 검증 우선.)

주의: live값이 현재 시뮬/가공 → 정확도 평가는 field_hist 백테스트로, live는 통합·안전 검증용. write 금지. 실제 실데이터 확보 시 재검증.


권장 순서

작업1(형제확장) → 작업2(shutdown) → 작업3(operator-assist) → 작업4(live포팅). 1·2는 분석 연장(코드 재사용·샘플보강), 3·4는 현장 투입. 3 전에 1로 다컬럼 일반화를 끝내면 assist가 전 컬럼 커버.

공통 참조

  • 디코드/데이터: 플랜 §15. C-6111 토폴로지: §16.1. 방법론 교훈: §16.6(운전점), §16.7(OOD), §16.8(롤링).
  • 코드 시작점: scripts/analysis/c6111_extract.py(tag_frame, ROLES, classify_phases), c6111_shadow.py(SteamPredictor).