自社便の配送で、当日の積込・走行・配達の記録から配送先ごとの到着時刻を見込み、遅れそうな配送先へ事前の連絡文を作る
自社便の当日の積込・走行・配達の記録から、残りの配送先ごとに到着の見込みを出し、指定の時間に遅れそうな配送先を配車係に知らせます。遅れそうな配送先には、到着の見込みを伝える連絡文の下書きを添えます。
- 生成AI
- ChatGPT/Claude/Gemini
- 連携・自動化
- Python
- 対象業界
- 商社/小売/物流/製造
- 対象部門
- カスタマーサポート/物流
- 対象業務
- 書類作成/集計・分析
- 主な課題
- 判断に時間がかかる/問い合わせが多い/属人化している
- AIで行う処理
- 予測
- 主な効果
- 判断支援/対応スピード向上/工数削減
- 導入難易度
- ★★★★☆
- 実装レベル
- 本格構成
- 費用感
- RAG・個別開発(大)
- 人間の確認
- 条件付き
01導入前 / 導入後の業務フロー
- 朝、配車システムで便ごとの配送順と時間指定を確かめる
- 出庫の後、時間指定の近い配送先について、ドライバーに電話して今どこを走っているかを聞く
- 残りの配送先の数と道の混み具合から、時間指定の配送先に何時ごろ着くかを頭の中で見込む
- 遅れそうなら、配送先へ電話し、到着の見込みを伝える。つながらなければ折り返しを待つ
- 配送先から「まだ来ないのか」と問い合わせが来たら、もう一度ドライバーに電話して確かめる
- 夕方、遅れた配送先と連絡した時刻を日報に書く
- 自動積込が終わった時点で、便ごとの配送順・時間指定・積込完了の時刻を Python が読み込む
- 自動30分ごとに、車載端末の最新の位置と配達完了の記録を読み込む
- 自動今の位置から残りの配送先までの走行時間を、道路の混み具合を考えた経路の所要時間で取る
- 自動機械学習のモデルが、残りの配送先ごとに「普通なら」と「遅めなら」の到着の見込みを出す
- 自動遅めの見込みが時間指定の終わりを過ぎる配送先を「遅れのおそれ」、普通の見込みでも過ぎるものを「遅れの見込み」とする
- 自動遅れのおそれ以上の配送先について、Claude API が到着の見込みを伝える連絡文の下書きを作る
- 人配車係が一覧を開き、遅れの見込みの配送先から順に、下書きを確かめて連絡する
- 人配送順を入れ替える、応援の車を出すなどの判断が要るものは、配車係が決める
- 自動配達が終わったら、見込みと実際の到着を並べて記録する
各工程の詳しい説明を読む
- 朝、配車システムで便ごとの配送順と時間指定を確かめる
- 出庫の後、時間指定の近い配送先について、ドライバーに電話して今どこを走っているかを聞く
- 残りの配送先の数と道の混み具合から、時間指定の配送先に何時ごろ着くかを頭の中で見込む
- 遅れそうなら、配送先へ電話し、到着の見込みを伝える。つながらなければ折り返しを待つ
- 配送先から「まだ来ないのか」と問い合わせが来たら、もう一度ドライバーに電話して確かめる
- 夕方、遅れた配送先と連絡した時刻を日報に書く
(a)見込みは配車係の頭の中にある。 3番目は、配送先ごとの荷受けにかかる時間、時間帯ごとの道の混み具合、ドライバーごとの走り方を知っている配車係にしかできません。ベテランが休んだ日は、遅れに気づくのが遅れ、問い合わせが増えます。
(b)ドライバーへの電話が運転を止める。 2番目と5番目の電話のたびに、ドライバーは車を止めて答えます。位置は車載端末に記録されているのに、それを読む仕組みが無いので、電話で聞いています。
(c)連絡が後手になる。 1人の配車係が同時に何台も見ているので、時間指定の配送先を順番に確かめているうちに、指定の時刻を過ぎてしまう配送先が出ます。 先に電話すべき配送先がどれかを、全部の便を見比べて決める余裕がありません。
(d)問い合わせへの答えが毎回の確認になる。 5番目は、配送先から聞かれてからドライバーに電話し直すので、同じ配送先について1日に何度も同じ確認をすることがあります。
- 【自動】 積込が終わった時点で、便ごとの配送順・時間指定・積込完了の時刻を Python が読み込む
- 【自動】 30分ごとに、車載端末の最新の位置と配達完了の記録を読み込む
- 【自動】 今の位置から残りの配送先までの走行時間を、道路の混み具合を考えた経路の所要時間で取る
- 【自動】 機械学習のモデルが、残りの配送先ごとに「普通なら」と「遅めなら」の到着の見込みを出す
- 【自動】 遅めの見込みが時間指定の終わりを過ぎる配送先を「遅れのおそれ」、普通の見込みでも過ぎるものを「遅れの見込み」とする
- 【自動】 遅れのおそれ以上の配送先について、Claude API が到着の見込みを伝える連絡文の下書きを作る
- 【人】 配車係が一覧を開き、遅れの見込みの配送先から順に、下書きを確かめて連絡する
- 【人】 配送順を入れ替える、応援の車を出すなどの判断が要るものは、配車係が決める
- 【自動】 配達が終わったら、見込みと実際の到着を並べて記録する
7番目が、この設計の分かれ目です。人が見るのは遅れのおそれのある配送先だけです。 1,800件すべてに電話で確かめる形のままだと、90.0時間はほとんど減りません。間に合う見込みの配送先は、一覧の色で流し見るだけにします。
5番目で2段階に分けるのは、連絡の順番を決めるためです。 普通の見込みでも遅れるものは、ほぼ確実に遅れます。遅めの見込みだけが過ぎるものは、荷受けが長引けば遅れるものです。前者から先に連絡します。
02今回想定するシステム構成
配車システム(便・配送順・時間指定) 車載端末(位置・出庫・到着・配達完了の時刻) │ ▼【トリガー】積込完了の時点と、8時〜18時の30分ごと Python(pandas で便ごとの残りの配送先と、その時点の状態を作る) │ ├──▶ Routes API ── 今の位置から残りの配送先までの所要時間(混み具合を考慮) ▼ Python(scikit-learn の HistGradientBoostingRegressor を2つ) │ 普通の見込み(中央値)/遅めの見込み(90%点) ▼ 時間指定と比べて判定(遅れの見込み/遅れのおそれ/間に合う見込み) │ ├──▶ Claude API ── 到着の見込みを伝える連絡文の下書き ▼ 【配車係が確かめ、配送先へ連絡する】 ▼ 配達完了の記録 ── 見込みと実際の到着を記録 ── 月1回の学び直し
| 役割 | 想定する製品 | 代替候補 |
|---|---|---|
| 実行環境 | Python(pandas・scikit-learn の HistGradientBoostingRegressor) | R、BigQuery ML |
| 生成AI | Claude API(到着の見込みを伝える連絡文の下書き) | OpenAI API、Gemini API |
| 道路の所要時間 | Google Maps Platform の Routes API(TRAFFIC_AWARE) | 過去の走行記録から作る区間ごとの平均 |
| データの取得元 | 配車システムと車載端末の書き出し | 各システムのAPI(提供がある場合) |
| 通知 | 配車係の画面とチャット | ― |
| 保存 | 社内のデータベース | ファイルサーバー |
配車システムには書き込みません。 配送順の入れ替えも、応援の車の手配も、いままでどおり配車係が配車システムで行います。この構成が受け持つのは、到着の見込みと、遅れそうな配送先の一覧と、連絡文の下書きまでです。
道路の所要時間には、Routes API の混み具合を考える設定を使います。 公式ドキュメントでは、TRAFFIC_UNAWARE(既定)は現在の交通状況を考えずに計算して応答が最も速く、TRAFFIC_AWARE は現在の交通状況を考えて TRAFFIC_UNAWARE より正確な結果を返し、TRAFFIC_AWARE_OPTIMAL は応答の遅さを問わず最も質の高い結果を返すとされています。duration は現在の交通を反映した所要時間、staticDuration は過去の交通だけを考えた所要時間です。 混み具合を考える2つの設定は、料金が高い区分になるとされています。
モデルに HistGradientBoostingRegressor を選ぶ理由は2つあります。 1つ目は、loss='quantile' で中央値や90%点のような分位点を直接学べることです。2つ目は、欠けた値(NaN)をそのまま扱えることで、車載端末の位置が途切れた時間帯や、初めての配送先で過去の荷受けの時間が無いものを、0で埋めずに渡せます。
03どうやって実装するのか
処理の起点を決める
積込完了の時点と、8時から18時までの30分ごとに回します。 積込完了の時点の見込みは、その日の最初の連絡に使います。出庫前に「今日は遅れる」と分かる配送先は、朝のうちに連絡します。
30分ごとの回は、便ごとに最新の記録だけで見込みを作り直します。 配達完了の記録が入るたびに回す形も考えられますが、25台が1日に数百件の完了を記録するので、30分ごとにまとめたほうが、見込みの揺れが落ち着きます。 回すたびに結果を上書きせず、時刻付きで残します。
入力データを集める
| データ | 中身 | 取得元 |
|---|---|---|
| 当日の便 | 便番号、車両、ドライバー、配送順、配送先、時間指定の始まりと終わり、立会いの要否 | 配車システム |
| 走行と配達の記録 | 出庫の時刻、位置と時刻、配送先ごとの到着と配達完了の時刻 | 車載端末 |
| 配送先の一覧 | 住所の緯度経度、荷受けの場所(現場の入口・店舗の裏口)、過去の荷受けにかかった時間 | 配送先の一覧と過去の記録 |
| 積込の記録 | 便ごとの積込完了の時刻、荷の個数・重さ | 倉庫の積込の記録 |
| 道路の所要時間 | 今の位置から次の配送先、配送先から配送先までの duration と staticDuration | Routes API |
質を決めるのは、2行目の「配送先ごとの到着と配達完了の時刻」です。 到着から完了までが荷受けにかかった時間で、これが配送先ごとに大きく違います。 工事現場は職人を呼んでくるまで待ち、ホームセンターは検品の列に並びます。到着と完了の両方を押す運用になっていなければ、最初にそこを直します。
3行目の過去の荷受けの時間は、配送先ごとの中央値と、ばらつきの大きさで持ちます。 「平均20分」の配送先でも、10分の日と50分の日が混ざっていれば、遅めの見込みが大きく変わります。
データの取得方法を決める
配車システムから当日の便を、車載端末の管理画面から位置と配達の記録を、それぞれCSVかAPIで取り、Python の pandas で読み込みます。どの形で取れるかは製品ごとに違うため、最初に、配達完了の記録が何分遅れで取れるかを確かめます。 1時間遅れでしか取れないなら、30分ごとに回す意味がありません。
| 取るもの | どこから | 何に使うか |
|---|---|---|
| 当日の便 | 配車システム(積込完了の時点) | 残りの配送先と時間指定 |
| 最新の位置と配達完了 | 車載端末(30分ごと) | 今どこにいて、何件残っているか |
| 道路の所要時間 | Routes API | 走行の時間の土台 |
| 過去の便と実際の到着 | この構成の保存先 | 学び直し |
Routes API は、残りの配送先を順番に結んだ区間ごとに呼びます。 今の位置から次の配送先、次から次へと区間を並べ、duration を足していきます。1台あたり残り十数区間で、30分ごとに25台分なので、呼ぶ回数と料金を最初に見積もります。 混み具合を考える設定は料金が高い区分なので、夕方以降に残りが数件になった便から、呼ぶ間隔を広げます。
AIへ渡す前に整形する
- その時点の状態を作る … 便ごとに、最後に配達を終えた配送先、今の位置、残りの配送先の並びを作ります
- 遅れの積み上がり … ここまでの配送先で、予定よりどれだけ遅れているか(分)を出します
- 走行の時間 … 残りの配送先ごとに、今の位置からその配送先までの
durationの合計とstaticDurationの合計を出します - 荷受けの時間 … その配送先より前にある配送先の、過去の荷受けの時間の中央値の合計を出します
- 時刻の特徴 … 曜日、その時点の時刻、月末か、雨か(気象の記録を取り込む場合)を加えます
- 欠けた値の扱い … 初めての配送先の荷受けの時間、位置が途切れた時間帯は、0で埋めずに NaN のまま渡します
- 目的の値 … 「その時点から、その配送先に実際に着くまでの分数」を目的の値にします
学習用のデータは、過去の便を30分ごとの時点で切って作ります。 同じ便の同じ配送先について、9時の時点、9時30分の時点、……の行ができ、それぞれに「その時点で分かっていたこと」だけを入れます。その時点より後の配達完了の記録を混ぜると、学習では当たるのに本番では外れるモデルになります。 時刻で切る処理を必ず入れます。
7番目を「到着の時刻」ではなく「その時点からの分数」にするのは、時刻のままだと朝の便と午後の便で値の大きさがまったく違うからです。 分数にしてから、その時点の時刻に足して到着の見込みに戻します。
AIに処理させる
この構成の「AI」は2つの部品に分かれます。 到着の見込みを出すのが機械学習のモデル、連絡文を整えるのが生成AIです。生成AIは時刻を作りません。
| 部品 | させること | させないこと |
|---|---|---|
| HistGradientBoostingRegressor(中央値) | 残りの配送先ごとの普通の見込み | 配送順を入れ替えたときの見込み |
| HistGradientBoostingRegressor(90%点) | 残りの配送先ごとの遅めの見込み | ― |
| 判定(Python) | 時間指定と比べて、遅れの見込み/遅れのおそれ/間に合う見込みに分ける | 連絡するかの最終の決定 |
| Claude API | 連絡文の下書き | 時刻を変える、遅れの理由を作る |
遅めの見込みに90%点を使うのは、「10回に1回はこれより遅くなる」ラインだからです。 公式ドキュメントでは、loss='quantile' はピンボール損失を使い、quantile で推定する分位点を0から1の間で指定するとされています。中央値(0.5)と90%点(0.9)で、モデルを2つ学ばせます。
2つのモデルの見込みが逆転することがあります。 別々に学ばせるので、まれに90%点の見込みが中央値より早く出ます。その場合は90%点を中央値にそろえ、記録に印を付けます。 印が増える配送先は、学ぶ材料が足りていません。
単調の制約も入れます。 公式ドキュメントでは、monotonic_cst で特徴ごとに単調増加(1)・単調減少(−1)を指定できるとされています。残りの走行時間と、前にある配送先の数は、増えれば到着が遅くなる向きに縛ります。 縛らないと、データの少ない範囲で「配送先が増えたのに早く着く」見込みが出ることがあります。
学び直しの成績は、時間の順に分けて測ります。 公式ドキュメントでは、TimeSeriesSplit は時間順のデータを分けるもので、ほかの分け方は未来のデータで学習して過去を評価することになり不適切とされています。
| 生成AIにさせないこと | 理由 |
|---|---|
| 見込みの時刻を書き換える、丸めを変える | 配車係が確かめた時刻と食い違う |
| 遅れの理由を書く(渋滞・前の配送先の都合) | 確かめていない理由を配送先へ伝えることになる |
| 「必ず」「確実に」と約束する | 見込みは見込み。外れたときに約束を破ったことになる |
| 他の配送先の名前や荷の中身を書く | 別の取引先の情報が漏れる |
指示内容を固定する
モデルの設定は次のとおりです。 学習は月1回、見込みは30分ごとに回します。
import numpy as np
from sklearn.ensemble import HistGradientBoostingRegressor
common = dict(
categorical_features="from_dtype", # 配送先の種類・曜日は Categorical 型
monotonic_cst={"remaining_drive_min": 1, # 残りの走行時間が増えれば遅くなる
"stops_before": 1}, # 前にある配送先が増えれば遅くなる
max_iter=400, learning_rate=0.05,
)
p50 = HistGradientBoostingRegressor(loss="quantile", quantile=0.5, **common)
p90 = HistGradientBoostingRegressor(loss="quantile", quantile=0.9, **common)
p50.fit(X_train, y_train) # y はその時点から到着までの分数
p90.fit(X_train, y_train)
eta50 = now + p50.predict(X_now) # 普通の見込み
eta90 = now + np.maximum(p90.predict(X_now), p50.predict(X_now)) # 逆転をそろえる
判定は、時間指定の終わりと2つの見込みを比べるだけにします。 普通の見込みが過ぎれば late_likely、遅めの見込みだけが過ぎれば late_risk、どちらも過ぎなければ on_time です。判定を生成AIに任せないのは、同じ見込みから毎回同じ答えが出る必要があるからです。
連絡文の下書きは、Claude API に次の指示で作らせます。
あなたは建築資材の卸の配車係で、時間指定のある配送先へ、到着の見込みを事前に知らせる
連絡文を書く立場です。渡された情報だけを使って、電話で伝える要点とSMS・メールの本文を
作ってください。
【渡す情報】
- 配送先の名前(会社名と現場名)、時間指定(例:10:00まで)
- 到着の見込み(普通の見込みと遅めの見込み。Python が出した時刻)
- 判定(late_likely または late_risk)
- 自社の名前と、配車係の連絡先
【書き方】
- 到着の見込みは「◯時◯分ごろから◯時◯分ごろ」と、渡された2つの時刻の幅で書いてください。
- late_likely の場合は、時間指定に間に合わない見込みであることをお詫びとともに伝えてください。
- late_risk の場合は、時間指定ぎりぎりになるおそれがあることを伝えてください。
- 受け取りの段取りに差し支えがあれば連絡がほしいと書き、連絡先を添えてください。
- 電話の要点は3行以内、SMSの本文は120字以内にしてください。
【厳守事項】
- 時刻を書き換えないでください。丸める場合は5分単位で、遅い側へ丸めてください。
- 遅れの理由(渋滞、前の配送先、天候 など)を書かないでください。
- 「必ず」「確実に」など、到着を約束する表現を使わないでください。
- 渡された配送先以外の会社名や、荷の中身を書かないでください。
- 渡された情報が足りない場合は、文面を作らず missing に足りない項目を書いてください。
【配送先と見込み】{stop}
【自社の情報】{company}
「遅れの理由を書かない」を明記しないと、生成AIは丁寧に理由を足します。 「道路の混雑により」と書かれた連絡を受けた配送先は、本当の理由が前の配送先での待ちだったと後で知ると、連絡そのものを信じなくなります。
出力形式を固定する
次の形のJSONを、残りの配送先ごとに作ります。 時刻と判定は Python が埋め、draft を Claude API の構造化出力(output_config.format に type: "json_schema")で受け取ります。
{
"run_at": "2026-10-07T09:30:00+09:00",
"route_id": "R-07-12",
"stop_seq": 6,
"stop_id": "C-20418",
"window_end": "2026-10-07T11:00:00+09:00",
"eta_p50": "2026-10-07T10:52:00+09:00",
"eta_p90": "2026-10-07T11:18:00+09:00",
"delay_so_far_min": 14,
"status": "late_risk",
"flags": ["first_visit"],
"draft": { "phone_points": "", "sms": "", "missing": [] },
"contacted": null
}
1つ目の理由は、時刻と文面を別の欄に置けることです。 配車係が見るのは eta_p50 と eta_p90 で、draft はそれをもとに作った文です。下書きの時刻が eta_p90 と食い違っていないかを、送る前に Python で照合します。
2つ目は、run_at で見込みの動きを追えることです。 同じ配送先の見込みが、9時、9時30分、10時と、どう動いたかを並べて見られます。遅れの見込みが急に跳ねたら、前の配送先で何か起きています。
3つ目は、flags で見込みの確からしさを伝えられることです。 first_visit(初めての配送先)、gps_gap(位置が途切れている)、order_changed(配送順が予定と違う)のような印があれば、配車係はその見込みを割り引いて読みます。
システムへ連携する
| つなぎ先 | 方式 | 内容 |
|---|---|---|
| 配車システム | 書き出しの読み取り | 当日の便、配送順、時間指定 |
| 車載端末 | 管理画面の書き出しかAPI | 位置、到着と配達完了の時刻 |
| Routes API | API呼び出し | 区間ごとの所要時間 |
| Claude API | API呼び出し | 連絡文の下書き |
| 配車係の画面とチャット | 一覧の表示と投稿 | 遅れの見込みと遅れのおそれの一覧 |
| 社内のデータベース | 書き込み | 見込み・判定・連絡の記録 |
配送先への連絡は、この構成から自動で送りません。 配車係が下書きを確かめ、電話するか、SMSやメールで送ります。遅れの連絡は取引先との関係に直接ひびくので、送る判断は人に置きます。
ドライバーへは、この構成から何も送りません。 運転中のドライバーに通知を送ると、画面を見る理由を作ってしまいます。ドライバーへの指示が要るときは、いままでどおり配車係が判断して連絡します。
人が確認する
人が開くのは、late_likely と late_risk の配送先だけです。 on_time のものは、一覧の色で流し見るだけにします。
late_likelyを先に見る … 下書きを確かめ、配送先へ連絡します。連絡した時刻と、相手の返事を記録しますlate_riskは時間指定の近い順に見る … 立会いの要る配送先は連絡し、置き場所の決まった配送先は様子を見ますflagsの付いた見込みは割り引く … 位置が途切れているなら、ドライバーに1回だけ確かめます- 配送順の入れ替えや応援の車は、配車係が決める … この構成は、入れ替えた後の見込みを出しません
目標は、1,800件をならして1件1分です。 遅れのおそれのある配送先は1割前後という想定で、それより多い日は、積込の遅れか、時間指定の付け方に無理があります。
例外に対処する
| 起きること | 対応 |
|---|---|
| 車載端末の位置が途切れる | 最後の位置と配達完了から見込みを作り、gps_gap を付ける |
| 配送順が予定と違う | 実際の配達の順から残りを並べ直し、order_changed を付ける |
| 不在で持ち戻り | その配送先を残りから外し、持ち戻りとして記録する |
| 初めての配送先 | 荷受けの時間を NaN で渡し、first_visit を付ける |
| Routes API が応答しない | 過去の走行記録から作った区間ごとの平均で代わりに計算し、一覧に表示する |
| 車両の故障・事故 | 見込みを止め、配車係へ知らせる。見込みを出し続けない |
| 下書きの時刻が見込みと食い違う | 下書きを捨てて作り直す。2回続けば下書き無しで一覧に出す |
| 当日に追加された配送先 | 次の回から残りに足す。追加の前の見込みには使わない |
6行目は、見込みを出し続けることのほうが危ないものです。 止まっている車の見込みは、走行の時間を足すほど現実から離れます。故障の連絡が入った便は、人が判断するまで一覧から外します。
記録を残す
- 30分ごとの見込み(
eta_p50・eta_p90)と判定、そのときの位置と残りの配送先 - 呼んだ Routes API の区間と、返ってきた
duration・staticDuration - 下書きと、配車係が直した後の文面、連絡した時刻と手段
- 見込みと実際の到着の差 … 配送先ごと、時刻ごと
- 学び直しの日付と、そのときの成績(中央値の誤差、90%点を超えた割合)
4つ目の差は、90%点が本当に「10回に1回」になっているかを見るために要ります。 実際の到着が90%点を超えた割合が1割を大きく超えるなら、遅めの見込みが甘く、遅れを見落としています。
04実装レベルの3段階
最小構成は当日には使えません。 過去の便で試すための段階です。 半自動化で、1件3分が2分程度になります。 ドライバーへの電話はほぼ無くなりますが、見込みが粗いので、遅れそうに見える配送先を配車係が一つずつ確かめる作業と、連絡文を書く作業が残ります。本格構成で1分になり、この段階が本記事の想定です。 段階を飛ばさないでください。 半自動化の一覧を1か月使うと、到着と完了の記録が抜けやすいドライバーと、荷受けの時間が読めない配送先が分かります。そこを直してからモデルを学ばせるほうが、見込みが早く当たるようになります。
05工数削減シミュレーション
導入後 1,800件 × 1分 ÷ 60 = 30 時間/月
自社条件で導入効果を整理したい方へ
このユースケースを自社に当てはめた場合の前提値と削減見込みを、業務ヒアリングをもとに整理します。
06向いている企業・向いていない企業
- 自社のトラックで、店舗・工事現場・事業所などへ1日に数百件を配送し、時間指定や立会いのある配送先が多い運送会社・卸・メーカーの物流部門。配車係がドライバーに電話で進み具合を聞き、遅れそうな配送先へ連絡するかを経験で決めている場合。車載端末やスマートフォンのアプリで、出庫・到着・配達完了の時刻と位置が記録に残っている場合。
- 配送を宅配便などの他社便に任せていて、自社で走行の記録を持たない場合。時間指定がほとんど無く、遅れても連絡の要らない配送が中心の場合。過去の配達の時刻が記録に残っておらず、学ぶ材料が無い場合。なお、配送の順番を組み替えるか、応援の車を出すかの判断は、この構成では代替できません。
07最小構成で試す方法
- 先月の1か月分について、便ごとの配送順・時間指定と、配送先ごとの到着と配達完了の時刻を書き出す
- 配送先ごとに、荷受けにかかった時間の中央値と、遅い日の値(上から1割の値)を表計算で出す
- 先月の便から20便を選び、出庫の時点で、時間指定の配送先に何時に着くかを「走行の目安+荷受けの中央値」で足し上げる
- 同じ計算を「荷受けの遅い日の値」でもう一度行い、遅めの見込みにする
- 実際の到着と並べ、遅れた配送先が遅めの見込みで拾えていたかを見る
確かめたいのは、「記録だけで、配車係より早く遅れに気づけたか」です。 モデルを作る前に、荷受けの時間の違いだけでどこまで説明できるかを見ます。
| 出てきた内容 | 判断 |
|---|---|
| 遅れた配送先の多くが遅めの見込みで拾えた | モデルと30分ごとの見込みに進む |
| 到着と完了の記録が抜けていて計算できない | 車載端末の押し方を直すのが先。AIの問題ではない |
| 荷受けの時間では説明できない遅れが多い | 走行の時間(時間帯・道)の影響が大きい。Routes API を足して試す |
2行目が出ることは珍しくありません。 失敗ではなく、配車係が電話で確かめていた理由が1つ分かったということです。
08実装時につまずきやすいポイント
| 問題 | 対策 |
|---|---|
| 学習では当たるのに本番で外れる | その時点より後の記録を特徴に混ぜない。 時刻で切る |
| 普通の見込みだけで遅れを見落とす | 90%点の見込みを並べ、遅めの見込みで判定する |
| 90%点が中央値より早く出る | 別々に学ぶので起きる。中央値にそろえ、印を付ける |
| 配送先が増えたのに早く着く見込みが出る | monotonic_cst で向きを縛る |
| 到着と完了の記録が抜ける | 車載端末の押し方をそろえる。最初の作業 |
| 配送順の入れ替えで見込みが崩れる | 実際の配達の順から並べ直す |
| Routes API の料金がふくらむ | 呼ぶ間隔と区間をまとめ、残りの少ない便は間隔を広げる |
| 初めての配送先の見込みが外れる | NaN で渡し、first_visit を付けて人が割り引く |
| 連絡文に遅れの理由が入る | 指示で禁じ、時刻だけを伝える |
| 連絡が自動で配送先に飛ぶ | 下書きまでにする。 送るのは配車係 |
| ドライバーに通知を送ってしまう | 運転中の画面を見る理由を作らない |
上の2行が、この構成の失敗のほとんどです。 1行目は学ぶ段の誤りで、成績の数字が良く見えるので気づけません。 2行目は判定の段の誤りで、平均的な見込みでは「ぎりぎり間に合う」配送先が、荷受けが長引いた日にそろって遅れます。
5行目は、AIの外の話です。 記録が抜けている便は、どれだけモデルを工夫しても見込めません。運用をそろえることが、この構成の土台です。
09セキュリティ・AIガバナンス上の注意点
この構成で扱うデータ: 車両とドライバーの位置と時刻、配送先の名前と住所、時間指定、荷の個数。位置の記録は、ドライバー個人の働き方の記録でもあります。
- 位置の記録を、到着の見込み以外に使わない … ドライバーの評価や指導に転用すると、記録を押す運用が崩れます。使う目的を決めて、ドライバーに説明します
- 生成AIへ渡すのは、その配送先の情報だけにする … 他の配送先の名前や、ドライバーの名前は渡しません
- 連絡を自動で送らない … 遅れの連絡は取引先との関係に直接ひびきます。判定が外れたときの1件の連絡は、削減した時間より高くつきます
- この構成は、配送の判断を代替しません … 配送順を入れ替えるか、応援の車を出すか、時間指定に間に合わないときにどうするかは、配車係と取引先との取り決めで決めることです
- 見込みの外れを記録して見直す … 90%点を超えた割合を毎月見て、遅めの見込みが甘くなっていないかを確かめます
- 運転中のドライバーに通知しない … 見込みの一覧は配車係だけが見ます
誤りが起きた場合のリスクは、遅れる配送先を見落とすことと、遅れない配送先に遅れの連絡をしてしまうことの2つです。 前者は普通の見込みだけで判定すると起き、後者は記録が抜けた便の見込みを信じると起きます。どちらも、2つの見込みと flags を並べて見ることで防ぎます。
10まず何から始めるか
1週目:到着と配達完了の記録をそろえる
車載端末で、配送先ごとに到着と配達完了の両方を押す運用になっているかを確かめます。抜けているドライバーがいれば、押す場所と押す理由を説明します。あわせて、配車システムと車載端末の記録が何分遅れで取れるかを確かめます。
2週目:過去の20便で試す
先月の20便について、荷受けの時間の中央値と遅い日の値で見込みを足し上げ、実際の到着と並べます。遅れた配送先が遅めの見込みで拾えていたかを見ます。
3週目:判定と連絡の決まりを決める
どの判定で連絡するか、どの手段で連絡するか、誰が送るかを、配車課と営業で決めます。 立会いの要る配送先と、置き場所の決まった配送先で、扱いを分けます。
4週目:半自動化の一覧を出す
Python で積込完了と30分ごとに記録を読み、荷受けの時間と過去の平均の走行時間で見込みの一覧を出すところまで作ります。この時点では連絡文の下書きを出さず、見込みと実際の到着の差だけを見ます。
2か月目: Routes API の所要時間と2つの分位点のモデルを足し、90%点を超えた割合を毎週数えます。3か月目以降: 連絡文の下書きを足し、1件3分が何分になったかを実測します。見込みと実際の差を見ながら学び直しの間隔を決めた時点で、この構成は完成です。
11関連ユースケース
12この仕組みを理解するための記事
13技術仕様の確認日・参考情報
| 確認した内容 | 情報源 | 確認日 |
|---|---|---|
loss に 'quantile' があり、ピンボール損失を使うこと。quantile で推定する分位点を0から1の間で指定すること。欠けた値(NaN)をそのまま扱い、学習時に送り先を学ぶこと。categorical_features の既定が 'from_dtype' であること。monotonic_cst で特徴ごとに単調増加(1)・単調減少(−1)を指定でき、辞書で名前を指定できること | scikit-learn: HistGradientBoostingRegressor | 2026-10-07 |
TimeSeriesSplit が時間順のデータを分け、ほかの分け方は未来のデータで学習して過去を評価することになり不適切とされること。gap で学習用の末尾を除けること | scikit-learn: TimeSeriesSplit | 2026-10-07 |
TRAFFIC_UNAWARE(既定)・TRAFFIC_AWARE・TRAFFIC_AWARE_OPTIMAL の違い。duration が現在の交通を反映し、staticDuration が過去の交通だけを考えた所要時間であること。混み具合を考える2つの設定が高い料金の区分になること | Google Maps Platform: Routes API の交通の設定 | 2026-10-07 |
構造化出力で output_config.format に type: "json_schema" を指定できること | Claude Docs: Structured outputs | 2026-10-07 |
判定の基準(中央値と90%点)、見込みを出す間隔(30分)は本記事のモデル条件です。 実際の値は、過去の便で試して決めてください。配車システムと車載端末からの記録の取り出し方は製品ごとに違い、本記事では確かめていません。
実装ステータス:構成例。 公開仕様に基づいて設計した構成であり、当社で実際に構築・検証したものではありません。工数の数値はモデル条件による試算です。
自社の業務に使えるAI活用候補を整理します
このユースケース(UC-0643)についてのご相談はこちらから。
