ホテルの予約・チェックアウト予定・連泊の数から、翌週の客室清掃に必要な人数を日ごとに予測してシフトの案に渡す
宿泊管理システムの予約と過去の予約・取消の動きから、翌週の日ごとのチェックアウトの室数と連泊で清掃する室数を見込み、客室清掃に必要な人数に直してシフトの案に渡します。人数の決め方が、リーダーの勘から数字になります。
- 連携・自動化
- Python
- 対象業界
- 不動産/宿泊
- 対象部門
- 人事
- 対象業務
- 集計・分析
- 主な課題
- 人手が足りない/判断に時間がかかる/属人化している
- AIで行う処理
- 予測
- 主な効果
- 判断支援/属人化解消/工数削減
- 導入難易度
- ★★★★☆
- 実装レベル
- 本格構成
- 費用感
- 個別開発(大)
- 人間の確認
- 条件付き
01導入前 / 導入後の業務フロー
- 毎週水曜、各ホテルのリーダーが宿泊管理システムで翌週の日ごとの予約の一覧を開く
- 日ごとに、チェックアウトの予定の室数と、連泊の室数を数える
- 先週の同じ曜日の様子と、近くの催しの予定を思い出し、これから入る予約を上乗せする
- 連泊の清掃を断るプランの予約を差し引く
- 部屋の種類ごとの清掃の時間を掛けて、必要な人数を電卓で出す
- 人数を表に書き、人事部へ送る
- 当日になって足りなければ、リーダー自身が清掃に入るか、休みの人に電話する
- 自動毎週水曜の朝、宿泊管理システムから翌週から2週先までの予約と、過去の予約・取消の記録を書き出す
- 自動Python が、ホテル・日ごとに、いま入っているチェックアウトと連泊の室数を数える
- 自動連泊の清掃を断るプランの予約を分け、清掃する連泊の室数を数える
- 自動過去の記録から学んだモデルで、その日までに動く分(これから入る予約と取消)を、真ん中と多めの2本で見込む
- 自動部屋の種類ごとの清掃の時間の表を掛けて清掃の分数にし、1人が1日に清掃できる分数で割って必要な人数にする
- 自動催しの予定表にある日、見込みの幅が広い日、先週の見込みから大きく変わった日に印を付ける
- 人各ホテルのリーダーが、印の付いた日だけを確かめ、人数を直すか決める
- 自動確かめた人数の表を、シフト作成の仕組みに取り込める形で書き出す
- 人人事部が勤務の希望と合わせてシフトを組み、木曜に確定する
- 自動翌週、日ごとの実際の清掃室数を記録し、見込みとの差を残す
各工程の詳しい説明を読む
- 毎週水曜、各ホテルのリーダーが宿泊管理システムで翌週の日ごとの予約の一覧を開く
- 日ごとに、チェックアウトの予定の室数と、連泊の室数を数える
- 先週の同じ曜日の様子と、近くの催しの予定を思い出し、これから入る予約を上乗せする
- 連泊の清掃を断るプランの予約を差し引く
- 部屋の種類ごとの清掃の時間を掛けて、必要な人数を電卓で出す
- 人数を表に書き、人事部へ送る
- 当日になって足りなければ、リーダー自身が清掃に入るか、休みの人に電話する
(a)上乗せが勘になっている。 3番目の「これから入る予約」は、リーダーの経験で決まっています。経験の長いリーダーのホテルは当たり、替わったばかりのホテルは外れます。 人事部から見ると、ホテルごとに人数の出し方が違います。
(b)連泊の数え方を間違えやすい。 予約の一覧には、その日に泊まっている客が並ぶだけで、連泊の何日目か、清掃を断るプランかは1件ずつ見ないと分かりません。週末の連泊の多い日ほど、数え違いが出ます。
(c)足りない日が当日に分かる。 前の週に人数を確定した後で予約が入っても、シフトには戻りません。当日の朝に足りないと分かり、チェックインの時刻までに部屋が仕上がらないことがあります。売れたはずの部屋を、清掃が終わらずに待たせることになります。
(d)余る日は見えない。 取消が多くて人が余った日は、早上がりをお願いして終わります。足りなかった日は覚えていても、余った日は記録に残らず、 上乗せの勘は多めの側にずれていきます。
- 【自動】 毎週水曜の朝、宿泊管理システムから翌週から2週先までの予約と、過去の予約・取消の記録を書き出す
- 【自動】 Python が、ホテル・日ごとに、いま入っているチェックアウトと連泊の室数を数える
- 【自動】 連泊の清掃を断るプランの予約を分け、清掃する連泊の室数を数える
- 【自動】 過去の記録から学んだモデルで、その日までに動く分(これから入る予約と取消)を、真ん中と多めの2本で見込む
- 【自動】 部屋の種類ごとの清掃の時間の表を掛けて清掃の分数にし、1人が1日に清掃できる分数で割って必要な人数にする
- 【自動】 催しの予定表にある日、見込みの幅が広い日、先週の見込みから大きく変わった日に印を付ける
- 【人】 各ホテルのリーダーが、印の付いた日だけを確かめ、人数を直すか決める
- 【自動】 確かめた人数の表を、シフト作成の仕組みに取り込める形で書き出す
- 【人】 人事部が勤務の希望と合わせてシフトを組み、木曜に確定する
- 【自動】 翌週、日ごとの実際の清掃室数を記録し、見込みとの差を残す
7番目が、この設計の分かれ目です。リーダーが見るのは14日分の全部ではありません。 印の付いていない日はそのまま通し、印の付いた日だけを、催しの事情や現場の様子と照らして直します。 全日を見直す設計にすると、40.0時間はほとんど減りません。
10番目を省かないでください。 見込みと実際の差を残さないと、第3章の(d)と同じく、どちらにずれているかが分からなくなります。
02今回想定するシステム構成
宿泊管理システム(予約・取消の記録、表の形で書き出し) │ 予約番号・到着日・出発日・部屋の種類・プラン・予約日・取消日 ▼【トリガー】毎週水曜 6:00 Python(pandas) ├──▶ 日ごとの在庫の展開(チェックアウト/連泊/清掃を断る連泊) ├──▶ 催しの予定表、祝日、部屋の種類ごとの清掃の時間の表 ▼ scikit-learn HistGradientBoostingRegressor │ loss="quantile"(quantile=0.5 と 0.8)で、これから動く分を見込む ▼ 人数への換算 ── 清掃の分数 ÷ 1人1日に清掃できる分数 ▼ 印付け ── 催しの日/幅の広い日/先週から大きく変わった日 ▼ 【リーダーが印の付いた日だけ確かめる】 ▼ シフト作成の仕組みへ必要人数の表
| 役割 | 想定する製品 | 代替候補 |
|---|---|---|
| 実行環境 | Python(pandas・scikit-learn) | R |
| 処理エンジン | scikit-learn の HistGradientBoostingRegressor(分位点の損失) | LightGBM、statsmodels の分位点回帰 |
| 集計 | Python(日ごとの在庫の展開と、人数への換算) | 宿泊管理システムの帳票 |
| データの取得元 | 宿泊管理システムの予約・取消の記録の書き出し | 宿泊管理システムのAPI |
| 結果の出力先 | シフト作成の仕組みに取り込む必要人数の表 | 人事部の共有フォルダ |
宿泊管理システムには書き込みません。 予約と取消の記録を読むだけで、部屋の販売の設定にも、客の予約にも触れません。 シフト作成の仕組みにも、取り込める形の表を渡すだけで、誰をどの日に入れるかは人事部が決めます。
見込みの中心は、scikit-learn の HistGradientBoostingRegressor です。 損失に loss="quantile" を選ぶと、quantile に指定した分位点(0から1の間)を見込みます。quantile=0.5 で真ん中、quantile=0.8 で多めの側の2つのモデルを作ります。損失には squared_error・absolute_error・gamma・poisson・quantile があり、分位点の損失はピンボール損失と呼ばれるものです。
このモデルを選ぶ理由は3つあります。 1つ目は、欠けている値をそのまま扱えることです。分かれ目ごとに、欠けた値を左右どちらに送ると良くなるかを学びます。開業から日の浅いホテルの「前年同日の値」のような空いた列を、埋めずに渡せます。2つ目は、categorical_features で曜日やホテルを区分の列として扱えることです。3つ目は、monotonic_cst で「催しの規模が大きいほど、これから入る予約も多い」という向きを決められることで、記録の少ない大きな催しの日に逆向きの見込みが出るのを防ぎます。
生成AIは使いません。 見込みも人数も数字で出し、印の理由も決まった言葉で付けます。人数を文章で考えさせると、根拠の無い上乗せが混ざります。
03どうやって実装するのか
処理の起点を決める
毎週水曜の朝6時に動かします。 シフトの確定が木曜なので、リーダーが水曜の日中に印の付いた日を確かめ、夕方までに人事部へ渡せる時刻にします。前日の夜の予約まで入った状態で書き出すため、夜間の締めの処理が終わった後にします。
見込む先は、翌週の月曜から2週先の日曜までの14日分です。 確定するのは翌週の7日分ですが、2週先の分を出しておくと、催しで人が多く要る週に、早めに勤務の希望を集め始められます。
月曜にも同じ処理をもう一度動かし、その週の見込みを出し直します。 確定したシフトとの差が大きい日だけを人事部に知らせ、追加で呼ぶ人を探す材料にします。
入力データを集める
| データ | 中身 | 取得元 |
|---|---|---|
| 予約の記録 | 予約番号、ホテル、到着日、出発日、部屋の種類、室数、プラン、予約した日、取り消した日 | 宿泊管理システムの書き出し |
| 部屋の種類ごとの清掃の時間 | チェックアウトの清掃と連泊の清掃の分数(部屋の種類ごと) | 各ホテルのリーダーが作る表 |
| 1人が1日に清掃できる分数 | 勤務の時間から、移動・リネンの補充・点検を除いた分数 | 同上 |
| 清掃を断るプランの一覧 | プランの名前と、連泊の清掃をしないことの印 | 宿泊管理システムのプランの設定 |
| 催しの予定表 | 近くの会場の催しの日と規模 | 各ホテルの営業担当がつける表 |
| 実際の清掃の記録 | 日ごとに清掃した室数(チェックアウト・連泊) | 客室係の作業表 |
質を決めるのは、予約の記録の「予約した日」と「取り消した日」です。 この2つが無いと、「8日前の時点で何室入っていて、最終的に何室になったか」が作れず、 これから動く分を学ばせることができません。宿泊管理システムの書き出しに、この2つの列が含まれるかを最初に確かめます。
清掃の時間の表は、リーダーが実際に測って作ります。 部屋の種類ごとに、チェックアウトの清掃と連泊の清掃を数回ずつ測り、平均を置きます。ここが実態とずれていると、室数の見込みが当たっても人数が外れます。
データの取得方法を決める
宿泊管理システムの帳票の機能で、予約の記録を表の形で書き出します。宿泊管理システムによって、書き出しの方法と列の名前が違います。 API を持つものなら定時に取りに行き、持たないものは帳票を定時に書き出す設定にして、共有フォルダに置かれたファイルを読みます。
| 取るもの | どこから | 何に使うか |
|---|---|---|
| 翌週から2週先の到着・滞在の予約 | 予約の記録(取消されていないもの) | いま入っている室数 |
| 過去2年分の予約と取消 | 予約の記録(取消も含む) | 「何日前の時点で何室、最終で何室」の組を作る |
| 過去の実際の清掃室数 | 客室係の作業表 | 最終の室数の答え合わせ |
| 清掃の時間と1人の分数 | リーダーの表 | 人数への換算 |
| 催しの予定 | 営業担当の表 | 特徴の列と、印付け |
過去の分は、取消も含めて取ります。 取消された予約を除いて書き出すと、「8日前には入っていたが、後で取り消された」という動きが消え、 取消の多い日を少なめに見込みます。
AIへ渡す前に整形する
- 予約を日ごとに展開する … 到着日から出発日の前日までを1泊ずつに分け、出発日を「チェックアウトの日」にします。連泊の2日目以降の泊まりを「連泊の清掃」にします
- 清掃を断る連泊を分ける … プランの一覧で、連泊の清掃をしない予約を数えから外します。ただし、何泊かに1回は清掃に入る決まりのプランは、その日だけ数えに戻します
- ある時点での室数を作る … 過去の各日について、「到着の14日前の時点で、取り消されずに入っていた室数」「13日前の時点で…」と、日数前ごとの数を作ります
- 学ばせる組を作る … 「何日前か」「その時点の室数」「曜日」「ホテル」「祝日・連休」「催しの有無と規模」「前年の同じ曜日の最終の室数」を特徴に、最終の室数からその時点の室数を引いた値(これから動く分)を答えにします
- 異常な日を外す … 休館した日、大きな団体の貸し切り、宿泊管理システムの入れ替えの前後は、学ばせる組から外します
- 検証の分け方を決める … 時系列を崩さないよう
TimeSeriesSplitで、過去で学んで後の期間で確かめる組を作ります
4番目で、最終の室数そのものを答えにしないでください。 これから動く分を答えにすると、いま入っている室数がそのまま土台になり、 モデルが外れても大きくは崩れません。
1番目で、予定より早い出発と延泊を答えに入れておきます。 予約の記録の出発日は、最後に更新された値です。客が1泊早く発った日は、チェックアウトの清掃が前の日に移ります。 答えには客室係の作業表の実際の清掃室数を使い、予約から数えた最終の室数との差を別の列に残します。この差が大きいホテルは、早い出発の多い客層だということで、その割合も特徴の列に足します。
6番目で gap を使います。 TimeSeriesSplit の gap は、学ばせる期間の終わりと確かめる期間の間に空ける数です。同じ到着日の別の時点の組が両側に入ると、答えが漏れて当たりすぎます。 少なくとも14日分を空けます。
AIに処理させる
させるのは、ホテル・日・清掃の種類ごとに、これから動く室数を真ん中と多めの2本で見込むことだけです。 人数への換算と印付けは、決まった計算で行います。
| 見込むもの | 使うもの | 判断できないときの扱い |
|---|---|---|
| チェックアウトの室数(これから動く分) | 日数前、いまの室数、曜日、ホテル、催し | 学ばせた範囲を外れる日は low_history |
| 清掃する連泊の室数(これから動く分) | 同上と、清掃を断るプランの割合 | 同上 |
| 多めの側との幅 | 分位点0.8と0.5の差 | 幅が真ん中の3割を超える日は wide |
右端の列が、人が見る日を決めます。 low_history は、開業したばかりのホテルや、過去に例の無い大きな催しの日です。モデルの見込みを信じる根拠が薄い日だけを、リーダーに回します。
| させないこと | 理由 |
|---|---|
| 誰をどの日に入れるかの決定 | 勤務の希望と労働時間の管理は人事部が行う |
| 清掃の時間の表の書き換え | リーダーが実測で決める |
| 確定したシフトの自動の変更 | 働く人の予定に直接かかわる |
| 予約の販売の調整 | 別の仕事。この構成は予約の結果を受け取るだけ |
| 催しの規模の推測 | 営業担当の表にある値だけを使う |
3行目がいちばん起きやすい失敗です。 月曜の見込みの出し直しで人数が減ったからといって、確定したシフトを自動で減らすと、働くつもりで予定を空けていた人の勤務が前日に消えます。 出し直しの結果は、人事部への知らせにとどめます。
指示内容を固定する
この構成は生成AIを使わないので、プロンプトの代わりに、モデルの設定と換算の規則を書いておきます。
【モデル】
- HistGradientBoostingRegressor(loss="quantile", quantile=0.5) 真ん中
- HistGradientBoostingRegressor(loss="quantile", quantile=0.8) 多めの側
- categorical_features = ["hotel", "weekday", "room_type"]
- monotonic_cst = {"event_scale": 1} 催しの規模が大きいほど、これから動く分も大きい向き
- 目的変数 = 最終の室数 − その時点の室数(これから動く分)
- 清掃の種類ごと(checkout / stayover_clean)に別のモデル
【換算の規則】
- 見込みの室数 = その時点の室数 + これから動く分(負なら取消が多い)
- 見込みの室数は 0 以上、その日の販売できる室数以下に収める
- 清掃の分数 = Σ 部屋の種類ごとの室数 × 清掃の時間
- 必要な人数 = 清掃の分数 ÷ 1人1日に清掃できる分数(切り上げ)
- 真ん中の人数 = 確定のシフトの目安、多めの人数 − 真ん中の人数 = 呼べたら呼ぶ人
【印を付ける条件】
- low_history:そのホテル・曜日で学ばせた組が 20 未満、または催しの規模が過去の最大を超える
- wide:多めの室数 − 真ん中の室数 が、真ん中の 3 割を超える
- event:催しの予定表に載っている日
- jump:先週の同じ日の見込みから、人数が 2 人以上変わった
- 印の無い日は、リーダーの確認なしで人事部へ渡す
「販売できる室数以下に収める」を書いておかないと、催しの日に満室を超える見込みが出ます。 モデルは室数の上限を知りません。上限は規則の側で決めます。
monotonic_cst の向きは、学ばせる前に記録で確かめます。 大きな催しの日は、早くから予約が埋まって直前に入る分がかえって少ないホテルもあります。向きの制約が実態と逆だと、見込みが一方に偏ります。 制約を付けた場合と付けない場合の両方で、確かめる期間の外れ方を比べてから決めます。
出力形式を固定する
ホテル・日ごとに、次の形のJSONを作り、表にしてシフト作成の仕組みへ渡します。
{
"hotel": "",
"date": "",
"checkout_rooms": { "on_books": 0, "p50": 0, "p80": 0 },
"stayover_clean_rooms": { "on_books": 0, "p50": 0, "p80": 0 },
"cleaning_minutes": { "p50": 0, "p80": 0 },
"staff_needed": { "p50": 0, "p80": 0 },
"flags": ["low_history | wide | event | jump"],
"model_version": "",
"leader_override": { "staff": null, "reason": "" }
}
1つ目の理由は、on_books と p50 を並べて見せられることです。 いま入っている室数と、見込みの室数の差が、そのまま「これから動く分」です。リーダーは、この差が現場の感覚と合うかを見れば足ります。
2つ目は、p50 と p80 を分けて持てることです。 シフト作成の仕組みには staff_needed.p50 を必要人数として渡し、p80 との差を「呼べたら呼ぶ人」の枠として別の列で渡します。 1本の数字にすると、どちらに寄せたかが後から分かりません。
3つ目は、leader_override で直した記録が残ることです。 リーダーが人数を直したら、ここに人数と理由を書きます。シフトに渡るのは直した後の値で、モデルの値も残ります。 どちらが当たったかを、翌週に比べられます。
システムへ連携する
| つなぎ先 | 方式 | 内容 |
|---|---|---|
| 宿泊管理システム | 帳票の定時の書き出し、またはAPI | 予約と取消の記録 |
| 客室係の作業表 | 表の読み取り | 日ごとの実際の清掃室数 |
| 催しの予定表 | 表の読み取り | 催しの日と規模 |
| リーダーの確認の表 | 表の書き出しと読み取り | 印の付いた日と、直した人数・理由 |
| シフト作成の仕組み | 必要人数の表の取り込み | 日ごとの真ん中の人数と、呼べたら呼ぶ人の枠 |
シフト作成の仕組みには、人数の表を渡すだけです。 取り込みは人事部の担当者が行い、取り込んだ後に誰を入れるかは、勤務の希望と労働時間を見て人が決めます。 必要人数の列だけを自動で書き換えるAPIがあっても、確定したシフトに触れる経路は作りません。
モデルの学ばせ直しは、月に一度、別の処理として動かします。 毎週の見込みは、その月に決めた版のモデルで出します。学ばせ直した版は、直近の8週を確かめる期間にして前の版と外れ方を比べ、良くなっていたときだけ切り替えます。 毎週学ばせ直すと、見込みが変わった理由が記録の変化なのかモデルの変化なのか、リーダーにも人事部にも分からなくなります。
人が確認する
人が見るのは、印の付いた日だけです。 印の無い日はそのまま人事部へ渡ります。14日分の全部を開く設計にすると、第10章の10.0時間には収まりません。
eventとlow_historyを先に見る … 催しの日と、記録の少ない日です。営業担当に、催しの客がこのホテルに来るかを確かめますwideを確かめる … 見込みの幅が広い日です。真ん中で組み、呼べたら呼ぶ人を多めに確保しますjumpを確かめる … 先週から人数が大きく変わった日です。団体の予約や大口の取消が入っていないかを、予約の一覧で見ます- 直したら理由を書く …
leader_overrideに人数と理由を残します - 翌週に、見込みと実際の差を見る … 外れた日の印と理由を読み、次の確認の参考にします
確認の期限は水曜の15時に置きます。 それを過ぎた日は第7章の例外処理のとおり「未確認」として渡し、人事部はシフトを組みながら必要ならリーダーに電話で確かめます。
1番目の催しの日は、モデルより人の知っていることのほうが確かなことがあります。 会場の催しでも、客層によっては近くの別のホテルに流れます。直すことはためらわず、直した理由を必ず残します。
目標は、120件をならして1件5分です。 印が付くのは一部の日という想定で、それより多い週は、催しの予定表が細かすぎるか、学ばせた期間が短すぎます。
例外に対処する
| 起きること | 対応 |
|---|---|
| 予約の記録の書き出しが失敗した | 前回の書き出しで出さず、その週は「見込みなし」として人事部に知らせる |
| 「予約した日」「取り消した日」の列が空 | 学ばせる組が作れない。その期間を外し、外した日数を記録する |
| 見込みの室数が販売できる室数を超えた | 上限に切り詰め、wide の印を付ける |
| 見込みの室数がいまの室数を大きく下回った | 取消が多いという見込み。真ん中の人数が過去の最小を下回れば jump |
| 部屋の種類が清掃の時間の表に無い | 人数を出さず、その日を low_history にして人へ |
| 休館や貸し切りの日 | 人数を出さず、リーダーが手で入れる |
| 宿泊管理システムの入れ替え | 入れ替えの前後で列の意味が変わる。学ばせ直すまで見込みを止める |
| リーダーが確認の期限までに戻さない | 印の付いた日も p50 のまま渡し、「未確認」の列を付ける |
| 新しい部屋の種類やプランを売り始めた | 清掃の時間の表とプランの一覧に足すまで、その室数を low_history で人へ |
| 学ばせ直したモデルの外れ方が前の版より悪い | 新しい版を使わず、前の版で見込みを出す。 版の比較を記録する |
上から2行目が、最初の数か月でいちばん起きます。 宿泊管理システムによっては、取消した予約の「予約した日」が書き出されないことがあります。学ばせる組が作れない期間がどれだけあるかを、最初に数えてください。
記録を残す
- 実行ごとに、書き出した予約の記録のファイル名と書き出し日時
- 学ばせたモデルの版(学ばせた期間、特徴の列、
monotonic_cstの有無) - 確かめる期間での外れ方(
mean_pinball_lossをalpha=0.5とalpha=0.8で) - ホテル・日ごとの出力のJSON(
on_books、p50、p80、flags) - リーダーが直した記録(
leader_overrideの人数と理由) - 日ごとの実際の清掃室数と、見込みとの差
外れ方は mean_pinball_loss で測ります。 分位点の回帰の損失を測る関数で、alpha で見る分位点を決め、alpha=0.5 のときは平均絶対誤差と同じになります。 0.8の側は、多めの見込みを下回った日がどれだけ痛かったかで測ります。真ん中だけを当たり外れで測ると、多めの側が当たっているかが分かりません。
直した記録は、モデルを学ばせ直す材料になります。 同じ催しで毎回同じ方向に直しているなら、催しの規模の列の付け方が実態と合っていません。
04実装レベルの3段階
半自動化で、数えと換算は機械になります。 1件20分のうち①と③の大半が消えますが、これから動く分の上乗せは、まだ比の掛け算か勘です。 本格構成で、1件5分になります。 本記事の想定はこの段階です。上乗せがモデルに置き換わり、リーダーは印の付いた日だけを見ます。 差が大きいのは、②の考える時間が、印の付いた日の確認に変わるからです。 段階を飛ばさないでください。 半自動化を1〜2か月回すと、清掃の時間の表の誤りと、連泊の数え方の誤りが先に見つかります。室数の数えが合っていない状態でモデルを足すと、外れの理由が分からなくなります。
05工数削減シミュレーション
導入後 120件 × 5分 ÷ 60 = 10 時間/月
自社条件で導入効果を整理したい方へ
このユースケースを自社に当てはめた場合の前提値と削減見込みを、業務ヒアリングをもとに整理します。
06向いている企業・向いていない企業
- 客室数が百室を超えるホテルを複数運営し、客室清掃のパート・アルバイトを自社で雇ってシフトを組んでいる会社。客室係のリーダーや支配人が、予約の画面を見ながら翌週の必要人数を勘で決めている場合。直前の予約と取消で人数が足りない日・余る日が毎週出ている場合。宿泊管理システムから過去1年以上の予約と取消の記録を書き出せる場合。
- 客室が数十室で、毎日同じ人数で回せる場合。客室清掃を外部の会社にすべて委託し、人数の手配も委託先が行っている場合(必要室数の見込みだけを渡す形に組み替える)。開業から日が浅く、予約と取消の記録がたまっていない場合。なお、個々の従業員の勤務の割り当て、労働時間の管理、採用の判断は、この構成では代替できません。
07最小構成で試す方法
- 宿泊管理システムから、1軒のホテルの過去3か月分の予約の記録を、取消も含めて書き出す
- 表計算ソフトで、各日について「7日前の時点で入っていたチェックアウトの室数」と「最終のチェックアウトの室数」を並べる
- 曜日ごとに、最終の室数を7日前の室数で割った比を平均する
- 翌週の各日について、いまの室数にその比を掛けて見込みを出す
- 同じ週のリーダーの見込みと並べ、翌週に実際の室数と比べる
最初に確かめるのは、比が曜日で違うかです。 平日と週末で比がはっきり違えば、リーダーの勘の中身が、この比だったということです。 違わなければ、催しや季節の影響のほうが大きいホテルです。
| 出てきた内容 | 判断 |
|---|---|
| 比の見込みがリーダーの見込みと同じくらい当たった | Python でのモデルに進む。 幅と連泊を足す |
| 取消を含めた書き出しができなかった | 書き出しの設定を先に直す。 予約した日と取り消した日が要る |
| 催しの日だけ大きく外れた | 想定どおり。催しの予定表を作る |
2行目が出ても、構成は有効です。 宿泊管理システムの帳票の設定で、取消の記録が出せるかを販売元に確かめます。ここが出せないと、これから動く分を学ばせることはできません。
08実装時につまずきやすいポイント
| 問題 | 対策 |
|---|---|
| 取消を除いて書き出し、取消の多い日を少なめに見込む | 取消も含めて書き出す。 予約した日と取り消した日が要る |
| 同じ到着日の組が学ばせる側と確かめる側に入る | TimeSeriesSplit の gap で間を空ける |
| 満室を超える見込みが出る | 販売できる室数で切り詰める規則を置く |
| 連泊の清掃を断るプランを数えから外し忘れる | プランの一覧に印を持たせ、展開のときに分ける |
| 何泊かに1回は清掃に入る決まりを忘れる | プランごとの清掃の周期を一覧に持たせる |
| 室数が当たっても人数が外れる | 清掃の時間の表を実測で作り直す |
| 真ん中の人数だけで組んで、半分の日が足りない | 多めとの差を「呼べたら呼ぶ人」として持つ |
| 出し直しで確定したシフトを自動で減らす | 知らせるだけにする。 シフトには触れない |
| 宿泊管理システムの入れ替えで列の意味が変わる | 入れ替えの前後で学ばせ直す |
| 実際の清掃室数の記録が無く外れを測れない | 客室係の作業表に清掃室数の欄を足す |
上の2行が、この構成の失敗のほとんどです。 どちらも「これから動く分」を学ばせる材料の問題です。取消を含めた記録と、時系列を崩さない検証が無いと、見込みは当たって見えるのに本番で外れます。
下の2行も、同じくらい早く効いてきます。 シフトは働く人の生活の予定です。見込みが出し直されるたびにシフトが動く仕組みは、作らないでください。
09セキュリティ・AIガバナンス上の注意点
この構成で扱うデータ: 予約の記録(到着日・出発日・部屋の種類・プラン)と、客室係の勤務の予定です。宿泊者の氏名・連絡先は使いません。
- 予約の記録から個人の項目を外して書き出す … 見込みに要るのは日付・部屋の種類・プラン・室数・予約した日・取り消した日だけです。宿泊者の氏名や連絡先の列は、書き出しの設定で外します
- 見込みで個人の勤務を決めない … この構成が出すのは日ごとの必要人数までです。誰をどの日に入れるかは、勤務の希望と労働時間を見て人事部が決めます
- 確定したシフトを自動で変えない … 出し直しの結果は知らせにとどめます。働く人の予定を、モデルの見込みで前日に動かさないでください
- 人数の見込みを、評価の材料にしない … 「見込みより清掃が遅かった」を個人の評価に使うと、清掃の時間の表が実態から離れていきます。表は部屋の種類ごとの平均で、個人の速さではありません
- 見込みの限界を伝える … 多めの側は「10日のうち8日はこれを下回る」水準で、残りの日は足りなくなります。 リーダーと人事部に、その前提を共有しておきます
誤りが起きた場合のリスクは、人が足りずに部屋が仕上がらないことと、人が余って早上がりをお願いすることの2つです。 前者は多めの側を持たないと起き、後者は印の付いた日を確かめないと起きます。どちらも、2本の見込みと人の確認で守ります。
10まず何から始めるか
1週目:清掃の時間の表を作る
各ホテルのリーダーと、部屋の種類ごとにチェックアウトの清掃と連泊の清掃の時間を測ります。1人が1日に清掃できる分数も、移動とリネンの補充を除いて決めます。 室数を人数に直す土台です。
2週目:取消を含めた書き出しを確かめる
宿泊管理システムから、過去3か月分の予約の記録を取消も含めて書き出し、予約した日と取り消した日の列があるかを確かめます。無ければ販売元に、書き出しの設定を問い合わせます。
3週目:最小構成で比を出す
1軒のホテルで、曜日ごとの「7日前の室数に対する最終の室数の比」を出し、翌週の見込みをリーダーの見込みと並べます。客室係の作業表に、日ごとの清掃室数の欄を足します。
4週目:Python で室数と人数を出す
予約を日ごとに展開し、連泊と清掃を断るプランを分け、清掃の時間から人数を出すところまで作ります。この時点ではモデルを使わず、比の掛け算で見込みます。
2か月目: 分位点の回帰で真ん中と多めを見込み、TimeSeriesSplit で外れ方を測ります。印付けを足し、リーダーの確認の表を回し始めます。3か月目以降: シフト作成の仕組みへの受け渡しを足し、1件20分が何分になったかを実測します。4軒すべてで、印の付いた日だけを見て人数が決まり、見込みと実際の差を毎週見られるようになった時点で、この構成は完成です。
11関連ユースケース
12この仕組みを理解するための記事
13技術仕様の確認日・参考情報
| 確認した内容 | 情報源 | 確認日 |
|---|---|---|
HistGradientBoostingRegressor の損失に squared_error・absolute_error・gamma・poisson・quantile があり、quantile は分位点の損失(ピンボール損失)であること。quantile の引数で0から1の分位点を指定すること。欠けた値を分かれ目ごとに左右へ送ることを学ぶこと。categorical_features で区分の列を扱えること。monotonic_cst で単調な向きを指定できること(scikit-learn 1.9.1 の文書) | scikit-learn: HistGradientBoostingRegressor | 2026-10-08 |
mean_pinball_loss が分位点の回帰の損失を測ること。alpha で分位点を決めること。alpha=0.5 のとき平均絶対誤差と同じになること | scikit-learn: mean_pinball_loss | 2026-10-08 |
TimeSeriesSplit が時間の順の記録で、前の期間で学ばせ後の期間で確かめる分け方であること。n_splits・test_size・gap の指定があり、gap が学ばせる期間の終わりから除く数であること | scikit-learn: TimeSeriesSplit | 2026-10-08 |
シフトの決定、労働時間の管理、清掃の手順は、人事部と各ホテルの判断で決めてください。 本記事は製品の公開ドキュメントで確認できた範囲だけを扱っています。
実装ステータス:構成例。 公開仕様に基づいて設計した構成であり、当社で実際に構築・検証したものではありません。工数の数値はモデル条件による試算です。
自社の業務に使えるAI活用候補を整理します
このユースケース(UC-1094)についてのご相談はこちらから。
