후보 모델 7개

일곱 갈래로 만들어 겨루는 중이다. 아직 고르지 않았다. 아래는 무엇을 계산하는지어디까지 검증됐는지만 적었다. 원리와 재료는 각 모델 페이지에 있다.

모든 모델이 공통으로 답하는 것 — 기능 정의

지금 이 정류장으로 오고 있는 그 버스가, 이 정류장을 출발할 때 자리가 하나도 안 남아 있을 확률.

p_full = P(출발 후 잔여석 = 0)  ·  화면에 나가는 값 p_board = 1 − p_full

일곱 모델은 전부 이 하나를 서로 다른 방법으로 계산한다. 아래 정의가 어긋나면 모델이 아니라 정의를 고친다.

1. 대상 — 무엇 하나에 대한 확률인가

조회 한 번이 만드는 판정은 정확히 하나다.

판정 단위(노선, 정류장, 그 정류장에 다음으로 올 차량) 하나
"다음 버스"의 정의목표 정류장을 아직 지나지 않은 차량 중 축거리가 가장 가까운 하나. last_passed < station_seq인 차량들 중 station_seq − last_passed 최소
동률이면덜 진행한 쪽을 고른다 — 출발 < 교차로 < 도착. 그래도 같으면 나중 여정, 그래도 같으면 차량 ID 사전순
다음 버스가 없으면판정하지 않는다. upstream_bus_exists = 0으로 남긴다
대상 노선경기 광역버스 1650 · 3330 두 개. 상·하행이 한 축이고 회차 순번으로 방면을 가른다
거리 세는 법내부 계산은 축 순번, 화면 표시는 정차 정류장만 센다. 둘을 섞지 않는다

2. 사건 — 무엇이 일어나면 "만석"인가

라벨은 예측이 맞았는지 채점하는 정답이다. 이 정의가 전부의 기준이 된다.

만석 (1)그 차량이 목표 정류장을 출발한 직후 관측한 잔여석이 0
여유 (0)같은 자리에서 잔여석이 양수
제외잔여석 -1은 좌석 정보 미제공이다. 0으로 바꾸지 않는다 — 바꾸면 가짜 만석이 생긴다
인정하는 관측 세 가지정류소 출발(stateCd=2, 순번 = S) · 교차로 통과(stateCd=0, 순번 = S) · 다음 정류소 도착(stateCd=1, 순번 = S+1). 이 셋이 아니면 라벨로 쓰지 않는다
왜 도착이 아니라 출발인가도착 시점 0은 만차가 아니다. 하차하면 자리가 생긴다. 실측으로도 도착 시점 만석 3.02%(23/762) 대 출발 이후 11.95%(399/3,339)로 네 배 차이가 난다 직접 수집 176호출. 도착 시점으로 재면 "거의 항상 탈 수 있다"고 잘못 알려주게 된다
입석은법으로 금지다. 그래서 잔여석 0 = 못 탐이 성립한다. 타는 것과 앉는 것이 같은 말이다

3. "나" — 누구 기준의 확률인가

여기가 가장 헷갈리는 자리다. 확률에는 사람이 하나 전제돼 있다.

"나"의 정의그 정류장에 새로 도착해 줄 맨 뒤에 서는 한 사람
왜 맨 뒤인가자리 C, 원래 대기 D, 출발 후 잔여석 R = max(C−D, 0)이다. R ≥ 1이면 나는 어디 서든 탄다. R = 0이면 맨 뒤에 선 나는 확실히 못 탄다. 이 둘이 합쳐져 P(못 탐) = P(R = 0)이 정확히 성립한다
이미 줄에 서 있던 사람은우리 값이 실제보다 비관적이다. R = 0이어도 앞쪽에 섰다면 탔을 수 있다. 예보로서는 안전한 쪽으로 틀린다
대기 인원은 어디에이미 R에 흡수돼 있다. 그날 사람이 많았으면 R이 작게 나온다. 따로 대기자 수를 몰라도 되는 이유다
깨지는 경우예보를 본 여러 명이 동시에 같은 정류장으로 몰릴 때. 그때는 각자가 "맨 뒤 한 명"이 아니게 된다

4. 상황 — 언제 예측하고 그때 무엇을 아는가

라벨을 재는 시점과 예측하는 시점은 다르다.

예측 시점사용자가 조회하는 그 순간. 버스는 아직 정류장 상류에 있다
라벨 재는 시점그 버스가 정류장을 출발한 뒤. 학습할 때 정답을 확인하는 자리일 뿐이다
그때 아는 것그 버스의 현재 잔여석·위치·상태, 앞차가 그 정류장을 어떻게 지났는지, 그 정류장 × 시간대의 과거 위험, 계획 배차간격
모르는 것지금 그 정류장에 몇 명이 서 있는지, 몇 명이 내릴지
시각 축우리 응답 수신 시각 하나뿐이다. 서버가 준 queryTime은 우리 수신 시각보다 항상 미래이고 되감김·점프가 있어 계산에 쓰지 않는다
모델마다 다른 점일곱 중 셋(못 본 것도 세기 · 재료 다 넣기 · 한계 재보기)은 그 버스의 현재 잔여석을 실제로 본다. 나머지 넷은 정류장 × 시간대 평균만 쓴다

5. 이것이 아니다

헷갈리기 쉬운 것들을 명시적으로 빼둔다.

  • 정원 대비 점유율이 아니다45석 차의 0석과 71석 2층버스의 0석은 라벨상 똑같이 만석이다. 라벨 식에 정원이 안 들어간다
  • 혼잡도 코드가 아니다crowded는 별도 필드이고 지금은 재료 후보일 뿐 정답이 아니다
  • 도착 시점 상태가 아니다승하차가 끝난 뒤를 잰다. 접근 중 만차여도 하차하면 탈 수 있다
  • 내 줄 순번을 반영하지 않는다맨 뒤 한 명 기준이다. 앞에 몇 번째인지는 모른다
  • 버스가 언제 오는지가 아니다도착 예정 시각은 별개 값이고 이 확률에 안 들어간다
  • "아무도 못 탔다"가 아니다만석이어도 그 정류장에서 여러 명이 탔을 수 있다. 한 명이 못 탄다는 뜻이다

6. 아직 못 보는 것

정직하게 적어둔다. 여기가 다음 기능이 들어올 자리다.

  • 잔여석 0 안쪽은 검열돼 있다. 자리가 딱 맞아떨어져 0이 된 경우와 40명이 못 탄 경우가 라벨상 똑같다. 초과 수요의 크기를 모른다 — 대기자 수 기능이 메울 자리다
  • 하차 인원은 API에 없다. 우리가 보는 건 승하차가 끝난 뒤의 순 잔여석 하나뿐이다. 하차가 많은 정류장의 특성은 정류장 효과로 간접 흡수한다
  • 2분 간격으로는 정류장을 놓친다. 실측 23.2%가 두 정류장 이상 건너뛰었다. 그래서 통과를 시점이 아닌 구간 검열 사건으로 다루고, 출퇴근 수집을 1분으로 좁혔다
  • 표본이 아직 얇다. 직접 수집 검증분은 만석 수십 건 수준이다. 지금 순위는 남의 20일 코퍼스로 낸 잠정값이다

지금 어디까지 왔나

설계구현 기준선 비교보정 비교 잠정 순위 여기 · 직접 수집 재대결 1회차채택 확정

직접 수집분만으로 한 번 돌렸고, 순위는 못 가렸다. 라벨 1,524건·만석 54건, 검증분 443건·만석 14건으로 일곱을 겨뤘더니 AUC 21쌍 중 16쌍이 구분되지 않았다. 승자를 선언하지 않았다. 다만 코퍼스로 낸 순위가 뒤집힌 쌍도 0개다. 방향은 틀리지 않았고 미세한 차이만 미지다.
가리려면 표본이 더 필요하다 — ΔAUC 0.05 문턱이 8 수집일, 날짜 변동까지 보려면 15일이 더 든다. 출퇴근 수집을 1분으로 좁혀 라벨 생산 속도를 올렸다.

지금 앞서는 것 — 구간 검열 + 보정

잠정이다. 아래 수치는 남의 20일 코퍼스로 낸 것이고, 기준선(정류장·시간만) 대비다.

만석인데 "탈 수 있다"고 답한 비율 .60 → .37승객이 버스를 놓치는 오판이 40% 줄었다. 실용적으로 가장 중요한 숫자
만석을 골라내나.9613 → .9751+.0138 [+.0103, +.0179]
얼마나 빗나갔나.0327 → .0268−.0059 [−.0075, −.0042]
확률이 정직한가.0063 → .0053−.0010 — 이 차이는 유의하지 않다

솔직하게 1순위 지표(확률의 정직함)에서는 기준선을 확실히 이기지 못했다. 그런데도 앞에 둔 건 나머지 세 지표가 모두 유의하게 좋아졌기 때문이다.
2등인 재료 다 넣기는 빗나감·벌점·안전성이 오히려 더 좋다. 그런데 뒤로 뒀다 — 확률 70~80% 구간에서 평균 .727이라 말한 상황이 실제로는 .870이었다(n=177). 가장 조심해야 할 구간에서 사용자를 안심시키는 셈이다.
직접 수집분으로 다시 돌리니 이 순위를 재현도 반박도 못 했다. 21쌍 중 16쌍이 구분되지 않았다. 뒤집힌 쌍은 0개다.

넘어야 할 선

기준선 셋을 먼저 세웠다. 검증 10,040건 · 만석 583건 · 부트스트랩은 정류장×날짜 644군집. 보정도(ECE)가 1순위 지표다 — 이 확률을 사용자에게 숫자로 그대로 보여주기 때문이다.

방법확률이 정직한가
ECE · 낮을수록 좋음
얼마나 빗나갔나
Brier · 낮을수록
확신하고 틀리면 벌점
log loss · 낮을수록
만석을 골라내나
AUC · 높을수록
아무것도 안 보고 평균만 말하기0.00040.05470.22160.5
앞차 한 대만 보고 말하기0.00210.04520.17930.7187
어느 정류장·몇 시인지만 보고 말하기0.00630.03270.10330.9613

정류장 × 시간대가 앞차 상태만 보는 것보다 훨씬 강했다(AUC .72 → .96). 어느 정류장에서 몇 시에 기다리느냐가 앞차가 만석이었는지보다 중요하다는 뜻이다. 후보들은 전부 이 선을 넘어야 한다.

먼저 읽으면 좋다 — 무슨 재료를 어떻게 쓰나 프로토타입은 과거 통계와 실시간 좌석을 함께 써서 "이 버스"를 추적했다. 새 후보는 "이 상황"을 본다. 절반은 실시간 좌석을 아예 안 쓴다. 그 차이를 한 장에 정리했다 →

이름표

통계 용어 그대로는 대화가 안 된다. 각 모델이 실제로 하는 일로 부르기로 했다. 괄호는 원래 이름.

점수 읽는 법

숫자 네 개가 각각 다른 걸 잰다. 하나만 좋아도 소용없다.

확률이 정직한가ECE

"70%"라고 말한 상황들에서 실제로 70%쯤 만석이었나. 어긋나면 값이 커진다. 이게 1순위다 — 이 확률을 사용자에게 숫자로 그대로 보여주기 때문이다. 90%라고 해놓고 절반만 맞으면 앱을 못 믿는다.

얼마나 빗나갔나Brier

예측한 확률과 실제(만석 1 / 아님 0)의 차이를 제곱해 평균낸 값. 전반적으로 얼마나 틀렸는지.

확신하고 틀린 벌점log loss

"99% 안전"이라 했는데 만석이면 크게 깎는다. 어정쩡하게 틀린 것보다 자신 있게 틀린 걸 더 나쁘게 본다.

만석을 골라내나AUC

만석인 경우와 아닌 경우를 아무거나 하나씩 뽑았을 때, 만석 쪽에 더 높은 확률을 준 비율. 0.5는 동전 던지기, 1.0은 완벽. 순서를 잘 매기는지만 보고 숫자 자체의 정직함은 안 본다.

기존 프로토타입과 다른 점

한 가지 짚고 갈 것 지금 성적은 전부 레스의 20일 코퍼스로 낸 것이다. 그 데이터는 차량 ID가 가명이라 정원·차종을 붙일 수 없었고, 그래서 정원을 쓰는 방식은 아직 테스트해 본 적이 없다. "쓸모없어서 뺀 것"이 아니라 "붙일 수가 없었던 것"이다. 우리가 직접 모으는 데이터는 원본 차량 ID를 남기므로 정원이 붙는다(40/41, 97.6%). 표본이 쌓이면 다시 겨룬다.

후보

초록 칸은 정류장×시간대 기준선보다 좋은 점수다. "보정"은 isotonic 후처리를 얹은 값.

01

못 본 것도 세기보정 적용

구간 검열 반영

못 본 통과를 지우지 않고 계산에 남긴다.

확률이 정직한가0.0053
얼마나 빗나갔나0.0268
확신하고 틀린 벌점0.0878
만석을 골라내나0.9751
미착수설계됨구현됨기준선 비교됨보정 비교됨직접수집 검증됨채택/탈락
원리·재료·성적 자세히 →
02

재료 다 넣기보정 적용

로지스틱 + 상호작용

관측 특징의 조합을 직접 점수화한다.

확률이 정직한가0.0065
얼마나 빗나갔나0.0231
확신하고 틀린 벌점0.0787
만석을 골라내나0.9775
미착수설계됨구현됨기준선 비교됨보정 비교됨직접수집 검증됨채택/탈락
원리·재료·성적 자세히 →
03

이웃에게 빌리기보정 없이

GAM / 스플라인

가까운 정류장과 시간을 매끈하게 잇는다.

확률이 정직한가0.0038
얼마나 빗나갔나0.0328
확신하고 틀린 벌점0.1034
만석을 골라내나0.9647
미착수설계됨구현됨기준선 비교됨보정 비교됨직접수집 검증됨채택/탈락
원리·재료·성적 자세히 →
04

평균으로 당기기보정 없이

경험적 베이즈 축소추정

얇은 셀을 노선 평균 쪽으로 당긴다.

확률이 정직한가0.007
얼마나 빗나갔나0.0327
확신하고 틀린 벌점0.1024
만석을 골라내나0.9613
미착수설계됨구현됨기준선 비교됨보정 비교됨직접수집 검증됨채택/탈락
원리·재료·성적 자세히 →
05

본사와 지점보정 적용

계층 로지스틱 (부분 풀링)

셀 효과를 나눠 쓰며 부분 풀링한다.

확률이 정직한가0.009
얼마나 빗나갔나0.0341
확신하고 틀린 벌점0.1079
만석을 골라내나0.9628
미착수설계됨구현됨기준선 비교됨보정 비교됨직접수집 검증됨채택/탈락
원리·재료·성적 자세히 →
06

보정 후처리모델이 아니라 얹는 층

모델 위에 확률 보정층을 얹는다.

미착수설계됨구현됨기준선 비교됨보정 비교됨직접수집 검증됨채택/탈락
원리·재료·성적 자세히 →
07

한계 재보기상한 참조 · 운영 후보 아님보정 적용

Gradient boosting

복잡한 모델이 낼 수 있는 상한만 잰다.

확률이 정직한가0.0053
얼마나 빗나갔나0.0155
확신하고 틀린 벌점0.0524
만석을 골라내나0.991
미착수설계됨구현됨기준선 비교됨보정 비교됨직접수집 검증됨채택/탈락
원리·재료·성적 자세히 →