ホテルの予約の経路・リードタイム・プラン・人数から直前キャンセルとノーショーを見込み、宿泊日ごとの売り越しの枠の案を出す
入っている予約1件ずつについて、宿泊日の直前に取り消されるか、連絡なく来ないかの確率を見込みます。それを宿泊日・客室タイプごとに足し上げ、振替が起きる確率を決めた範囲に収めたまま、何室まで売り越せるかの案を出します。
- 連携・自動化
- Python
- 対象業界
- その他/宿泊
- 対象部門
- 営業
- 対象業務
- 比較検討/集計・分析
- 主な課題
- データ分析に時間がかかる/判断に時間がかかる/属人化している
- AIで行う処理
- 予測
- 主な効果
- 判断支援/属人化解消/機会損失防止
- 導入難易度
- ★★★★★
- 実装レベル
- 本格構成
- 費用感
- 個別開発(大)
- 人間の確認
- 条件付き
01導入前 / 導入後の業務フロー
- 予約課が、PMSから見直す宿泊日の予約一覧を書き出す
- 表計算で、客室タイプごとの予約数、取消の数、経路ごとの内訳を集計する
- レベニューマネージャーが、去年の同じ時期・同じ曜日の取消と不泊の数を別の表で探す
- 2つを見比べ、経験則と合わせて売り越しの室数を決める
- 予約課が、サイトコントローラーで販売できる室数を調整する
- 当日、部屋が足りなくなったら、フロントが近隣のホテルに空きを問い合わせて振り替える
- 自動毎朝5時、PMSから予約と、その作成・変更・取消の履歴を分析用の場所へ書き出す
- 自動Python が、見直す宿泊日の予約を、その時点の状態に組み立て直す
- 自動予約1件ごとに、直前の取消または不泊になる確率を見込む
- 自動宿泊日・客室タイプごとに確率を足し上げ、空く室数の分布を出す
- 自動売り越しの室数ごとに「あふれる確率」を計算し、上限に収まる最大の室数を案にする
- 自動上限の規則(客室タイプごとの最大室数、売り越さない日の一覧)を当てはめる
- 自動案と、案の根拠になった予約の内訳を、宿泊日ごとの一覧に書き出す
- 人レベニューマネージャーが一覧を見て、案をそのまま使うか、直すかを決める
- 人予約課が、決まった室数をサイトコントローラーで調整する
- 自動宿泊日が過ぎたら、実際の取消・不泊の数と案の数を突き合わせて記録する
各工程の詳しい説明を読む
- 予約課が、PMSから見直す宿泊日の予約一覧を書き出す
- 表計算で、客室タイプごとの予約数、取消の数、経路ごとの内訳を集計する
- レベニューマネージャーが、去年の同じ時期・同じ曜日の取消と不泊の数を別の表で探す
- 2つを見比べ、経験則と合わせて売り越しの室数を決める
- 予約課が、サイトコントローラーで販売できる室数を調整する
- 当日、部屋が足りなくなったら、フロントが近隣のホテルに空きを問い合わせて振り替える
(a)枠が予約の中身を見ていない。 3番目で比べるのは、去年の同じ曜日の件数です。今年の予約に無料で取り消せるプランが多いのか、返金不可のプランが多いのかは見ていません。同じ金曜でも、学会の開催で法人の予約が多い週は取消が少なく、去年と同じ枠では部屋が足りなくなります。
(b)担当者でないと決められない。 4番目の経験則は書かれていません。レベニューマネージャーの不在の週は、前回の数字を使い回すか、売り越しをやめるかのどちらかになります。 やめた週は、取消で空いた部屋がそのまま空室で終わります。
(c)外れたときの手当てが重い。 部屋が足りなくなると、フロントが当日の夕方から近隣のホテルに電話をかけ、宿泊客に事情を説明して移ってもらいます。移動の手配と差額の負担に加え、その宿泊客の次の予約は戻ってこないかもしれません。 外れを恐れて枠を小さくすると、今度は空室が残ります。
(d)1件の判断に時間がかかる。 1件6分でも月540件で54.0時間です。2日前の見直しは毎日の業務に重なり、忙しい日ほど見直しが省かれて、前回の枠のまま当日を迎えます。
- 【自動】 毎朝5時、PMSから予約と、その作成・変更・取消の履歴を分析用の場所へ書き出す
- 【自動】 Python が、見直す宿泊日の予約を、その時点の状態に組み立て直す
- 【自動】 予約1件ごとに、直前の取消または不泊になる確率を見込む
- 【自動】 宿泊日・客室タイプごとに確率を足し上げ、空く室数の分布を出す
- 【自動】 売り越しの室数ごとに「あふれる確率」を計算し、上限に収まる最大の室数を案にする
- 【自動】 上限の規則(客室タイプごとの最大室数、売り越さない日の一覧)を当てはめる
- 【自動】 案と、案の根拠になった予約の内訳を、宿泊日ごとの一覧に書き出す
- 【人】 レベニューマネージャーが一覧を見て、案をそのまま使うか、直すかを決める
- 【人】 予約課が、決まった室数をサイトコントローラーで調整する
- 【自動】 宿泊日が過ぎたら、実際の取消・不泊の数と案の数を突き合わせて記録する
8番目が、この設計の分かれ目です。 案は出しますが、サイトコントローラーの在庫を自動で書き換えることはしません。 地域の催しや近隣のホテルの空き具合のように、予約の記録に載らない事情を知っているのは担当者だけだからです。
5番目で平均ではなく確率で枠を決めているのも、意図してのことです。 「平均で6室空く」から6室売り越すと、空きが5室以下だった日はすべてあふれます。あふれる確率という形にしておけば、上限を経営と話し合って決められます。
02今回想定するシステム構成
PMS(予約・変更・取消の履歴、客室タイプ、プラン、経路) │ 毎朝5時に、前日までの履歴を分析用の場所へ書き出し ▼【トリガー】定時実行 Python(pandas) ├──▶ 予約を見直しの時点の状態に組み立て直す ├──▶ 予約ごとの特徴を作る(氏名・国籍などの列は読まない) ▼ scikit-learn(HistGradientBoostingClassifier+確率の較正) │ 予約1件ごとの「直前の取消または不泊」の確率 ▼ Python ── 宿泊日・客室タイプごとに足し上げ/あふれる確率の計算/上限の規則 ▼ 売り越しの枠の案の一覧(宿泊日別・客室タイプ別) ▼ 【レベニューマネージャーが確かめて決め、予約課がサイトコントローラーで調整】
| 役割 | 想定する製品 | 代替候補 |
|---|---|---|
| 実行環境 | Python(pandas・scikit-learn の HistGradientBoostingClassifier) | R、BigQuery ML、LightGBM |
| データの取得元 | PMSの予約・変更・取消の履歴の書き出し | PMSのAPI(提供されている場合) |
| 一覧の出力先 | 営業部の共有フォルダの一覧(宿泊日別のシート) | 社内のダッシュボード |
| 定時実行 | 社内のジョブ管理の仕組み | OSのタスクスケジューラ |
生成AIは使いません。 この構成で行うのは、予約の記録から確率を見込み、足し上げて枠を計算することです。宿泊客の氏名や連絡先を外部の生成AIに渡す場面を、最初から作りません。 案の理由も、内訳の数字を並べるだけで足ります。
サイトコントローラーとPMSには書き込みません。 案はあくまで担当者が決めるための材料で、在庫の調整はいまと同じく予約課が手で行います。 書き込みの経路を作らないことで、計算の誤りがそのまま販売に出ることを防ぎます。
モデルに HistGradientBoostingClassifier を選ぶのは、欠けた値をそのまま扱えるからです。 公式の説明では、学ばせるときに分かれ目ごとに欠けた値を左右どちらへ送るかを学ぶとされています。法人契約の予約には「契約先の過去の取消率」があり、OTAの個人予約には無い、 というように、経路で埋まる列が違います。0で埋めると「記録が無い」と「取消がゼロ」の区別が消えます。
カテゴリの列もそのまま入ります。 categorical_features の既定は "from_dtype" で、表の列をカテゴリの型にしておけば、予約経路、プラン、客室タイプ、決済の方法を数値に直さずに渡せます。 カテゴリの数は max_bins 以下である必要があるとされているので、OTAのプラン名のように数が多い列は、取消の決まりで束ねてから渡します。
03どうやって実装するのか
処理の起点を決める
毎朝5時の定時実行を起点にします。 夜間の予約・取消がPMSに確定した後で、予約課が出社する前に一覧ができている時刻です。予約が入るたびに動かす形にはしません。 枠は1日1回決めれば足り、予約のたびに案が変わると、担当者がどの数字を信じればよいか分からなくなります。
毎朝作る一覧は、見直しの対象の宿泊日だけです。 その朝に30日前・7日前・2日前に当たる宿泊日の3日分を出します。月の初めにまとめて作る形にしないのは、予約の中身が日々変わるからです。 30日前の時点の案は、7日前には古くなっています。
モデルの学び直しは月に1回です。 毎月1日の朝、前月までの24か月分の予約で学ばせ直し、学び直した後のモデルが、前のモデルより当たっているかを確かめてから入れ替えます。 当たり方が悪くなっていれば、前のモデルを使い続けて担当者に知らせます。
入力データを集める
| データ | 中身 | 取得元 |
|---|---|---|
| 予約 | 宿泊日、泊数、客室タイプ、室数、人数、プラン、予約経路、決済の方法、予約を受けた日時 | PMS |
| 予約の履歴 | 作成・変更・取消の日時と、変わった項目 | PMS |
| 宿泊の結果 | チェックインの有無、不泊の扱い、取消の日時 | PMS |
| 法人契約 | 契約先ごとの過去の取消・不泊の率 | PMS(契約先のマスタ) |
| 暦 | 曜日、祝日、連休、大型の催しの日(担当者が登録) | 営業部で用意する表 |
| 上限の規則 | 客室タイプごとの売り越しの最大室数、売り越さない日、あふれる確率の上限 | 営業部で用意する表 |
質を決めるのは、予約の履歴です。 PMSの予約一覧は、たいていいまの状態しか出しません。30日前に見直すときの予約は、その時点では取り消されていなかったのに、いまの一覧では「取消」になっています。履歴が無いと、見直しの時点の状態を組み立て直せません。 書き始める前に、PMSが変更の日時を残しているかを確かめてください。
暦の表は担当者が作ります。 近くの会場の催しや学会の日程は、予約の記録からは分かりません。ここに載っていない催しの日は、モデルが去年と同じ傾向で見込みます。 新しい催しを知ったら、表に1行足すのが担当者の仕事になります。
読まない列も決めておきます。 氏名、連絡先、国籍、生年月日は書き出しの段階で外します。国籍で取消の傾向を見込むと、確率の数字がそのまま宿泊客の扱いの差につながりかねません。 見込みに要るのは、予約の条件だけです。
データの取得方法を決める
PMSから、予約と予約の履歴をそれぞれ書き出します。 多くのPMSは帳票やデータの書き出しの機能を持っていますが、項目と形式は製品ごとに違います。履歴が書き出せない場合は、毎朝の予約一覧をそのまま日付付きで保存し、翌日以降の差から履歴を作ります。 この場合、学ばせられる記録がたまるまで、書き出しを始めてから1年ほど待つことになります。
| 取るもの | どこから | 何に使うか |
|---|---|---|
| 予約の条件 | 予約の書き出し | 予約ごとの特徴 |
| 作成・変更・取消の日時 | 履歴の書き出し | 見直しの時点の状態の組み立て直し |
| チェックインの有無 | 宿泊の結果 | 学ばせるときの答え |
| 契約先の取消率 | 契約先のマスタ | 法人予約の特徴 |
| 催しの日 | 暦の表 | 宿泊日の特徴 |
答えの付け方を先に決めます。 この構成で見込むのは、宿泊日の2日前以降の取消と、連絡の無い不泊です。2日前より前の取消は、2日前の見直しで反映できるので含めません。30日前の見直しでは「30日前から当日までの取消と不泊」、7日前では「7日前から」と、見直しの時点ごとに答えを付け直します。 時点ごとにモデルを分けるか、時点を特徴の1つにするかは、記録の量で決めます。
AIへ渡す前に整形する
- 見直しの時点への組み立て直し … 履歴を見て、30日前・7日前・2日前の時点で生きていた予約だけを残し、その時点のプランと人数に戻します
- リードタイムの計算 … 予約を受けた日から宿泊日までの日数と、見直しの時点から宿泊日までの日数の2つを作ります
- 変更の回数 … 見直しの時点までに、日付・人数・客室タイプが何回変わったかを数えます
- プランの束ね … OTAごとにばらばらなプラン名を、「無料で取り消せる」「期限付きで取り消せる」「返金不可」の3つに束ねます
- 団体の除外 … 15名以上の団体の予約は外し、担当者の判断に残します
- 列の型 … 予約経路・プラン・客室タイプ・決済の方法をカテゴリの型にします
- 重複の確認 … 同じ予約がOTAと自社の両方で取り込まれていないかを、予約番号の対応表で確かめます
1番目を省くと、モデルは未来を見て学びます。 いまの一覧で学ばせると、30日前の時点ではまだ分からなかった「変更が3回あった」が特徴に入り、検証ではよく当たるのに、本番ではまったく当たらないモデルになります。 この構成でいちばん起きやすい失敗です。
5番目で団体を外すのは、取消の決まりが違うからです。 宿泊約款の取消料の表は、個人と、15名から99名、100名以上の団体に分かれています。団体の一部の取消には、取消料のかからない人数の枠も書かれています。 個人と同じモデルに入れると、団体の1件で客室タイプの見込みが大きく振れます。
AIに処理させる
させるのは、予約1件ごとに「直前に取り消されるか、来ないか」の確率を出すことだけです。 枠の計算と上限の規則は、確率を受け取った後の Python の側で行います。
| 見るもの | 扱い方 | 判断できないときの扱い |
|---|---|---|
| リードタイム | 予約を受けた日から宿泊日までの日数 | 予約日が欠けていれば欠けた値のまま渡す |
| プラン | 3つに束ねた取消の決まり | 束ねられないプランは「その他」 |
| 予約経路 | OTA・自社サイト・旅行会社・法人契約 | 経路が空なら欠けた値 |
| 人数・泊数・室数 | そのまま | - |
| 変更の回数 | 見直しの時点までの回数 | - |
| 決済の方法 | 事前決済・現地払い | 不明なら欠けた値 |
| 宿泊日の性質 | 曜日、祝日、連休、催しの日 | 暦に無い日は平日扱い |
確率は較正してから使います。 足し上げて室数にするので、「0.2と出た予約のうち、実際に2割が空いた」という意味の確率でなければ、足した数がずれます。 較正には CalibratedClassifierCV を使い、公式の説明では、十分なデータ(約1,000件超)があれば isotonic は sigmoid と同等以上とされています。客室タイプ別に見ると件数の少ないタイプがあるため、最初は sigmoid にします。
足し上げは、確率の平均ではなく分布で行います。 予約1件ごとに「空く・空かない」の2通りがあり、確率がそれぞれ違うので、空く室数が0室、1室、2室……になる確率を順に計算します。 売り越しを k 室にしたとき、空く室数が k 室より少なければあふれます。k を1室ずつ増やし、あふれる確率が上限を超える手前で止めた k が案です。
空く室数の分布 dist[0..n] を 1件ずつ畳み込む
dist = [1.0]
for p in 予約ごとの確率:
dist = [dist[i]*(1-p) + dist[i-1]*p for i in 0..len(dist)]
売り越し k 室のとき あふれる確率 = dist[0] + dist[1] + ... + dist[k-1]
案 = あふれる確率 ≦ 上限 を満たす最大の k(上限の規則で頭を押さえる)
| させないこと | 理由 |
|---|---|
| 売り越しの室数の決定 | 予約の記録に載らない事情がある。担当者が決める |
| 個々の予約の取消・扱いの変更 | 確率は足し上げて使うもの。宿泊客の扱いに使わない |
| 在庫の書き換え | 計算の誤りがそのまま販売に出る |
| 団体の見込み | 取消の決まりが違う。担当者の判断に残す |
| 暦に無い催しの推測 | 担当者が表に足す |
2行目がいちばん大事です。 「この予約は来ない確率が高いから先に取り消す」という使い方は、宿泊約款の決まりと合いません。確率は、宿泊日ごとの空き室数を見込むための部品です。
指示内容を固定する
この構成は生成AIを使わないため、プロンプトはありません。 代わりに、学習・計算・一覧の作成を決める設定を、ひとつのファイルにまとめます。モデルに「何を見て、何を見ないか」を伝えるのは、この設定です。
【見込む先】
target: 見直しの時点から宿泊日までの取消、または連絡の無い不泊(=1)
見直しの時点: 宿泊日の30日前・7日前・2日前
学習期間: 前月までの24か月 検証: 直近3か月
【対象から外す予約】
- 15名以上の団体、社員・関係者の利用、無料の招待
- 見直しの時点ですでに取り消されている予約
【読まない列(書き出しの段階で除く)】
- 氏名、連絡先、住所、国籍、生年月日
- 予約の備考欄の自由記述
【モデル】
estimator: HistGradientBoostingClassifier
categorical_features: from_dtype
calibration: CalibratedClassifierCV(method="sigmoid")
入れ替えの条件: 検証の期間で、前のモデルより較正曲線のずれが小さいこと
【枠の計算】
あふれる確率の上限: 5%(経営会議で決めた値)
客室タイプごとの売り越しの最大: シングル6室、ダブル4室、ツイン3室、その他1室
売り越さない日: 暦の表で「売り越し不可」とした日
近隣の振替先の空きが無いと担当者が登録した日: 案を0室にする
【一覧に載せる内容】
- 宿泊日、客室タイプ、予約室数、販売できる室数、案の売り越し室数
- 空く室数の見込み(中央の値と、90%の範囲)
- プランの内訳(無料取消・期限付き・返金不可の室数)、経路の内訳
- 前回の見直しの案と、担当者が決めた室数
あふれる確率の上限を設定ファイルに書くのが大事です。 この数字はモデルが決めるものではなく、振替の手間と空室の損を比べて、経営が決める値です。 担当者の手元で変えられないようにし、変えたときは日付と理由を残します。
「近隣の振替先の空きが無い日は0室」を入れているのは、あふれたときの手当てが前提だからです。 宿泊約款では、契約した客室を提供できないときは、宿泊客の了解を得て同じ条件の宿泊施設をあっせんするとされています。振替先が無い日に売り越すと、その手当てができません。
出力形式を固定する
一覧は表で出し、同じ内容を JSON でも残します。 表は担当者が読むため、JSON は宿泊日が過ぎた後の突き合わせのためです。
{
"run_at": "2026-10-14T05:00:00+09:00",
"stay_date": "2026-11-13",
"checkpoint": "d-30 | d-7 | d-2",
"room_type": "single",
"booked_rooms": 0,
"sellable_rooms": 0,
"expected_vacancy": { "median": 0, "p05": 0, "p95": 0 },
"plan_mix": { "free_cancel": 0, "deadline_cancel": 0, "non_refundable": 0 },
"channel_mix": { "ota": 0, "direct": 0, "agent": 0, "corporate": 0 },
"overbook_proposal": 0,
"walk_probability_at_proposal": 0.0,
"capped_by": "none | room_type_max | no_oversell_day | no_walk_option",
"model_version": "",
"decided_rooms": null,
"decided_by": ""
}
1つ目の理由は、案と決定を同じ行に残せることです。 overbook_proposal は計算が埋め、decided_rooms は担当者が埋めます。宿泊日が過ぎた後、案どおりにしていたらどうなったか、担当者の判断でどうなったかを、同じ行で比べられます。
2つ目は、capped_by で案が小さくなった理由が分かることです。 確率の計算では5室売り越せるのに、客室タイプの最大で3室に押さえられた、という場合に、担当者は計算の結果と規則の結果を分けて読めます。
| 列 | 担当者が見ること |
|---|---|
plan_mix | 返金不可が多い日は空きが少ない。案が小さくても不思議ではない |
expected_vacancy の幅 | 幅が広い日は予約の中身がばらついている。案を控えめに使う |
walk_probability_at_proposal | 上限の5%にどれだけ近いか |
capped_by | 規則で押さえた日は、規則を見直す材料になる |
expected_vacancy の幅を出すのは、平均だけを見せないためです。 中央の値が6室でも、5%の側が2室なら、6室売り越した日は高い確率であふれます。幅を見れば、案がなぜ6室ではなく3室なのかが分かります。
システムへ連携する
| つなぎ先 | 方式 | 内容 |
|---|---|---|
| PMS | データの書き出し(読み取りのみ) | 予約、予約の履歴、宿泊の結果、契約先のマスタ |
| 分析用の場所 | ファイルの保存 | 毎朝の書き出しと、見直しの時点の状態の保存 |
| 営業部の共有フォルダ | 一覧の書き出し | 宿泊日別・客室タイプ別の案 |
| サイトコントローラー | 連携しない | 予約課が手で調整する |
| 社内のチャット | 通知 | 一覧ができたこと、モデルを入れ替えなかったこと |
PMSへは書き込みません。 予約の確率をPMSの予約画面に出すと、フロントや予約課がそれを見て宿泊客の扱いを変えるおそれがあります。 一覧は営業部の共有フォルダにだけ置き、見られる人をレベニューマネージャーと予約課に限ります。
担当者が決めた室数は、一覧の decided_rooms の列に手で入れてもらいます。 サイトコントローラーで調整した数と同じ数を入れるだけです。この1列が、翌月の振り返りの材料になります。
人が確認する
人が見るのは、毎朝の3日分の一覧です。 1日あたり3宿泊日 × 6客室タイプ = 18行で、そのうち案が前回と変わった行と、capped_by が付いた行を先に見ます。
- 前回から案が変わった行を見る …
plan_mixとchannel_mixの変化で、理由が説明できるかを確かめます - 暦の表の漏れを確かめる … 一覧の宿泊日に、表に載っていない催しや工事が無いかを思い出します
- 振替先の空きを確かめる … 2日前の見直しでは、近隣のホテルの空き具合を見て、振替先が無ければ0室にします
- 室数を決めて記録する … 案と違う室数にしたら、
decided_roomsと短い理由を残します
3番目を省かないでください。 案はあふれる確率を5%に収めた数字ですが、5%はゼロではありません。 あふれた日に振替先が無ければ、宿泊約款の手当てができません。
目標は、1件あたりならして2分です。 前回と案が変わらず、規則で押さえられてもいない行は数秒で終わります。案が大きく変わった行と、2日前の行だけに時間を使います。
例外に対処する
| 起きること | 対応 |
|---|---|
| PMSの書き出しが朝までに届かない | 前日の一覧を「古い」と印を付けて残し、担当者に知らせる。案は出さない |
| 履歴が欠けた予約がある | その予約は確率を出さず、空かないものとして数える(案が控えめになる側に倒す) |
| 新しいプラン・経路が出てきた | 束ねの表に無ければ「その他」として扱い、一覧に件数を出す |
| 客室タイプの予約が少なすぎる | 予約が10室未満の日は案を出さず「件数不足」と書く |
| 学び直したモデルが前より当たらない | 入れ替えず、前のモデルを使い続けて知らせる |
| 大型の催しで予約が急に増えた | 暦の表に載っていなければ、担当者が載せて翌朝の一覧に反映する |
| 同じ予約が二重に取り込まれた | 予約番号の対応表で寄せ、二重に数えない |
| 当日あふれた | 振替の記録を残し、翌月の振り返りで、その日の案と決定を確かめる |
2行目を「空かない」側に倒しているのは、誤りの向きを決めるためです。 分からない予約を「空く」側に数えると、案が大きくなり、あふれる側に外れます。外れるなら、空室が残る側に外れるようにします。
最後の行は、責める材料ではありません。 あふれる確率5%で枠を決めていれば、20回に1回ほどはあふれる日がある設計です。 振り返りで見るのは、その日の予約の中身が普段と違っていたか、暦の表に漏れが無かったかです。
記録を残す
- 毎朝のPMSの書き出しと、見直しの時点に組み立て直した予約の一覧
- 予約ごとの確率と、使ったモデルの版
- 宿泊日・客室タイプごとの案、あふれる確率、
capped_by - 担当者が決めた室数と、案と違うときの理由
- 宿泊日が過ぎた後の、実際の取消・不泊の室数と、振替の有無
- 設定ファイルの変更の履歴(あふれる確率の上限、客室タイプの最大)
4つ目と5つ目を並べて残すのが、この構成の振り返りの土台です。 案どおりなら何室あふれ、何室空いたか。担当者の判断ではどうだったか。3か月分たまると、案が小さすぎる客室タイプと大きすぎる客室タイプが分かります。
予約ごとの確率は、営業部の外に出しません。 保存の期間を決め、期間を過ぎたら宿泊日・客室タイプごとの集計だけを残して消します。
04実装レベルの3段階
最小構成では、見直しの時点の状態が作れません。 いまの一覧から率を出すので、30日前・7日前の案には使えません。 2日前の目安を確かめるための段階です。 半自動化で、1件6分が3分程度になります。 集計と去年との見比べは無くなりますが、空きの見込みから室数を決める計算が担当者の手に残ります。本格構成で2分になり、この段階が本記事の想定です。 差が大きいのは、あふれる確率と室数の関係を、担当者が毎回頭の中で計算していたからです。 段階を飛ばさないでください。 半自動化の一覧を2か月見ると、確率の当たり方の悪い客室タイプと経路が先に分かります。そこを直してから枠の計算を足すほうが、案が担当者に信じてもらえます。
05工数削減シミュレーション
導入後 540件 × 2分 ÷ 60 = 18 時間/月
自社条件で導入効果を整理したい方へ
このユースケースを自社に当てはめた場合の前提値と削減見込みを、業務ヒアリングをもとに整理します。
06向いている企業・向いていない企業
- 客室が100室を超え、OTA・自社サイト・旅行会社・法人契約の複数の経路から予約を受けている都市型のホテル。満室に近い日が月に何日もあり、直前の取消と無断の不泊で空いた部屋を売り越しで埋めているが、その枠を担当者の経験で決めている場合。予約の作成・変更・取消の日時がPMSに2年以上残っている場合。
- 客室が数十室で、予約の大半が常連か団体で、取消の傾向を担当者が把握できている旅館。満室になる日がほとんど無く、売り越しをする場面が無い施設。予約の変更の履歴が残らず、いまの状態しか取り出せないPMSの場合。なお、売り越しをするかどうか、あふれたときに誰をどこへ振り替えるかの判断と、宿泊客への説明は、この構成では代替できません。
07最小構成で試す方法
- PMSから、過去1年分の予約と、取消の日時・チェックインの有無を書き出す
- 1年分を、宿泊日の2日前に生きていた予約だけに絞る(変更の履歴が無ければ、取消の日時だけで判定する)
- 表計算で、プラン(3つに束ねる)× 予約経路ごとに、2日前以降の取消と不泊の率を出す
- 直近の満室に近かった宿泊日を10日選び、その日の2日前の予約に、3番目の率を当てて足し上げる
- 足し上げた空きの見込みを、実際に空いた室数と、その日に担当者が決めた売り越しの室数と比べる
10日は必ずやってください。 モデルを作る前に、「予約の中身で空きの見込みが変わるのか」を確かめます。 プランと経路の掛け合わせだけでも、去年の同じ曜日の件数より当たるなら、構成は有効です。
| 出てきた内容 | 判断 |
|---|---|
| プランと経路で取消の率が大きく違う | モデルに進む。 予約の中身に手がかりがある |
| 率に違いがほとんど無い | 取消は宿泊日の性質で決まっている。暦の表から作り直す |
| 2日前の予約を組み立て直せない | PMSの書き出しが先。 毎朝の一覧の保存から始める |
3行目が出ることは珍しくありません。 失敗ではなく、担当者の経験則が件数でしか比べられていなかった理由が1つ分かったということです。 その場合は、毎朝の予約一覧を日付付きで保存するところから始めてください。
08実装時につまずきやすいポイント
| 問題 | 対策 |
|---|---|
| 検証ではよく当たるのに本番で外れる | 見直しの時点の状態で学ばせる。 いまの一覧で学ばせない |
| 足し上げた空きが実際とずれる | 確率を較正する。較正曲線で、0.2の予約が2割空いているかを見る |
| 平均で枠を決めてあふれる | 分布で計算し、あふれる確率の上限で止める |
| プラン名が多すぎて学べない | 取消の決まりで3つに束ねる |
| 団体の1件で見込みが振れる | 15名以上は外し、担当者の判断に残す |
| 法人予約の列が空で0が入る | 欠けた値のまま渡す。0で埋めない |
| 催しの日に外れる | 暦の表を担当者が足す。表に無い日は去年と同じ傾向で見込むと伝えておく |
| 確率がフロントに知られる | PMSに書き込まない。一覧の置き場所と見られる人を限る |
| 案をそのまま在庫に入れてしまう | 自動の書き込みを作らない。担当者が決めて手で調整する |
| 学び直したモデルが悪くなる | 入れ替えの条件を決め、満たさなければ前のモデルを使う |
| 上限の5%を担当者が変える | 設定ファイルで管理し、変更の履歴を残す |
| 振替先が無い日に売り越す | 2日前の見直しで振替先の空きを確かめ、無ければ0室にする |
上の3行が、この構成の失敗のほとんどです。 どれも「数字は出るが、意味が違う」という形で起きます。時点、較正、分布の3つを押さえてあるかで、案が使えるかが決まります。
下の2行は、運用が始まってから効いてきます。 上限を現場の判断で動かすと、あふれた日と空いた日の振り返りが成り立ちません。振替先の確認は、案の外にある人の仕事として残してください。
09セキュリティ・AIガバナンス上の注意点
この構成で扱うデータ: 予約の条件(宿泊日、客室タイプ、人数、プラン、経路、決済の方法)、予約の変更・取消の履歴、宿泊の結果、法人契約の先の名前と取消の率です。
- 個人を特定する列を書き出さない … 氏名・連絡先・住所・生年月日は、PMSから書き出す段階で外します。予約番号だけでつなぎ、予約番号と氏名の対応は分析の側に持ちません
- 国籍や属性で見込まない … 国籍、性別、年齢を特徴に入れると、確率の数字が特定の宿泊客の扱いの差につながりかねません。 宿泊約款は、旅館業法第5条に挙げる場合以外に宿泊を拒むことを意味しないと断っています。見込みは予約の条件だけで行います
- 確率を個々の予約の扱いに使わない … 確率の高い予約を先に取り消す、確認の電話を集中してかける、といった使い方はしません。取消を扱えるのは、宿泊約款に書かれた場合だけです
- あふれたときの手当てを先に決めておく … 宿泊約款では、契約した客室を提供できないときは同じ条件の宿泊施設をあっせんし、あっせんできないときは取消料に相当する補償料を払うとされています。売り越しは、この手当てを引き受けることを前提にした判断です。 振替先の一覧と手順を、フロントと共有してください
- 生成AIに予約の記録を渡さない … この構成は生成AIを使いません。理由の文を作るために予約の一覧をチャットのAIに貼り付けることも、運用の決まりで禁じます
- 法人契約の取消率を社外に出さない … 契約先ごとの取消・不泊の率は、営業上の情報です。一覧には契約先の名前を出さず、「法人契約」の内訳だけを出します
誤りが起きた場合のリスクは、売り越しすぎて宿泊客をあふれさせることと、控えすぎて空室を残すことの2つです。 前者は宿泊客の旅行や出張に直接ひびき、後者は売上が減るだけです。だから例外の扱いは、迷ったら空室が残る側に倒す設計にしています。
10まず何から始めるか
1週目:PMSの書き出しを確かめる
PMSから、予約・予約の履歴・宿泊の結果を書き出せるかを確かめます。変更の日時が残っているかが最初の分かれ目です。 残っていなければ、毎朝の予約一覧を日付付きで保存する仕組みを、この週のうちに始めます。
2週目:10日で試す
過去1年分で、プラン×経路ごとの2日前以降の取消と不泊の率を出し、満室に近かった10日に当てて足し上げます。実際に空いた室数と、担当者が決めた室数と並べて見ます。
3週目:あふれる確率の上限を決める
振替が1回起きたときの手間と費用、空室が1室残ったときの損を並べ、経営と上限を決めます。 あわせて、客室タイプごとの売り越しの最大と、売り越さない日の決め方を、レベニューマネージャーの経験則から書き出します。
4週目:見直しの時点の状態を作る
Python で、30日前・7日前・2日前の時点で生きていた予約を組み立て直す処理を作ります。この時点ではモデルを作らず、組み立て直した予約の数が、当時の一覧の数と合うかだけを確かめます。
2か月目: モデルで確率を出し、較正曲線で当たり方を見ます。一覧を毎朝出し、担当者は従来どおり決めながら案と並べます。3か月目以降: あふれる確率の計算と上限の規則を足し、decided_rooms を記録して、宿泊日が過ぎた後の突き合わせを毎月行います。案と担当者の判断の当たり方を3か月分比べ、客室タイプごとの最大を見直した時点で、この構成は完成です。
11関連ユースケース
12この仕組みを理解するための記事
13技術仕様の確認日・参考情報
| 確認した内容 | 情報源 | 確認日 |
|---|---|---|
HistGradientBoostingClassifier が欠けた値(NaN)をそのまま扱い、学ばせるときに分かれ目ごとに欠けた値を左右どちらへ送るかを学ぶこと。categorical_features の既定が "from_dtype" で、カテゴリの型の列をカテゴリとして扱い、カテゴリの数が max_bins 以下である必要があること。predict_proba がクラスの確率を返すこと | scikit-learn: HistGradientBoostingClassifier | 2026-10-14 |
| CalibratedClassifierCV の sigmoid と isotonic の違い。十分なデータ(約1,000件超)があれば isotonic が sigmoid と同等以上で、少ないと過学習しやすいこと。較正曲線(信頼度の図)で、予測した確率と実際の割合を比べること | scikit-learn: Probability calibration | 2026-10-14 |
| モデル宿泊約款(令和5年12月13日最終改正)で、宿泊客が連絡なく来ないときに契約を宿泊客による解除とみなせること。取消料の表が個人と15名以上の団体に分かれ、団体の一部の取消に取消料のかからない人数の枠があること。契約した客室を提供できないときは同じ条件の宿泊施設をあっせんし、できないときは取消料に相当する補償料を払うこと。宿泊の拒否が旅館業法第5条に挙げる場合以外に宿泊を拒むことを意味しないこと(観光庁の英語版で確認) | 観光庁: Terms and Conditions for Model Accommodation | 2026-10-14 |
売り越しをするかどうか、あふれる確率の上限をいくつにするかは、経営と営業部で決めてください。 自社の宿泊約款の取消料と振替の扱いは、モデル宿泊約款と違う場合があります。本記事は上記の公式情報で確認できた範囲だけを扱っています。
実装ステータス:構成例。 公開仕様に基づいて設計した構成であり、当社で実際に構築・検証したものではありません。工数の数値はモデル条件による試算です。
自社の業務に使えるAI活用候補を整理します
このユースケース(UC-1454)についてのご相談はこちらから。
