후보 모델
못 본 것도 세기
구간 검열 반영
못 본 통과를 가짜 정답으로 채우지 않는다. 양끝 상태 사이의 가능한 경로를 모두 우도에 남긴다.
Q. 사진 사이에서 사라진 통과는 버려야 하나?
아니다. 폴링은 버스를 계속 보는 영상이 아니라 띄엄띄엄 찍는 사진이다. 앞 사진에서 순번 20이던 버스가 다음 사진에서 순번 23이면, 21과 22의 출발 후 좌석 상태는 보이지 않는다. 그렇다고 두 통과가 없었던 일은 아니다.
재구축 자료의 검열행은 2,779건이다. 이 가운데 정상 순번 도약에서 생긴 미관측 중간 통과가 2,090건이다. 물리적으로 불가능한 이동 689건은 PX로 빼고 라벨 우도에 넣지 않았다. 시간 경계, 정차 정류장, 90초 연속성까지 통과해 코퍼스 train 우도에 들어간 것은 양끝 상태쌍 800개다. 그 안에서 중간 통과 821개를 잠재 상태로 합산했다. 점 라벨을 새로 만든 건 0건이다.
이 재료가 필요한 배경은 셀의 얇음이다. 노선×정류장×30분 셀은 833개다. 표본 10건 이하가 281개, 33.73%다. 만석을 한 번도 못 본 셀은 719개, 86.31%다. 셀 빈도만 믿으면 “못 봤다”를 “없다”로 읽기 쉽다. 구간 검열 모형은 셀 위험을 축소한 뒤, 폴링 사이 전이가 남긴 정보를 따로 보탠다.
코퍼스 보조 검증에서는 잠정 운영 선두다. 검증 표본은 10,040건, 만석은 583건이다.
| 모형 | ECE | Brier | log loss | AUC |
|---|---|---|---|---|
| 정류장×시간 기준선 | .0063 | .0327 | .1033 | .9613 |
| 구간 검열 raw | .0200 | .0284 | .0968 | .9748 |
| 구간 검열 isotonic | .0053 | .0268 | .0878 | .9751 |
전이 정보만 섞은 raw는 순위를 잘 세웠지만 확률 눈금은 틀어졌다. 시간순 OOF로 학습한 isotonic 보정이 그 눈금을 다시 맞췄다. 기준선 대비 ECE 차이 -.0010의 95% 구간은 [-.0037, +.0040]이라 보정 개선 자체는 유의하지 않다. Brier와 log loss, AUC의 짝지은 95% 구간은 모두 0을 포함하지 않았다.
축소 셀 위험과 검열 전이 위험을 섞고, 시간순 OOF 보정 뒤 탈 확률로 뒤집는다.
Q. 양끝만 보고 가운데를 어떻게 세나?
Q. 무엇이 보이고 무엇이 안 보이나?
상태는 둘만 둔다. 출발 후 잔여석 0이면 F(만석), 양수면 A(여유)다. -1은 결측이라 어느 쪽에도 넣지 않는다.
예를 들어 F → ? → A가 관측됐다고 하자. 가운데를 F나 A로 찍지 않는다. F→F→A와 F→A→A 두 경로를 모두 남긴다. 못 본 상태가 두 개면 가능한 네 경로를 모두 더한다.
Q. 모든 경로를 직접 늘어놓나?
아니다. 두 상태의 전이표를 T라 두고 작은 우도 하나만 계산한다.
P(Y_end | Y_start, T^k)
k는 양끝 사이의 축상 이동 칸 수다. T^k가 중간의 모든 F/A 경로를 한 번에 합친다. 가짜 행도, 가짜 통과시각도 생기지 않는다.
전이표는 노선, 오전·오후, 정류장 순번 10칸 묶음으로 나눈 29개 그룹에서 배운다. 각 그룹에는 A→F와 F→A 두 확률이 있다. 그룹 표본이 얇으면 전역 전이 쪽으로 당긴다. 선택된 전이 규제값은 5다.
Q. 전이 확률만으로 답하나?
아니다. 첫 갈래는 노선×정류장×30분 셀 위험이다. 만석 수와 표본 수를 세고, 의사표본 강도 4로 노선 평균 쪽에 축소한다. 둘째 갈래는 가장 가까운 상류 관측 버스의 0석/양수, 목표까지의 내부 축거리, 위 전이표로 계산한 위험이다.
두 갈래는 확률 자체가 아니라 log-odds에서 90:10으로 섞는다. 상류 버스나 축거리가 없으면 셀 위험만 쓴다. 마지막에는 train 안의 날짜 순방향 OOF 10,236건, 만석 572건으로 배운 isotonic 계단을 통과한다. validation 라벨은 이 과정에 들어가지 않았다.
관측은 F와 A 두 끝뿐이다. 가운데 상태를 하나로 찍지 않는다.
Q. 실제 한 행은 어떻게 계산되나?
2026년 8월 3일 07:12:25 KST, 1650번 부흥고등학교.임광아파트 정류장이다. 정류장 ID는 209000147, 내부 순번은 54다. 가장 가까운 상류 관측 버스는 축상 2칸 앞에 있었고 잔여석은 0이었다. 실제 출발 후 라벨도 만석이었다. 아래 값은 소수 넷째 자리로 반올림했다.
| 단계 | 실측값과 계산 | 만석 확률 |
|---|---|---|
| 셀 위험 | train 14건 중 만석 7건. 1650 노선 사전확률 .0688을 의사표본 4개로 섞음: (7 + 4×.0688) / 18 | .4042 |
| 전이 위험 | 1650·오전·순번 51~60 그룹의 A→F=.0033, F→A=.0376. 만석에서 2칸 뒤 만석은 .9624×.9624 + .0376×.0033 | .9263 |
| raw 혼합 | 셀 .4042와 전이 .9263의 log-odds를 90:10으로 혼합 | .4760 |
| isotonic 보정 | 과거 OOF에서 배운 단조 계단 적용 | .5976 |
| 사용자용 변환 | 탈 확률 = 1 - 만석 확률 | .4024 |
전이 갈래만 보면 만석 지속 위험이 높다. 셀 갈래는 그보다 낮다. 10%만 섞었는데도 raw가 .4042에서 .4760으로 올랐다. 보정기는 이 raw 구간이 과거에 실제 만석으로 더 자주 이어졌다고 보고 .5976으로 올렸다.
Q. 무엇을 쓰고 무엇을 버리나?
| 쓰는 재료 | 쓰는 이유 |
|---|---|
| 노선, 정류장 ID, 내부 순번, 로컬 시각 | 축소 셀과 전이 그룹을 만든다. 시각은 응답 수신 KST만 쓴다. |
출발 후 0/양수 라벨 | F/A 양끝 상태와 최종 정답을 만든다. 내 정류장 도착값은 쓰지 않는다. |
| 정상 순번 도약의 양끝, 못 본 통과 수 | T^k 우도에 넣는다. 중간 상태는 복원하지 않는다. |
| 가장 가까운 상류 관측 버스의 잔여석과 내부 축거리 | 예측 시점의 시작 상태와 전이 횟수를 정한다. 차량 식별자는 모델 입력이 아니다. |
| 날짜 순방향 OOF 예측 10,236건 | isotonic 보정층의 눈금을 잡는다. |
| 안 쓰는 재료 | 이유 |
|---|---|
| 정원·점유율 | 라벨은 출발 후 잔여석 0만으로 정해진다. 코퍼스 차량키는 정원 자료와 0/77 조인이다. 관측 최대는 정원이 아니라 하한이고 시간에 따라 바뀐다. |
crowded | 대상은 노선유형 11인데 공식 제공 유형은 13·15·23이다. 180초 이하 인접 81,147쌍에서 혼잡도만 바뀐 쌍은 0건이었다. 직접 수집분에서 같은 잔여석에 다른 코드가 붙은 값이 26개 나와 잔여석만의 함수는 아니다. 다만 같은 차량·같은 잔여석에서는 충돌이 0셀이라 차량별 정원 임계화일 가능성이 남는다. 산식이 미확정이라 이 모형에서는 아직 쓰지 않는다. |
queryTime | 직접 수집 92호출 전부가 로컬 수신 시각보다 미래였고 중앙 +17.265초였다. 되감김은 인접 호출 전체 16건, 같은 노선 안 2건이다. HTTP Date도 초 절삭까지 92/92 일치해 독립 시계가 아니다. 경과시간 계산에 쓰지 않는다. |
잔여석 -1 | 69건 모두 결측이다. 0으로 바꾸면 가짜 만석이 생긴다. |
물리 불가능 이동 PX | 689건이다. 전이도 라벨도 만들지 않는다. |
| 단계 | 만석 확률 |
|---|---|
| 축소 셀 위험 | .4042 |
| 2칸 전이 위험 | .9263 |
| 90:10 raw 혼합 | .4760 |
| isotonic 보정 | .5976 |
| 탈 확률 | .4024 |
2026-08-03 07:12:25 KST, 1650번, 내부 순번 54의 계산이다.
Q. 언제 실패하나?
- 누락이 무작위가 아니면 틀어진다. 만석일 때만 응답이 더 자주 빠지거나 긴 폴링 공백이 혼잡 시간에 몰리면, 관측된 양끝으로 배운 전이표가 빠진 구간을 대표하지 못한다.
- 두 상태 Markov 가정이 거칠다. 현재 구현은 노선×오전·오후×순번 10칸 안에서 같은 전이표를 쓴다. 연속 만석 길이, 더 먼 과거, 회차점의 급변은 직접 넣지 않는다.
- 실제 다음 버스가 아니라
next_observed_bus다. 90초 이하 구간에서도 숨은 제3차량 하한은 3330 17.24%, 1650 12.01%였다. 빠진 차량이 있으면 시작 상태와 축거리가 어긋난다. - 새 셀과 새 노선 근거가 없다. 코퍼스 validation의 새 셀은 2/10,040행, 만석 0건뿐이다. 본 적 없는 셀의 AUC와 보정 수치: 아직 없음.
- 보정 계단도 얇은 구간에서 흔들린다.
[.1,.2)는 97건에서 평균예측 .1216, 관측률 .2577이었다.[.6,.7)는 21건에서 .6051 대 .8095였다. - 직접 수집분 표본이 아직 얇다. train 1,081건·만석 40건, validation 443건·만석 14건이고 수집 날짜가 하루뿐이다. AUC 21쌍 중 16쌍을 못 가려 승자를 정하지 않았다.
- 출력 라벨은 개인의 승차 성공과 같지 않다. 출발 후 0석은 좌석이 소진됐다는 보수적 사건이다. 하차로 생긴 자리에 일부 승객이 탄 경우까지 만석으로 센다.
Q. 프로토타입의 검열과 무엇이 다른가?
같은 “검열”이라는 말이 같은 계산을 뜻하나? 아니다.
| 프로토타입 | 구간 검열 반영 모형 |
|---|---|
좌석 변화 관측쌍의 양끝 중 하나가 0석이면 수요 숫자를 버리고 censoredWeight만 올렸다. | 폴링 사이에 못 본 중간 통과의 F/A를 잠재 상태로 두고 양끝 우도에 넣는다. |
화면의 탑승률은 정류장×시간 셀의 1-zeroCount/samples였다. 차량별 좌석 예보와 다른 계산이었다. | 출발 후 만석확률 하나를 내고, 사용자용 탈 확률은 1-p_full로만 바꾼다. |
| 좌석값을 도착 전과 처리 후 의미로 섞어 읽는 경로가 있었다. | 내 정류장 도착값은 금지한다. 출발 이후 0만 만석 라벨이다. |
| 확률 보정층이 없었다. | 날짜 순방향 OOF로 isotonic을 학습한다. validation 라벨은 보지 않는다. |
| 중간 상태 전이표가 없었다. | T^k가 가능한 중간 상태 경로를 합산한다. 점 통과시각과 가짜 행은 만들지 않는다. |
계승한 원칙도 있다. -1과 0을 가르고, 보지 못한 값을 사실처럼 만들지 않는다. 달라진 점은 못 본 사건을 경고 숫자로만 남기지 않고 학습 우도에 직접 넣었다는 데 있다.
재료 한눈에
아직 못 써본 것과 그 이유
- 정원·점유율 — 라벨은 출발 후 잔여석 0만으로 정해진다. 코퍼스 차량키는 정원 자료와 0/77 조인이다. 관측 최대는 정원이 아니라 하한이고 시간에 따라 바뀐다.
- crowded — 대상은 노선유형 11인데 공식 제공 유형은 13·15·23이다. 180초 이하 인접 81,147쌍에서 혼잡도만 바뀐 쌍은 0건이었다. 직접 수집분에서 같은 잔여석에 다른 코드가 붙은 값이 26개 나와 잔여석만의 함수는 아니다. 다만 같은 차량·같은 잔여석에서는 충돌이 0셀이라 차량별 정원 임계화일 가능성이 남는다. 산식이 미확정이라 이 모형에서는 아직 쓰지 않는다.
- queryTime — 직접 수집 92호출 전부가 로컬 수신 시각보다 미래였고 중앙 +17.265초였다. 되감김은 인접 호출 전체 16건, 같은 노선 안 2건이다. HTTP Date도 초 절삭까지 92/92 일치해 독립 시계가 아니다. 경과시간 계산에 쓰지 않는다.
- 잔여석 -1 — 69건 모두 결측이다. 0으로 바꾸면 가짜 만석이 생긴다.
- 물리 불가능 이동 PX — 689건이다. 전이도 라벨도 만들지 않는다.
아래 성적은 남의 20일 코퍼스로 낸 것이다. 그 코퍼스는 차량 ID가 가명이라 정원·차종·저상 여부를 붙일 수 없었다(조인 0/77). 이 재료들은 테스트 자체를 못 했다.
우리 직접 수집분에는 원본 차량 ID가 남아 정원이 실제로 붙는다 — 고유차량 55/62대(88.7%). 다만 1회차 재대결에서 정원·차종을 넣어도 뚜렷한 개선은 확인되지 않았다. 표본이 얇아 판정이 안 될 뿐, 쓸모없다는 뜻은 아니다. 관측 최대 잔여석으로 정원을 추정하는 것은 계속 금지다 — 원본 ID를 써도 그 값은 관측할수록 올라가서 정원이 아니다.
직접 수집분으로 다시 잰 성적 1회차
우리 수집기가 직접 쌓은 데이터만 쓰고 코퍼스는 뺐다. 검증분 443행·만석 14건, 정류소×날짜 125군집 부트스트랩 5,000회.
| 지표 | 직접 수집분 (95% 구간) | 코퍼스 |
|---|---|---|
| 확률이 정직한가 | 0.0138[0.0072, 0.0351] | 0.0053 |
| 얼마나 빗나갔나 | 0.0244[0.0117, 0.0389] | 0.0268 |
| 확신하고 틀린 벌점 | 0.0987[0.0565, 0.1469] | 0.0878 |
| 만석을 골라내나 | 0.9093[0.8462, 0.9711] | 0.9751 |
표본이 얇아 21쌍 중 16쌍이 구분되지 않았다. 검증 날짜가 하루뿐이라 날짜 간 변동도 못 본다. 21쌍 중 16쌍을 못 가리고 validation 날짜가 1개라 전체 순위를 발표하지 않는다
코퍼스 순위가 뒤집힌 쌍은 0개다. 방향은 틀리지 않았고 미세한 차이만 미지로 남았다. ΔAUC 0.05를 가리려면 8 수집일, 날짜 변동까지 보려면 15일이 더 든다.
주의 — 이번 실행에서는 보정층이 작동하지 않았다. 검증 날짜가 하루뿐이라 적격 보정 fold가 없었다. 이름에 isotonic이 붙어 있어도 위 숫자는 보정 전 예측이다. 보정 효과는 반증된 것이 아니라 아직 재지 못한 것이다.
쓰는 재료 17개 — 출처 필드까지
| 재료 | 종류 | 어느 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 통과 사건 빌더 |
상류 버스 잔여석 (upstream_remain_seats)축거리와 동률 규칙으로 고른 상류 차량의 remainSeatCnt를 붙인다.주의 — -1은 0으로 바꾸지 않고 결측으로 둔다. 이 값은 목표 차량의 미래 라벨이 아니다. | 파생 | msgBody.busLocationList[].remainSeatCnt, msgBody.busLocationList[].stationSeq, msgBody.busLocationList[].stateCd, msgBody.busLocationList[].vehId; S1 upstream_remain_seatsGBIS 버스위치정보 getBusLocationListv2 + S1 최근접 상류차 선택 |
상류 버스 존재 (upstream_bus_exists)정규화 마지막 통과 순번이 목표 station_seq보다 작은 차량이 하나라도 있으면 1이다.주의 — API가 노선의 모든 차량을 포착한다는 뜻은 아니다. | 파생 | msgBody.busLocationList[].vehId, msgBody.busLocationList[].stationSeq, msgBody.busLocationList[].stateCd; S1 정규화 last_passed; S1 upstream_bus_existsGBIS 버스위치정보 getBusLocationListv2 + S1 스냅샷 특징 빌더 |
상류 버스 축거리 (upstream_axis_gap_seq)상류 후보 중 목표에 가장 가까운 차량을 고르고 target station_seq-last_passed를 계산한다.주의 — 동률은 출발 stateCd=2, 교차 0, 도착 1 순, 더 최신 운행, 차량키 사전순으로 푼다. 좌석값은 선택 기준이 아니다. | 파생 | msgBody.busLocationList[].vehId, msgBody.busLocationList[].stationSeq, msgBody.busLocationList[].stateCd; S1 정규화 last_passed; S1 upstream_axis_gap_seqGBIS 버스위치정보 getBusLocationListv2 + S1 스냅샷 특징 빌더 |
KST 하루 중 분 (query_minute_of_day)KST 시각에서 hour*60+minute을 계산한다.주의 — msgHeader.queryTime은 쓰지 않는다. 초는 버린다. | 파생 | timing.response_received_at.kst, timing.response_received_at.utc; S1 E4 response_received_kst, response_received_utc; 코퍼스 collectedAt; S1 query_minute_of_day우리 수집기 응답 수신시각; 제한 코퍼스는 수집기가 붙인 collectedAt |
목표 축 순번 (station_seq)stateCd=1이면 현재 stationSeq-1, stateCd=0·2이면 현재 stationSeq를 마지막 통과 순번으로 놓는다. 인접 적격 응답에서 이 값이 전진한 끝점을 통과 사건 순번으로 삼는다.주의 — 모델 축은 routestation 전체 순번이다. 학습 행은 서비스 정차점만 남겨도 축 간격에는 미정차·경유 지점이 들어간다. | 파생 | msgBody.busLocationList[].vehId, msgBody.busLocationList[].stationSeq, msgBody.busLocationList[].stateCd; routestation.staOrder; S1 station_seqGBIS 버스위치정보 getBusLocationListv2 + GBIS routestation 마스터 + S1 통과 사건 빌더 |
원천 구분 (source_kind)직접 수집 행은 direct_e4, 제한 코퍼스 행은 corpus로 붙인다.주의 — GBIS 응답 필드가 아니다. GBM에는 범주형 예측 재료로 들어가고, 구간 검열에서는 같은 원천끼리 연결하는 데 쓴다. | 파생 | S1 source_kindS1 데이터셋 빌더 |
날짜 순번 (query_day_index)KST 날짜에서 2026-07-19를 뺀 일수를 쓴다.주의 — 이 데이터셋의 고정 기준일에 묶인 값이다. 달력 날짜의 보편적 ID가 아니다. | 파생 | timing.response_received_at.kst, timing.response_received_at.utc; S1 E4 response_received_kst, response_received_utc; 코퍼스 collectedAt; S1 query_day_index우리 수집기 응답 수신시각; 제한 코퍼스는 수집기가 붙인 collectedAt |
같은 차량·운행 연결키같은 원천·노선·구간·가명 차량을 묶고 순번 회귀·긴 공백에서 운행을 나눠 journey_index를 붙인다.주의 — 코퍼스 차량키는 plateNo 우선 HMAC 앞 16 hex이며 외부 원 식별자로 되돌릴 수 없다. 원천을 넘겨 같은 차량으로 보지 않는다. | 파생 | msgBody.busLocationList[].vehId, msgBody.busLocationList[].plateNo; 직접 S1 target_vehicle_hash, 코퍼스 vehicles[].id; S1 source, route, segment_id, vehicle_hash, journey_indexGBIS 버스위치정보 getBusLocationListv2 + 수집기 가명화 + S1 운행 분할 |
미관측 중간 통과 구간인접 적격 응답의 정규화 순번이 +2 이상이면 끝점 사건만 만들고 각 중간 순번을 reason=sequence_jump_intermediate_passage_unobserved로 기록한다.주의 — 선형 보간한 가짜 통과시각을 만들지 않는다. 불가능 이동 사유는 이 모형의 전이쌍에서 제외한다. | 파생 | S1 censored_passages.reason, censored_passages.source, censored_passages.route, censored_passages.segment_id, censored_passages.vehicle_hash, censored_passages.interval_start, censored_passages.interval_end, censored_passages.station_seq, censored_passages.normalized_sequence_jumpS1 censored_passages |
서비스 정차점 표시stationName에 (미정차)나 (경유)가 없으면 1로 둔다.주의 — 현재 S1 빌더는 station.stationName이 아니라 routestation.stationName을 읽는다. | 파생 | routestation.stationName; S1 is_service_stopGBIS routestation 마스터 + S1 정류장 필터 |
검열 구간 양끝 만석 상태검열 구간 끝점의 서비스 정차 통과 라벨과, 같은 차량·운행에서 90초 안에 앞서 확정된 서비스 정차 라벨을 연결한다.주의 — label_status=ok, is_service_stop=1만 쓴다. 같은 원천과 인과 시각 조건을 지킨다. | 파생 | S1 censored_passages.source, censored_passages.route, censored_passages.segment_id, censored_passages.vehicle_hash, censored_passages.interval_start, censored_passages.interval_end, censored_passages.station_seq; passage_events.source, passage_events.route, passage_events.segment_id, passage_events.vehicle_hash, passage_events.label_status, passage_events.is_service_stop, passage_events.label_full, passage_events.passage_interval_start, passage_events.passage_interval_end, passage_events.journey_index, passage_events.station_seq; 모델 내부 start_state, end_stateS1 censored_passages + S1 passage_events |
전이 횟수와 숨은 통과 수같은 검열 구간의 중간 순번 행 수를 latent_passage_count로 세고 transition_count=latent_passage_count+1로 둔다.주의 — 한 구간의 중간 순번 행을 서로 독립 표본으로 세지 않는다. | 파생 | S1 censored_passages.normalized_sequence_jump; 모델 내부 latent_passage_count, transition_countS1 censored_passages + 구간 검열 모형 내부 |
검열 전이 그룹route | am·pm | b((station_seq-1)//10)으로 묶어 0↔1 전이율을 추정한다. 12:00 전은 am이다.주의 — API의 공식 시간대나 방향 코드가 아니다. 10순번 폭은 구현 규칙이다. | 파생 | S1 route, query_minute_of_day, station_seq; 모델 내부 transition_group구간 검열 모형 내부 |
지금은 안 쓰는 재료 5개
- 차량 정원·점유율 —
TBBMSVEHINFOM.SEAT_RDNG_PSN_CNT; 점유율 후보식1-msgBody.busLocationList[].remainSeatCnt/TBBMSVEHINFOM.SEAT_RDNG_PSN_CNT20일 코퍼스 차량키가plateNo우선 HMAC이라 외부 정원과 조인된 차량이 0/77이다. 기존 231,048행의capacity_exact도 모두 0이다. 관측 최대 잔여석은 정원의 하한일 뿐 고정 정원이 아니다. 라벨은 출발 후 좌석이 0인지에 정원이 필요 없다. 프로토타입의defaultSeatCapacity=80은 분포 배열 상한이며 점유율 분모가 아니다. - 혼잡도 — GBIS getBusLocationListv2
msgBody.busLocationList[].crowded공식 제공 노선유형은 13·15·23이고 대상 노선은 11이다. 직접 수집분에서 같은 잔여석 값에 다른 코드가 붙은 값이 26개 나와 잔여석만의 전역 함수라는 해석은 반증됐다. 다만 같은(vehId, remainSeatCnt)에서는 충돌이 0셀이고crowded만 바뀐 연속쌍도 0건이라 차량별 임계화일 가능성이 남는다. 산식은 미확정이고 아직 특징으로 써 보지 않았다. - API queryTime 파생 시간 — GBIS getBusLocationListv2
msgHeader.queryTime; HTTP 응답 헤더Date같은 노선 연속 38쌍 중 7쌍에서queryTime이 뒤로 갔다. 직접 수집 92/92건에서는 응답 수신시각보다 미래였고 중앙 +17.265초였다. HTTPDate는queryTime의 초 절삭과 92/92 일치해 독립 시계가 아니다. 감사 원문만 보존하고 나이·속도·헤드웨이·분할에 쓰지 않는다. remainSeatCnt=-1을 0석으로 대치 — GBIS getBusLocationListv2msgBody.busLocationList[].remainSeatCnt20일 코퍼스 차량행에서-1은 69건이다. 좌석 미제공이며 만석 0과 뜻이 다르므로 결측으로 둔다.- 불가능 이동 간선 — S1
censored_passages.reason=impossible_movement_edge_passage_count_unknown,normalized_sequence_jump정규화 순번 도약이 +3 이상이고 축 거리 하한 속도가 300km/h를 넘은 S1 검열 행 689건이다. 통과 수 자체를 모르는 검열이라 구간 전이쌍으로 쓰지 않는다.
언제 실패하나
- 누락이 무작위가 아니면 틀어진다. 만석일 때만 응답이 더 자주 빠지거나 긴 폴링 공백이 혼잡 시간에 몰리면, 관측된 양끝으로 배운 전이표가 빠진 구간을 대표하지 못한다.
- 두 상태 Markov 가정이 거칠다. 현재 구현은 노선×오전·오후×순번 10칸 안에서 같은 전이표를 쓴다. 연속 만석 길이, 더 먼 과거, 회차점의 급변은 직접 넣지 않는다.
- 실제 다음 버스가 아니라 next_observed_bus다. 90초 이하 구간에서도 숨은 제3차량 하한은 3330 17.24%, 1650 12.01%였다. 빠진 차량이 있으면 시작 상태와 축거리가 어긋난다.
- 새 셀과 새 노선 근거가 없다. 코퍼스 validation의 새 셀은 2/10,040행, 만석 0건뿐이다. 본 적 없는 셀의 AUC와 보정 수치: 아직 없음.
- 보정 계단도 얇은 구간에서 흔들린다. [.1,.2)는 97건에서 평균예측 .1216, 관측률 .2577이었다. [.6,.7)는 21건에서 .6051 대 .8095였다.
- 직접 수집분 표본이 아직 얇다. train 1,081건·만석 40건, validation 443건·만석 14건이고 수집 날짜가 하루뿐이다. AUC 21쌍 중 16쌍을 못 가려 승자를 정하지 않았다.
- 출력 라벨은 개인의 승차 성공과 같지 않다. 출발 후 0석은 좌석이 소진됐다는 보수적 사건이다. 하차로 생긴 자리에 일부 승객이 탄 경우까지 만석으로 센다.
기존 프로토타입과 다른 점
- 프로토타입은 좌석 변화 관측쌍의 양끝 중 하나가 0석이면 수요 숫자를 버리고 censoredWeight만 올렸다. 이 모형은 폴링 사이에 못 본 중간 통과의 F/A를 잠재 상태로 두고 양끝 우도에 넣는다.
- 프로토타입 화면의 탑승률은 정류장×시간 셀의 1-zeroCount/samples였고 차량별 좌석 예보와 다른 계산이었다. 이 모형은 출발 후 만석확률 하나를 내고 탈 확률을 1-p_full로만 바꾼다.
- 프로토타입에는 좌석값을 도착 전과 처리 후 의미로 섞어 읽는 경로가 있었다. 이 모형은 내 정류장 도착값을 금지하고 출발 이후 0만 만석 라벨로 쓴다.
- 프로토타입에는 확률 보정층이 없었다. 이 모형은 날짜 순방향 OOF로 isotonic을 학습하며 validation 라벨을 보지 않는다.
- 프로토타입에는 중간 상태 전이표가 없었다. 이 모형은 T^k로 가능한 중간 상태 경로를 합산하며 점 통과시각과 가짜 행을 만들지 않는다.
- 둘 다 -1과 0을 가르고 보지 못한 값을 사실처럼 만들지 않는다. 이 모형은 못 본 사건을 경고 숫자로만 남기지 않고 학습 우도에 직접 넣는다.