비운영 참조

평균으로 당기기

계층적 경험 베이즈 축소

한 줄 결론 — 적은 표본의 극단값을 공통 평균 쪽으로 완화하는 후보다. 채택되지 못한 채 2026-08-19 결정으로 비운영 참조가 됐다.

왜 믿나

잠정 — 아직 채택하지 않는 이유

학습은 평가일보다 앞선 날짜만 쓰고, 성적은 뒤 날짜에서만 잰다. 그래도 관측일과 만석 표본이 관문에 닿기 전에는 잠정으로 읽고 순위와 승자를 정하지 않는다. 관문 기준은 평가 규약에 있다.

숫자의 원장은 아래 동결 이력 성적이다. 페이지를 열면 일일 평가 API에서 마지막 이력을 한 번 받아오고, 실패하면 배포 시점 값과 스탬프가 그대로 남는다.

이 모델의 일일 채점은 2026-08-19 평가일까지로 끝났다. 08번(A18)을 단일 운영 모델로 확정하며 evaluation-v3에서 도입한 결정이고, 현재 evaluation-v6도 이어받는다. 새 점수는 만들지 않으며 마지막 값과 중단 시점은 이력에 남는다.

동결 이력 성적

상태 잠정 · 역할 비운영 참조 · 배포 시점 값 · 일일 평가 2026-08-16분 · 생성 08-17 00:15 KST

종합 점수
51.9
평가 관측일
2일 / 10일
만석 누적
173건 / 100건
만석 관측일
2일 / 5일

전체 표본 — 평가 18,055행 · 만석 173건 · 비만석 17,882건

지표오늘 값읽는 법
Brier0.0097얼마나 빗나갔나 — 예측확률과 실제 0·1의 제곱 오차 평균. 낮을수록 좋다.
만석 누락률100.0%실제 만석 중 확률 50% 미만으로 말한 비율. 낮을수록 좋다.
ROC-AUC0.827만석·비만석 한 쌍에서 만석에 더 높은 확률을 줄 가능성. 높을수록 좋다.
Log loss0.0479확신하고 틀릴수록 커지는 벌점. 낮을수록 좋다.
ECCE-MAD0.0075확률 오차를 누적했을 때 가장 벌어진 폭. 낮을수록 좋다.
PR-AUC0.057드문 만석을 위쪽으로 모으는 힘. 높을수록 좋다.
확률 쏠림0.0075평균 예측확률에서 실제 만석률을 뺀 값. 0에 가까울수록 좋다.
비용 1:10.0096잘못 안심과 과한 경고를 1:1로 둔 평균 비용. 같은 비용 가정끼리만 비교한다.
비용 2:10.0200잘못 안심을 과한 경고의 2배 비용으로 둔 평균 비용.
비용 4:10.0449잘못 안심을 과한 경고의 4배 비용으로 둔 평균 비용.

점수 50 = 시간순 과거 만석률 기준 모델 · 자세한 기준은 평가 규약

구간별 성적

구간행만석Brier만석 누락ROC-AUC
주말18,0551730.0097100.0%0.827
출근2,70200.0005——
퇴근4,195120.0050100.0%0.958
그 외11,1581610.0137100.0%0.860
노선 16507,5321600.0195100.0%0.815
노선 333010,523130.0027100.0%0.879
노선 1650·출근97000.0003——
노선 1650·퇴근1,694120.0068100.0%0.969
노선 1650·그 외4,8681480.0277100.0%0.837
노선 3330·출근1,73200.0007——
노선 3330·퇴근2,50100.0039——
노선 3330·그 외6,290130.0028100.0%0.930

평가 행이 없는 구간 1개: 평일

아래 해설의 실측 수치는 연구 구간 기록(M1–M3 · 2026-08-15 동결) 기준이다. 오늘 수치는 위 표가 매일 갱신한다.

Q. 이 모델은 지금 무엇을 계산하나?

관측이 적은 노선·정류장·시간 집단에서도 출발 뒤 만석 확률 추정이 한두 사건에 과도하게 출렁이지 않게 하는 문제를 다룬다.

Q. 어떻게 계산하나?

적격 사건을 만든다

현재 운영 수집기 관측에서 제외 규칙을 통과한 사건만 남기고 같은 통과 사건은 한 번만 센다.

공통 경향을 추정한다

평가일보다 앞선 학습 날짜에서 사전에 고정한 집단들의 만석·비만석 분포를 모아 베타 사전분포의 α와 β를 추정한다. 평가 구간의 라벨은 이 단계에 넣지 않는다.

집단 관측과 공통 경향을 합친다

한 집단의 만석 건수를 x, 적격 사건 수를 n이라 두고 사후 평균 (x+α)/(n+α+β)를 만석 확률로 계산한다. n이 작을수록 공통 경향의 영향이 크고 n이 커질수록 그 집단의 관측이 더 많이 반영된다.

뒤 날짜에서 검증한다

만든 확률을 뒤 한국 표준시 날짜의 라벨과 맞춰 본다. 검증 결과를 본 뒤 집단이나 사전분포를 다시 고쳐 같은 구간의 점수를 내지 않는다.

이 방식의 강점

Q. 만석을 한 번도 못 본 셀은 위험 0%인가?

아니다. 코퍼스 학습분의 노선×정류장×30분 셀은 833개다. 이 중 281개(33.73%)는 표본이 10건 이하다. 719개(86.31%)는 만석을 한 번도 못 봤다. 학습 만석률 자체가 705/12,065=5.84%라서, 표본이 몇 건뿐이면 0회 관측이 흔하다.

위치와 시간은 버리기 아까운 신호다. 아무것도 안 본 기준선 AUC는 .5000, 앞차 한 대만 본 기준선은 .7187, 정류장·30분 셀 기준선은 .9613이었다. 문제는 셀을 쓰느냐가 아니다. 얇은 셀을 얼마나 믿느냐다.

무축소 셀 비율은 만석 0건인 셀에 확률 0을 냈다. 검증 log loss는 .1318이었다. 노선 평균에 해당하는 의사표본 1개를 섞자 .1033으로 줄었다. 이 진단 때문에 축소추정이 본 후보로 올라왔다.

비유하면 학생 한 명만 시험을 본 반의 평균을 그 한 점수로 확정하지 않는 것과 같다. 학생이 적은 반은 학교 평균을 조금 섞는다. 학생이 많아지면 그 반의 점수를 그대로 믿는다.

평균을 두 번 거쳐 셀로 간다
전체 train 12,065건·만석 705건
Jeffreys 보정
전역 만석률 5.847%
의사표본 4개
1650 6.880% / 3330 5.263%
선택 α=.5
정류장×30분 셀
만석확률을 탈 확률로 변환
p_full → 1-p_full

전역 평균으로 노선을 안정시키고, 노선 평균으로 정류장×30분 셀을 안정시킨다.

Q. 어디로, 얼마나 당기나?

Q. 한 칸은 무엇인가?

한 셀은 노선×station_id×로컬 30분대다. 셀 안에서 출발 후 잔여석이 0인 사건 수 m과 전체 사건 수 n을 센다. 도착 시점 0석은 쓰지 않는다. 하차 뒤 자리가 생길 수 있어서다. remainSeatCnt=-1도 결측이라 뺀다.

Q. 당김의 기준은 무엇인가?

먼저 전체 학습분에서 전역 만석률을 구한다. 만석과 비만석에 .5건씩 더하는 Jeffreys 보정을 쓴다. 노선 만석률은 전역 만석률 쪽으로 의사표본 4개만큼 당긴다. 마지막으로 각 셀을 그 노선 만석률 쪽으로 당긴다.

셀 예측식은 하나다.

p_full = (m + α × p_route) / (n + α)

α는 노선 평균이 몇 건의 표본처럼 작용하는지 정한다. 실제 후보는 .5, 1, 2, 4, 8, 16, 32, 64를 날짜 순방향 교차검증으로 겨뤘다. 선택값은 .5였다. 노선 평균을 반 건만 섞는 약한 축소다.

Q. 왜 ‘경험적’ 베이즈인가?

사전평균 p_route를 사람이 정하지 않고 같은 학습 데이터의 노선·전역 빈도에서 구하기 때문이다. beta-binomial 방식으로 노선 평균을 의사표본처럼 보고 셀의 만석/비만석 횟수와 합친다. 사후분포 전체가 아니라 사후평균 하나만 내보낸다.

Q. 처음 보는 셀은 어떻게 하나?

정확한 셀이 없으면 노선×정류장 → 노선×30분대 → 노선 → 전역 순서로 내려간다. 이미 본 셀은 표본이 1건이어도 이 폴백을 쓰지 않는다. 그 셀의 비율과 노선 평균만 섞는다.

출력은 만석 확률 p_full이다. 사용자에게 보이는 탈 확률은 별도 모델이 아니라 1-p_full이다.

얇은 셀만 눈에 띄게 움직인다
셀무축소축소 후
태영아파트 0/50%0.625%
롯데백화점.범계역 14/2360.87%59.69%

같은 α=.5라도 표본 수가 다르면 당기는 폭이 달라진다.

Q. 실제 숫자는 어떻게 바뀌나?

1650번 태영아파트(station_id 209000243), 18:00~18:30 셀을 보자. 전부 학습 데이터에서 계산한 값이다.

  1. 전체 학습분은 12,065건, 만석 705건이다. Jeffreys 보정을 거친 전역 만석률은 5.847%다.
  2. 학습분의 1650번은 4,331건 중 298건이 만석이다. 전역 평균을 의사표본 4개만큼 섞은 노선 만석률은 6.880%다.
  3. 이 셀은 5건 중 만석 0건이다. 무축소 값은 0%다.
  4. 선택된 α=.5를 넣으면 (0 + .5×.068797) / (5+.5) = .006254다. 만석 확률 0.625%, 탈 확률 99.375%다.

검증 라벨은 이 계산에 넣지 않았다. 뒤 검증에서는 같은 셀 4건 중 1건이 만석이었다. 한 셀의 4건으로 모델 전체를 판정할 수는 없다. 다만 학습의 0/5가 위험 0이라는 뜻은 아니었다.

표본이 두꺼우면 덜 움직인다. 3330번 롯데백화점.범계역 07:00~07:30 셀은 학습 23건 중 14건이 만석이었다. 무축소 60.87%가 축소 뒤 59.69%가 됐다.

재료 한눈에

쓰는 재료는 네 가지다. 출처 필드까지 아래 표가 정본이다.

쓰는 재료 4개 — 출처 필드까지

재료종류어느 API의 어느 필드
노선 (route)직접 수집은 calls.jsonl.route_name, 코퍼스는 route.name을 모델 범주로 읽고 같은 route.routeName 마스터 행을 찾는다. 수집기 설정의 route.route_id와 원응답 routeId는 원문에 남는다.주의 — 현재 S1 구현은 실제로 routeName으로 마스터를 찾는다. msgBody.busLocationList[].routeId를 모델의 route로 복사하지 않는다. 대상 두 노선 밖으로 넓힐 때는 ID 검증이 필요하다.응답 원본msgBody.busLocationList[].routeId; 운영 수집기 route.name, route.route_id; S1 E4 calls.jsonl.route_name; 코퍼스 route.name; route.routeName, route.routeId; S1 routeGBIS 버스위치정보 getBusLocationListv2 + 우리 수집기 노선 메타데이터 + 제한 코퍼스 + GBIS route 마스터
목표 정류장 ID (station_id)차량별 정규화 위치가 전진한 끝점의 station_seq를 만들고, 같은 노선의 staOrder와 맞춰 stationId를 붙인다.주의 — 응답의 msgBody.busLocationList[].stationId를 목표 통과 정류장 ID로 복사하지 않는다. 그 값은 응답 시점 차량 위치의 정류장이다.파생msgBody.busLocationList[].vehId, msgBody.busLocationList[].stationSeq, msgBody.busLocationList[].stateCd; routestation.routeName, routestation.staOrder, routestation.stationId; S1 station_idGBIS 버스위치정보 getBusLocationListv2 + GBIS routestation 마스터 + S1 통과 사건 빌더
KST 30분대 (query_half_hour)응답 수신시각을 KST로 바꾸고 hour*2 + 1[minute>=30]으로 0~47을 만든다.주의 — msgHeader.queryTime과 HTTP Date는 시간 계산에 쓰지 않는다. 코퍼스 collectedAt은 본문 파싱 뒤 시각이다.파생timing.response_received_at.kst, timing.response_received_at.utc; S1 E4 response_received_kst, response_received_utc; 코퍼스 collectedAt; S1 query_half_hour우리 수집기 응답 수신시각; 제한 코퍼스는 수집기가 붙인 collectedAt
출발 후 만석 라벨 (label_full)정류장 s 통과 뒤 같은 차량에서 (stateCd,stationSeq)=(2,s),(0,s),(1,s+1) 중 처음 잡힌 유효 좌석값을 찾는다. 0이면 1, 양수면 0이다.주의 — remainSeatCnt=-1은 결측이다. (stateCd,stationSeq)=(1,s)는 도착 상태라 라벨이 아니다. 예측 시점 뒤에 생기므로 학습 정답으로만 쓴다.파생msgBody.busLocationList[].vehId, msgBody.busLocationList[].stationSeq, msgBody.busLocationList[].stateCd, msgBody.busLocationList[].remainSeatCnt; timing.response_received_at.kst, timing.response_received_at.utc; S1 passage_events.label_full, label_remain_seatsGBIS 버스위치정보 getBusLocationListv2 + 우리 수집기 응답 수신시각 + S1 통과 사건 빌더

지금은 안 쓰는 재료 5개

정원·차종은 검증해서 버린 재료가 아니다

M3는 직접 수집분만 쓰고 공식 이력·제원으로 정원·차종 ablation을 실행했다. 직접 관측 고유차량 55/62대에 공식 이력이 연결됐다. 공유 페이지에는 차량번호와 비공개 조인 식별자 값을 싣지 않는다.

새 지표에서 명백한 개선으로 판정한 조합은 0개다. 표본 관문 미달이라 쓸모없다는 뜻은 아니다. 관측 최대 잔여석으로 정원을 추정한 행은 0건이며 계속 금지한다.

Q. 보정은 실제로 적용됐나?

이 모델 자체에는 보정층을 얹지 않는다. 축소로 만든 확률을 그대로 낸다. 확률 보정은 별도 후보 숫자 다듬기 · Platt 확률 보정이 맡는다. 보정 눈금이 뒤 날짜로 옮겨가지 않았던 실측은 아래 ‘언제 실패하나’에 있다.

Q. 언제 실패하나?

관측이 적은 구간은 공통 평균 쪽으로 더 많이 당겨진다. 그 구간의 현장 차이가 작다는 증거는 아니다. 관측이 많은 구간은 자체 비율이 더 반영되지만, 그 자체가 뒤 날짜 검증을 통과했다는 뜻은 아니다.

그 밖의 약점도 남는다.

Q. 축소했는데 왜 보정은 나빠졌나?

S1 층화 기준선은 의사표본 1개를 섞었다. 경험적 베이즈가 고른 α=.5는 그보다 약한 축소다. 날짜 순방향 2-fold에서 ECE·Brier·log loss의 합이 .188043으로, α=1의 .188211보다 아주 조금 낮아 선택됐다. ECE만 고른 결과가 아니다.

ECE·Brier·log loss는 낮을수록 좋고 AUC는 높을수록 좋다.

모델ECEBrierlog lossAUC
층화 기준선.0063.0327.1033.9613
경험적 베이즈 raw.0070.0327.1024.9613

log loss는 .0009 좋아졌지만 ECE는 .0007 나빠졌다. 0% 같은 극단값을 피한 이득과 전체 확률 눈금의 작은 편향이 서로 다른 지표에 잡혔다.

후처리는 더 분명히 실패했다. OOF는 각 날짜를 그보다 앞선 날짜로만 예측해 만든 값이다. 학습 OOF 10,236건·만석 572건에서는 ECE가 raw .0128에서 Platt .0064, isotonic .0016으로 좋아졌다. 하지만 뒤 검증 10,040건·만석 583건에서는 raw .0070이 Platt .0134, isotonic .0131로 나빠졌다. 평균 예측도 raw 5.4829%에서 4.4684%·4.4963%로 내려가 관측 5.8068%를 크게 밑돌았다. 앞 구간에서 배운 눈금이 뒤 날짜로 옮겨가지 않은 것이다. 날짜별 분포 이동, 보정 표본 구성, isotonic의 60개 계단이 각각 얼마나 영향을 줬는지 분리한 실측은 아직 없다.

보정층이 뒤 검증에서 위험도를 너무 낮췄다
변형ECE평균 예측관측 만석률
EB raw.00705.4829%5.8068%
EB Platt.01344.4684%5.8068%
EB isotonic.01314.4963%5.8068%

raw보다 Platt·isotonic의 평균 예측이 관측 만석률에서 더 멀어졌다.

Q. 프로토타입과 무엇이 다른가?

Q. 개인정보와 미래 정답은 어떻게 막나?

관문 기준·구간 정의·지표 정의·학습/평가 분할·라벨 규칙·검열 처리 규칙은 평가 규약에 있다.

M3 연구 이력 — 2026-08-15 동결

동결된 연구 기록이다. 위 오늘 성적과 합치거나 변화율로 읽지 않는다. 당시 문장의 ‘최신’·‘권위값’은 현재 공개 평가를 뜻하지 않는다.

Brier0.0096ECCE-MAD0.0326log loss0.04561:1 결정비용0.00422:1 결정비용0.02104:1 결정비용0.0679
M3 권위값

직접 API 응답 582개를 고정해 train 604행·만석 28건, validation 1,901행·만석 8건·날짜 1일로 나눴다.

모델 7개를 paired bootstrap 5,000회와 Holm 21쌍으로 비교했다. 결정은 no_winner, 승자 없음이다. 최소 관문은 validation 날짜 10일·만석 100건이다.

validation 양성 20건 미만이면 만석 누락률·PR-AUC·ROC-AUC 수치를 억제한다. 아래 M1·M2 수치는 역사 기록이며 최신 결론과 섞지 않는다.

M3 직접 수집분 성적

68/32 이동 분할이 아니라 M2 마지막 응답 뒤의 고정 미래구간을 썼다. 검증 1,901행·만석 8건· 하루·정류소×날짜 129군집, paired_station_id_x_query_date_cluster_bootstrap 5,000회다.

A · 평균으로 당기기 · raw

운영 후보 · M3 고정 미래구간 기술값 · 낮을수록 좋음

지표값 (95% 구간)
Brier · 얼마나 빗나갔나0.0096[0.0046, 0.0157]
ECCE-MAD · 확률 오차가 쌓이나0.0326[0.0204, 0.0469]
log loss · 확신하고 틀린 벌점0.0456[0.0272, 0.0664]
만석 누락 @ .5 · 만석을 안심으로 놓쳤나만석 20건 미만 · 수치 억제
1:1 결정비용 @ .500.0042[0.0000, 0.0099]
2:1 결정비용 @ .330.0210[0.0021, 0.0481]
4:1 결정비용 @ .200.0679[0.0246, 0.1203]
승자는 없다

동결 당시 표본은 validation 날짜 1/10일 (미달), 만석 8/100건 (미달)이다. 만석 민감 지표는 양성 20건부터 숫자를 내며 동결 시점에는 수치 억제였다. 관문은 검토 최소선이지 충분조건이 아니다.

모델별 보정 관문은 미달 — 적격 적용 0/3개 · raw fallback 5,703행이다. 비억제 모델쌍×지표 bootstrap 유효비율 최소값은 100.0%(기준 90%), 운영 후보 비용 방향 뒤집힘은 0/15쌍이다. 마지막 세 날짜 누적 Brier도 승자 전에 확인한다.

하루 조건부 기술 구간과 Holm 계산상 0을 벗어난 Brier 쌍은 10/21쌍이지만 날짜 일반화나 우열 판정이 아니다. 최종 판정은 0/21쌍이다. 만석 8건이면 누락률이 한 사건당 12.5%p 움직인다. PR-AUC·ROC-AUC도 만석 20건 미만이면 억제하며 순위에 쓰지 않는다.

1–4일은 관측 날짜 안 조건부 기술값, 5–9일은 진단 기술값이다. 검증 10일부터도 모든 관문을 통과해야 추론과 승자 선언을 검토한다. 경로·수집구간·날짜·라벨 규칙·관측간격 다섯 축은 한 축씩 기록하고 90초 초과는 검열한다. ECCE 동률은 독립 동결 nonce의 SHA-256 순서로 재현하고 전 행 누적곡선을 남긴다. 이번 재실행은 registry 후보 3,054건 중 기존 nonce 3,054건을 재사용했고 신규는 0건이다.

직접 수집분 재대결(M2)은 21쌍 중 16쌍을 못 가려 승자를 정하지 않았고 채택·탈락도 없었다. 코퍼스 ECE·AUC 표와 초기 직접 수집분 수치, 68/32 이동 분할은 M1·M2 당시 기록이며 최신 결론이 아니다.

아래는 이전 공개 평가의 기록이다. 현재 점추정과 합치지 않는다.

이전 공개 평가

평가평가 규격행Brier
eval-20260815-7e03dc730de91f34evaluation-v12,8940.009100
출처와 검증 장부
동결 이력 · 마지막 보고서daily-20260816-86afbfc70dbb876b · 2026-08-16분 · 생성 08-17 00:15 KST
모델 버전empirical-bayes-v1+fd482d90
이력 평가 규격evaluation-v2 · 구간 규격 cohort-v1 · 점수 규격 composite-score-v1 · v2 현재값이 아님
이력 · 공개 평가eval-20260815-f0f59cf25a9c3503 · 자료판 current-7cf2243ffe6c4cdc · 모델 버전 empirical-bayes-v1+cca34cdb · 이전 평가 eval-20260815-7e03dc730de91f34(evaluation-v1)
이력 검증 해시규약 43913ebf483a48a02f6a83e01181a01ccf8bc10a728a38b9e838031ac9dbeec5
구현 cca34cdb16f663754e630e9f41abd26b6b441a19dd5002291f18af63f9a21a9a
평가 d133e3d6c2db757c5fa780d5ffb19e6998b2dcefc049b844a8faebd64e14a817