Skip to content

ETA推定の系統誤差を修正: 迂回係数を経路全体で較正し種別速度倍率を実ダイヤに合わせる - #1590

Merged
TinyKitten merged 2 commits into
devfrom
claude/eta-estimation-accuracy-j0kfdt
Jul 5, 2026
Merged

TinyKitten merged 2 commits into
devfrom
claude/eta-estimation-accuracy-j0kfdt

Conversation

@TinyKitten

@TinyKitten TinyKitten commented Jul 5, 2026 •

Copy link
Copy Markdown
Member

概要

到着時間推定(ETA)が実乗車時間より短く出るという報告を受け、実路線の時刻表16ケース(山手線・銀座線・井の頭線・東横線・中央快速/特快・京急快特・小田急快急・新快速など)とモデル出力を突き合わせて系統誤差を較正した。都市部の優等列車(東横特急・中央特快・井の頭急行など)で10〜17%の過小評価が出ていた。

変更の種類

  • バグ修正
  • 新機能
  • データの修正・追加
  • リファクタリング
  • ドキュメント
  • CI/CD
  • その他

変更内容

  • 迂回係数αのスライス較正バグ修正(主因): αを「路線全体の平均実駅間距離(average_distance)÷ クエリ区間スライスの直線平均駅間距離」で計算していたため、駅間隔が路線平均と異なる部分区間(長距離路線の都心側など)でαが上限1.6に張り付き、走行距離を最大60%水増ししていた(例: 中央快速 東京→新宿 α=1.6、小田急 新宿→町田 α=1.53)。較正母数を切り出し前の経路全体に変更する estimate_arrival_minutes_calibrated を追加し、estimate_route_arrival_times の全呼び出し(線形スライス・逆順・環状弧)を切り替え。この水増しが一部路線で速度モデルの過大な速さを偶然相殺しており、誤差が±30%に散る原因になっていた
  • 種別速度倍率の見直し: 従来は kind != 0 の全種別に一律×1.2を掛けていたが、快速系(Branch/Rapid/CommuterRapid)は各停と同じ車両・線路を走り速達性は通過で表現されるため×1.0に。急行×1.15・特急×1.2とし、130km/h運転の新快速級(HighSpeedRapid)は×1.5に引き上げ(新快速の+20〜25%過大評価を解消)
  • 通過駅ペナルティの導入: 分岐器・ホーム進入部の曲線で最高速度を維持できないぶんとして、通過駅1駅あたり3秒(pass_penalty_seconds)を走行時間に加算
  • 回帰テスト3本を追加(スライス較正バグ・種別倍率・通過ペナルティ)

較正ベンチマーク16ケースでの効果: 平均絶対誤差 9.6%→7.4%、最悪の過小評価 -17%→-10%、平均バイアス -2%→+2.7%(「表示より早く着く」側にわずかに倒した設定)。既知の限界として、京急快特・小田急快急は実勢120km/h運転を kind から区別できず+20%ほど長めに出る(安全側)。

テスト

  • cargo fmt --all -- --check が通ること
  • cargo clippy -- -D warnings が通ること
  • cargo test(SQLX_OFFLINE=true)が通ること

関連Issue

スクリーンショット(任意)

🤖 Generated with Claude Code

https://claude.ai/code/session_01TsvFBx2rLj486tvj64M9eP


Generated by Claude Code

Summary by CodeRabbit

  • 新機能

    • 到着時刻の推定精度を改善し、通過駅に対する追加遅延を考慮できるようになりました。
    • 列車種別ごとの速度差をより柔軟に反映するようになりました。
    • 経路全体を使った到着時刻の補正に対応しました。
  • バグ修正

    • 迂回率の補正に、切り出した区間ではなく経路全体を使うよう修正しました。
    • 環状・直線・逆方向の経路でも、推定結果が安定するよう改善しました。

実路線の時刻表(山手線・銀座線・井の頭線・東横線・中央快速/特快・京急快特・
小田急快急・新快速など16ケース)と突き合わせたところ、推定誤差が±30%超に
散っており、利用頻度の高い都市部の優等列車(東横特急・中央特快・井の頭急行
など)で10〜17%の過小評価(ETAが短すぎる)が出ていた。

原因と修正:

1. 迂回係数αのスライス較正バグ(主因)
   αを「路線全体の平均実駅間距離(average_distance) ÷ クエリ区間スライスの
   直線平均駅間距離」で計算していたため、駅間隔が路線平均と異なる部分区間
   (長距離路線の都心側など)でαが上限1.6に張り付き、走行距離を最大60%
   水増ししていた(例: 中央快速 東京→新宿 α=1.6、小田急 新宿→町田 α=1.53)。
   較正母数を切り出し前の経路全体に変更(estimate_arrival_minutes_calibrated)。
   隣接駅間では軌道距離≒直線距離のためαの実態は1.0〜1.05であり、この水増しが
   一部路線で速度モデルの過小評価を偶然相殺して誤差の散らばりを生んでいた。

2. 種別速度倍率の見直し
   従来はkind≠0の全種別に一律×1.2を掛けていたが、快速系(Branch/Rapid/
   CommuterRapid)は各停と同じ車両・線路を走り速達性は通過で表現されるため
   ×1.0に。急行×1.15・特急×1.2は維持し、130km/h運転の新快速級
   (HighSpeedRapid)は×1.5に引き上げ(新快速の+20〜25%過大評価を解消)。

3. 通過駅ペナルティの導入
   分岐器・ホーム進入部の曲線で最高速度を維持できないぶんとして通過駅1駅
   あたり3秒(pass_penalty_seconds)を加算。

較正ベンチマーク16ケースでの効果: 平均絶対誤差 9.6%→7.4%、最悪の過小評価
-17%→-10%、平均バイアス -2%→+2.7%(わずかに安全側=実際より早く着くと
表示しない方向)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TsvFBx2rLj486tvj64M9eP
@TinyKitten TinyKitten self-assigned this Jul 5, 2026
@coderabbitai

coderabbitai Bot commented Jul 5, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 51 minutes

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f14002d7-8af9-482a-9698-f9707ca73f75

📥 Commits

Reviewing files that changed from the base of the PR and between 12279bf and ef50bb5.

📒 Files selected for processing (1)
  • stationapi/src/domain/arrival_estimation.rs
📝 Walkthrough

Walkthrough

到着時刻推定モデルに通過駅ペナルティと列車種別速度倍率ロジックを追加し、迂回係数の較正母数を経路全体の駅列から計算する estimate_arrival_minutes_calibrated を新設。query.rs の呼び出し箇所を更新し、環状・直線・逆順各経路で経路全体を較正母数として渡すよう変更した。

Changes

到着時刻推定ロジック変更

Layer / File(s) Summary
速度倍率と最高速度計算
stationapi/src/domain/arrival_estimation.rs
TrainTypeKind の import を追加し、kind_speed_multiplier を新設。max_speed_kmh を路線基本速度×種別倍率として再構成した。
通過駅ペナルティの追加
stationapi/src/domain/arrival_estimation.rs
EstimationParams に pass_penalty_seconds(デフォルト3.0)を追加し、通過駅ごとに巡航時間へ加算するよう変更した。
較正母数を経路全体から計算する関数
stationapi/src/domain/arrival_estimation.rs
estimate_arrival_minutes_calibrated を新設し、estimate_arrival_minutes をそのラッパーに変更。直線距離平均の計算を calibration_stops ベースに変更し、コメントを更新した。
query.rs での較正呼び出し切替
stationapi/src/use_case/interactor/query.rs
import を更新し、環状・直線・逆順の各分岐で切り出し前の route_stops を較正母数として渡すよう変更、スライス較正バグ回避のコメントを追加した。
テスト更新と回帰テスト追加
stationapi/src/domain/arrival_estimation.rs
速度種別指定テストを更新し、空入力・種別速度一致・通過ペナルティ加算・スライス較正バグ回帰の各テストを追加した。

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant QueryInteractor
  participant estimate_arrival_minutes_calibrated
  participant assign_segment_times

  QueryInteractor->>estimate_arrival_minutes_calibrated: stops(区間), calibration_stops(route_stops)
  estimate_arrival_minutes_calibrated->>estimate_arrival_minutes_calibrated: calibration_stopsから直線距離平均を計算
  estimate_arrival_minutes_calibrated->>assign_segment_times: 較正済みdetour_by_lineを渡す
  assign_segment_times-->>QueryInteractor: EstimatedStopリストを返す
Loading

Possibly related PRs

  • TrainLCD/StationAPI#1563: arrival_estimation.rs の到着時刻推定ロジックと estimate_route_arrival_times の呼び出しを、本PRのキャリブレーション対応が置き換える前提実装。
  • TrainLCD/StationAPI#1572: 同じ max_speed_kmh/速度倍率・迂回係数計算ロジックを路線種別基準で再構成しており、変更領域が直接重なる。
  • TrainLCD/StationAPI#1575: estimate_route_arrival_times が推定関数に渡す停止区間・較正用停止群の扱いを変更しており、本PRの較正母数受け渡しと同一箇所で連動する。

Suggested labels: fix

Poem

ぴょんと跳ねて 通過駅を数える耳
ペナルティ秒を そっと足して
経路全体で 距離を測り直し
較正の輪が きれいに揃う
うさぎも満足 到着時刻ぴったり 🐇⏱️

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed 主要な変更点であるETAの系統誤差修正、経路全体での較正、種別速度倍率の調整を簡潔に表しています。
Description check ✅ Passed 概要、変更の種類、変更内容、テストが揃っており、関連Issueとスクリーンショットは任意項目として扱えます。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/eta-estimation-accuracy-j0kfdt

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@stationapi/src/domain/arrival_estimation.rs`:
- Around line 505-520: The calibration logic in arrival_estimation’s detour
estimation currently only builds distances for adjacent station pairs, so a
circular route misses the final segment back to the first stop. Update the
calibration path handling in the detour calculation flow around
detour_factors_by_line and the calibration_straight_km setup to include the
closing edge for ring lines, or add a dedicated circular-route regression test
that verifies the full loop is included in average_distance-based calibration.

In `@stationapi/src/use_case/interactor/query.rs`:
- Around line 1204-1210: The circular-route calibration path in query.rs is
using the de-duplicated route_stops, which drops the closing segment from the
calibration basis. Update the is_circular_route branch around
select_circular_arc and estimate_arrival_minutes_calibrated so the calibration
input still accounts for the last-to-first seam on closed loops, instead of
passing only the truncated route_stops; make sure the fix preserves circular arc
handling while keeping the full adjacent-pair coverage needed for ETA
calibration.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: becd75c4-84a3-40b0-888a-3b846fd9337a

📥 Commits

Reviewing files that changed from the base of the PR and between d55f5c3 and 12279bf.

📒 Files selected for processing (2)
  • stationapi/src/domain/arrival_estimation.rs
  • stationapi/src/use_case/interactor/query.rs

Comment thread stationapi/src/domain/arrival_estimation.rs
Comment thread stationapi/src/use_case/interactor/query.rs
average_distance 自体が格納順の隣接ペアのみ(シーム辺なし)から算出されて
いるため、分母(直線平均)も同じ母数にするのが整合的であることを記載。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TsvFBx2rLj486tvj64M9eP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants