コインランドリーの事業者が機械ごとの利用の記録・曜日・天気から、店舗ごとの時間帯の稼働を Python で予測し、巡回と点検の時間帯の案を出す
コインランドリーの機械ごとの利用の記録と曜日・天気から、Python で翌週の店舗ごとの1時間ごとの稼働を機種別に予測します。全台がふさがる帯に印を付け、清掃・集金・点検に回る時間帯の案を出します。
- 連携・自動化
- Python
- 対象業界
- その他/小売
- 対象部門
- 経営企画
- 対象業務
- 集計・分析
- 主な課題
- データ分析に時間がかかる/判断に時間がかかる/属人化している
- AIで行う処理
- 予測
- 主な効果
- 判断支援/属人化解消/工数削減
- 導入難易度
- ★★★★☆
- 実装レベル
- 本格構成
- 費用感
- 個別開発(大)
- 人間の確認
- 条件付き
01導入前 / 導入後の業務フロー
- 木曜に、計画係が管理の仕組みから先週の店舗ごとの時間帯別の売上を見る
- 店ごとに、先週と前年の同じ時期の混み方を見比べる
- 週間天気予報を見て、雨の日に乾燥機が埋まりそうな店と時間帯を決める
- 店ごとに、空いていそうな時間帯を選んで巡回の時間を入れる
- 担当4名の予定と移動の順を考えて、巡回の予定表に書く
- 雨の予報が変わったら、前日に担当に連絡して時間を入れ替える
- 人巡回の担当が、店で機械の故障や使用の停止を見つけたら、故障の記録のシートに機械の番号と止めた時刻・戻した時刻を入れる
- 人計画係が、翌週の日ごとの天気予報(雨の有無、最高気温)と、店の近くの催しを予定のシートに入れる
- 自動木曜の朝、Python が管理の仕組みの CSV・故障の記録・予定のシート・過去の天気を読み込む
- 自動学習済みのモデルで、店ごと・機種ごとに翌週の1時間ごとの使い始めの回数を、中央と上振れで予測する
- 自動コースの長さの記録から1時間ごとの稼働を積み上げ、使える台数を超える帯に「満台」の印を付ける
- 自動店ごとに、稼働の低い帯から巡回に向く時間帯の候補を3つ出す
- 人計画係が候補と担当の予定と移動の順を突き合わせ、巡回の予定表を組む
- 【自動/人】 前日の朝、天気予報が変わった日だけ予定のシートを直して予測をやり直し、計画係が入れ替えるかを決める
各工程の詳しい説明を読む
- 木曜に、計画係が管理の仕組みから先週の店舗ごとの時間帯別の売上を見る
- 店ごとに、先週と前年の同じ時期の混み方を見比べる
- 週間天気予報を見て、雨の日に乾燥機が埋まりそうな店と時間帯を決める
- 店ごとに、空いていそうな時間帯を選んで巡回の時間を入れる
- 担当4名の予定と移動の順を考えて、巡回の予定表に書く
- 雨の予報が変わったら、前日に担当に連絡して時間を入れ替える
(a)売上の合計では、どの機械が埋まっているかが分からない。 1番目の時間帯別の売上は、店の全機種の合計です。乾燥機が全台埋まって客が帰っている時間も、洗濯機が空いていれば「そこそこ」の売上に見えます。 機械ごとの記録は書き出せるのに、見比べに使われていません。
(b)全台がふさがっている時間は、記録が頭打ちになる。 乾燥機が8台しかない店の雨の夕方は、記録の上では「8台が使われていた」で終わります。入れなかった客が何人いたかは、どこにも残っていません。 前年の同じ雨の日を見ても、本当の混み方より少なく見えます。
(c)計画係しか決められない。 2番目と3番目は経験による見当です。店ごとの癖(駅前の店は平日の夜が混む、住宅地の店は土曜の朝が混む)は、計画係の頭の中にしかありません。 計画係が休む週は、先週と同じ時間帯で組まれます。
(d)雨の読みで迷う。 「曇り時々雨」の日は、乾燥機が埋まるかどうかで毎回迷います。巡回を夕方に入れた店が雨で埋まれば、フィルターの掃除ができずに乾燥の効きが落ちます。 落ちれば客が2回分払うことになり、苦情につながります。
- 【人】 巡回の担当が、店で機械の故障や使用の停止を見つけたら、故障の記録のシートに機械の番号と止めた時刻・戻した時刻を入れる
- 【人】 計画係が、翌週の日ごとの天気予報(雨の有無、最高気温)と、店の近くの催しを予定のシートに入れる
- 【自動】 木曜の朝、Python が管理の仕組みの CSV・故障の記録・予定のシート・過去の天気を読み込む
- 【自動】 学習済みのモデルで、店ごと・機種ごとに翌週の1時間ごとの使い始めの回数を、中央と上振れで予測する
- 【自動】 コースの長さの記録から1時間ごとの稼働を積み上げ、使える台数を超える帯に「満台」の印を付ける
- 【自動】 店ごとに、稼働の低い帯から巡回に向く時間帯の候補を3つ出す
- 【人】 計画係が候補と担当の予定と移動の順を突き合わせ、巡回の予定表を組む
- 【自動/人】 前日の朝、天気予報が変わった日だけ予定のシートを直して予測をやり直し、計画係が入れ替えるかを決める
1番目の故障の記録が、この設計の土台の一つです。 乾燥機が1台止まっていた週は、記録の上では使い始めが減ります。止まっていた機械を引かずに学習すると、モデルは「この店は需要が少ない」と覚えます。 使える台数を時間ごとに持つために、止めた時刻と戻した時刻を残します。
7番目で決めるのは計画係です。 モデルが出すのは時間帯の候補で、どの担当がどの順で回るかは、担当の住まいと車と、店の間の道の混み方を知っている計画係が決めます。
02今回想定するシステム構成
決済の端末・管理の仕組みの CSV(機械番号・使い始めの時刻・コース・金額・エラー) + 故障の記録のシート + 機械の台帳(店・機種・容量・コースの長さ) + 過去の天気(気象庁の過去の気象データ)+ 祝日(内閣府の CSV) + 翌週の天気予報と催し(計画係が入れる予定のシート) │ ▼【トリガー】毎週木曜の朝(事務所のパソコンの定時実行) Python(pandas) ├──▶ 店・機種・1時間ごとの使い始めの回数をそろえ、使える台数を出す ▼ scikit-learn(HistGradientBoostingRegressor) │ 翌週の1時間ごとの使い始め:中央(ポアソン)・上振れ(分位点) ▼ Python ── コースの長さで稼働を積み上げ、満台の帯に印 ▼ Python ── 店ごとに巡回に向く時間帯の候補を3つ ▼ 【人】計画係が担当の予定と移動の順で巡回の予定表を組む
| 役割 | 想定する製品 | 代替候補 |
|---|---|---|
| 実行環境 | Python(pandas・scikit-learn) | R |
| 処理エンジン | scikit-learn の HistGradientBoostingRegressor(ポアソン損失と分位点損失、単調性の制約) | LightGBM、Prophet |
| 集計 | Python(稼働の積み上げ、満台の帯の印、巡回の候補の選び出し) | スプレッドシートの計算式 |
| 保管 | Google スプレッドシート(故障の記録、予定、機械の台帳、巡回の予定表) | - |
新しく足すのは、Python の処理と、故障の記録のシート、予定のシート、機械の台帳です。 決済の端末と管理の仕組みはこれまでどおりで、この構成は巡回の予定表に担当の名前を書き込みません。 出すのは店ごとの時間帯の候補です。
予測のエンジンに HistGradientBoostingRegressor を選んだのは、損失と制約を目的に合わせて替えられるからです。 使い始めの回数は0以上の数なので、中央の見込みには loss="poisson"(目的の値が0以上であることが要る)を使い、上振れには loss="quantile" で分位を指定します。さらに monotonic_cst で、乾燥機のモデルでは降水量が増えても使い始めが減らない、という向きの制約を付けられます。
生成AIは使いません。 予測は数の問題で、計画係に渡すのは店ごとの表です。
03どうやって実装するのか
処理の起点を決める
毎週木曜の朝に1回動かします。 巡回の担当の翌週の予定の締めが木曜の夕方なので、計画係が昼のうちに候補を見て、担当の予定と突き合わせられる時刻にします。事務所のパソコンの定時実行の仕組み(Windows ならタスク スケジューラ)で Python のスクリプトを起動します。
前日の朝にも、天気予報が変わった日だけ動かします。 計画係が予定のシートの翌日の天気を直して「やり直し」の印を付けたら、その日の分だけ予測と候補を作り直します。 毎日すべての日をやり直すと、担当への連絡が増えて予定が落ち着きません。
月に1回、モデルを作り直します。 毎月の第1木曜に、先月までの記録で学習し直し、作り直す前と後で、先月の当たり方を比べた結果を残します。悪くなっていれば、前のモデルのまま使います。
結果の表には作った日時を必ず印字します。 前日のやり直しの後に、古い表で巡回を組まないためです。
入力データを集める
| データ | 中身 | 取得元 |
|---|---|---|
| 機械の利用 | 機械番号、使い始めの時刻、コース(洗濯のみ/洗濯乾燥/乾燥の分数)、金額、エラーの番号 | 決済の端末・管理の仕組み(CSV) |
| 機械の台帳 | 店、機械番号、機種(洗濯乾燥機・乾燥機・洗濯機・スニーカー)、容量、コースごとの標準の長さ | 機械の台帳のシート(新しく作る) |
| 故障の記録 | 機械番号、止めた時刻、戻した時刻、理由 | 故障の記録のシート(新しく作る) |
| 過去の天気 | 日ごとの降水量・日照時間・平均湿度・最高気温 | 気象庁の過去の気象データ・ダウンロード(CSV) |
| 祝日 | 国民の祝日の日付 | 内閣府の祝日の CSV |
| 予定 | 翌週の日ごとの天気予報(雨の有無・最高気温)、店の近くの催し、店の工事・休業 | 予定のシート(計画係が入れる) |
質を決めるのは、故障の記録と機械の台帳です。 故障の記録が無ければ、止まっていた機械の分だけ需要が少なく学習されます。台帳のコースの長さが無ければ、使い始めの回数から稼働を積み上げられません。 どちらも管理の仕組みからは出てこない、運営の側が持つ情報です。
利用の記録に会員の番号が含まれる仕組みもあります。 ポイントのカードやアプリで払った客の番号です。予測には要らないので、読み込むときに列ごと捨てます。
天気は日ごとの値を使います。 コインランドリーの乾燥機の需要は、その日に雨が降ったかに加え、前日の雨と、晴れの日の湿度でも動きます。気象庁の過去の気象データ・ダウンロードでは、地点と項目を複数選び、検索の結果を CSV で落とせます。 店の近くの観測地点の日ごとの降水量・日照時間・湿度・最高気温を取ります。店が離れていれば、店ごとに近い地点を割り当てます。
データの取得方法を決める
| 取るもの | どこから | 何に使うか |
|---|---|---|
| 機械の利用 | 管理の仕組みの画面から週に1回 CSV を書き出し、決まったフォルダに置く | 使い始めの回数、コースの長さ |
| 機械の台帳・故障の記録・予定 | スプレッドシートを CSV で書き出す(またはシートの API で読む) | 使える台数、催し |
| 過去の天気 | 月に1回、気象庁のページから CSV を落とす | 降水・日照・湿度・気温 |
| 祝日 | 年に1回、内閣府の CSV を入れ替える | 祝日の印 |
気象庁の CSV には、値の列のほかに品質情報や均質番号の列が並び、降水量には現象なし情報の列もあります。 値の列だけを名前で選んで読みます。列の位置で読むと、項目を足したときに湿度の列に品質情報が入ります。
祝日の CSV は、翌年の分が前の年の2月に載るとされています。年に1回、2月に入れ替えます。
管理の仕組みの CSV は、店によって機械の世代が違うと書き方も違うことがあります。 古い機械は使い始めの時刻だけ、新しい機械は終わりの時刻まで出る、という具合です。最初に店ごとに1週分を見て、時刻とコースの列の読み方を1か所に書いておきます。
AIへ渡す前に整形する
- 1時間の枠にそろえる … 営業時間を1時間ずつに区切り、店・機種ごとに使い始めの回数を数えます
- 使える台数を出す … 機械の台帳の台数から、故障の記録で止まっていた機械を時間ごとに引きます。全台止まっていた枠は、0ではなく行ごと外します
- 満台の枠に印を付ける … コースの長さで稼働を積み上げ、使える台数の95%を超えた枠を「満台」とします
- エラーで止まった利用を外す … エラーの番号のある利用は、すぐ別の機械で使い直されることが多いので、二重に数えないよう外します
- 項目を作る … 店、機種、曜日、時刻、祝日とその前日、月、その日と前日の降水量、日照時間、湿度、最高気温、催しの有無、前年の同じ週の同じ曜日・同じ枠の回数、直近4週の同じ曜日・同じ枠の平均
- 店・機種・曜日・時刻を Categorical にする … pandas の Categorical の型にしておけば、既定の設定でカテゴリとして扱われます
2番目と3番目が、この構成の肝です。 乾燥機が1台止まっていた雨の日は、使える台数が1つ少なく、満台になりやすい日です。台数を引かずに学習すると、「雨なのに使い始めが少なかった日」として覚えます。
満台の枠の使い始めは、本当の需要より少なく出ます。 コインランドリーには待ちの受付がなく、入れなかった客の記録を取る手段がありません。満台の枠は、中央のモデルの学習から外し、上振れのモデルにだけ使います。 印の付いた枠が多い店は、予測が低めに出ていることを表の上に書きます。
前日の降水量を項目に入れるのは、雨が上がった翌日にも乾燥機が埋まるからです。 雨の日に乾かせなかった洗濯物を、翌日にまとめて持ち込む客がいます。その日の雨だけで学習すると、翌日の混み方を見落とします。
AIに処理させる
させるのは、翌週の店・機種・1時間ごとの使い始めの回数を予測することだけです。 機械学習のモデルを2本作ります。
| 出すもの | 損失 | 使いみち |
|---|---|---|
| 中央の見込み | loss="poisson" | 稼働の基準と、巡回の候補の選び出し |
| 上振れの見込み(0.8) | loss="quantile"、quantile=0.8 | 満台の恐れの印と、巡回を避ける帯 |
稼働そのものは、モデルに直接予測させません。 稼働は台数で頭打ちになるので、学習させると天井を覚えます。使い始めを予測し、コースの長さで1時間ごとに積み上げて稼働を出します。
| 1時間の枠の状態 | 決め方 | 表の印 |
|---|---|---|
| 空き | 中央の稼働が使える台数の40%未満 | 巡回の候補 |
| 普通 | 中央の稼働が40%以上 | - |
| 満台の恐れ | 上振れの稼働が使える台数を超える | 橙 |
| 満台 | 中央の稼働が使える台数を超える | 赤 |
巡回の候補は、「空き」の枠が1時間以上続き、前後の枠に橙や赤が無いところから選びます。 乾燥機のフィルターの掃除には、乾燥機を止められる時間が要るからです。40%の線は、計画係と一緒に決めます。 店の広さや作業の長さで、邪魔にならない稼働は違います。
| させないこと | 理由 |
|---|---|
| 担当の割り当てと回る順 | 担当の住まい・車・道の混み方は計画係が知っている |
| 機械の増設・入れ替えの判断 | 投資の判断。予測は材料の1つにすぎない |
| 料金の改定や割引の時間帯の決定 | 客への案内の方針。予測とは別に決める |
| 故障の修理の手配 | 業者と機械の状態で決める |
| 天気予報そのもの | 計画係が予報を見て入れる |
2行目は、とくに気を付けてください。 満台の印が多い店は乾燥機を足したくなりますが、満台の枠の需要は少なめにしか見えていません。 増設を考えるなら、予測の表ではなく、満台の枠の数と長さの推移を別に見ます。
指示内容を固定する
生成AIを使わないので、プロンプトはありません。 かわりに、予測と積み上げの中身を示します。
from sklearn.ensemble import HistGradientBoostingRegressor
from sklearn.model_selection import TimeSeriesSplit
import numpy as np
FEATURES = ["store", "machine_type", "weekday", "hour", "is_holiday", "is_pre_holiday",
"month", "rain_mm", "rain_mm_prev", "sunshine_h", "humidity", "tmax",
"event_flag", "last_year_same", "recent4w_same_mean"]
# store・machine_type・weekday・hour は pandas の Categorical にしておく
# 乾燥機のモデルだけ、降水量が増えて使い始めが減ることはない、という向きを付ける
dryer_cst = {"rain_mm": 1, "rain_mm_prev": 1}
center = HistGradientBoostingRegressor(
loss="poisson", max_iter=800, learning_rate=0.05, monotonic_cst=dryer_cst,
early_stopping=True, validation_fraction=0.15, random_state=0)
upper = HistGradientBoostingRegressor(
loss="quantile", quantile=0.8, max_iter=800, learning_rate=0.05,
monotonic_cst=dryer_cst, early_stopping=True, validation_fraction=0.15, random_state=0)
train_c = dryer[~dryer["full"]] # 満台の枠は中央の学習から外す
center.fit(train_c[FEATURES], train_c["starts"])
upper.fit(dryer[FEATURES], dryer["starts"])
# 当たり方は時系列の順を守って確かめる(学習は常に検証より前)
tscv = TimeSeriesSplit(n_splits=5, gap=24 * 7) # 1時間の枠で1週分の間を空ける
monotonic_cst は名前で指定しています。 公式の説明では、辞書で渡すと項目の名前で制約を対応させ、1は増える向き、-1は減る向き、0は制約なしです。名前で渡すには、学習に項目の名前のある表(pandas の DataFrame)を使います。乾燥機のモデルにだけ付け、洗濯機のモデルには付けません。 洗濯機は雨で増えるとは限らないからです。
当たり方の確かめには TimeSeriesSplit を使います。 公式の説明では、時系列の順に並んだデータで、学習が常に検証より前になるように分け、後の分割ほど学習の範囲が広がります。gap で学習の末尾と検証の間を空けられます。ふつうの交差検証で混ぜると、未来の記録で学習して過去を当てることになり、当たり方が良く見えすぎます。 公式は、各回の比べ方をそろえるには等間隔に並んでいることが要るとしているので、営業時間外の枠も行として持ってから分けます。
early_stopping を明示的に有効にしているのは、既定の 'auto' では学習の行が10,000を超えるときにしか有効にならないからです。 9店・4機種・1時間の枠で1年分あれば超えますが、1店で試す段階では超えないことがあります。
def occupancy(starts_by_hour, run_share):
"""run_share[k] = 使い始めた機械が k 時間後の枠でもまだ動いている割合"""
occ = np.zeros(len(starts_by_hour))
for i, s in enumerate(starts_by_hour):
for k, r in enumerate(run_share):
if i + k < len(occ):
occ[i + k] += s * r
return occ
run_share は、機械の台帳のコースの長さと、利用の記録のコースの分数から作ります。 洗濯乾燥のコースは1時間を超え、乾燥機は10分単位で延長されるので、機種ごと・時間帯ごとに分けて持ちます。
出力形式を固定する
計画係に渡すのは、次の2つの表です。 印刷して木曜の昼に見ることを前提にします。
【店ごとの1時間ごとの稼働(1日分の例・駅前店)】
| 時 | 乾燥機(中央/上振れ/台数) | 洗濯乾燥機(中央/上振れ/台数) | 洗濯機 | 印 |
|---|---|---|---|---|
| 9 | 2.1/3.4/8 | 1.2/2.0/5 | 0.4 | 巡回の候補 |
| 10 | 2.6/4.0/8 | 1.8/2.9/5 | 0.6 | 巡回の候補 |
| 18 | 6.8/8.9/8 | 3.9/5.2/5 | 0.9 | 橙 |
| 19 | 8.4/10.1/8 | 4.6/5.8/5 | 1.1 | 赤 |
【翌週の巡回の時間帯の候補】
| 店 | 日 | 天気(入力) | 候補1 | 候補2 | 候補3 | 印 |
|---|---|---|---|---|---|---|
| 駅前店 | 月 | 雨のち曇り | 9〜11時 | 14〜15時 | - | 雨の翌日:火の夕方も混む |
| 住宅地店 | 土 | 晴れ | 15〜17時 | 20〜22時 | - | 朝は大型が満台 |
「印」の列で、計画係が見る先を決めます。 雨の日の翌日には「雨の翌日」、満台の枠が多い店には「予測は低めの恐れ」、故障の記録で機械が止まったままの店には「台数減で計算」、予定のシートが空の日には「予定未入力」を出します。
機械で読む用には、同じ内容を CSV でも残します。 列は、店、日、時、機種、中央・上振れの使い始め、稼働、使える台数、印、モデルを作った日付です。翌週に実績と並べて当たり方を見るのは、この CSV です。
システムへ連携する
| つなぎ先 | 方式 | 内容 |
|---|---|---|
| 決済の端末・管理の仕組み | 週に1回、画面から CSV を書き出してフォルダに置く | 機械の利用を読む |
| 機械の台帳・故障の記録・予定のシート | スプレッドシートを CSV で書き出して読む(またはシートの API で読む) | 使える台数、コースの長さ、催し |
| 気象庁の過去の気象データ | 月に1回、画面から CSV を落とす | 過去の天気 |
| 巡回の予定表 | 書き込まない(計画係が候補を見て組む) | - |
管理の仕組みに API があっても、最初は CSV の書き出しで始めます。 週に1回の書き出しで足り、仕組みの会社との取り決めや認証の手間を先に抱えなくて済みます。 書き出しの手間が負担になってから、API に替えるかを考えます。
人が確認する
- 作った日時を見る … 表の上の日時が当日の朝であることを確かめます
- 赤と橙の帯を見る … 巡回がその帯にかからないよう、候補から組みます
- 雨の日と翌日の印を見る … 雨の予報の日は、前日にやり直すかを決めます
- 予測の外の事情を足し引きする … 近くの店の休業、学校の行事、引っ越しの多い時期、機械の入れ替えの工事
目標は、36件をならして1件5分です。 印の無い店は候補を写すだけで、時間を使うのは雨の週と満台の印が多い店です。
例外に対処する
| 起きること | 対応 |
|---|---|
| 店の CSV が届いていない週がある | その週を欠けとして扱い、表に「利用の記録の欠け」 |
| 故障の記録に戻した時刻が無い | 止まったままとして台数を引き、表に「台数減で計算」 |
| 予定のシートが空 | 予測は出し、表の一番上に「予定と天気予報が未入力」 |
| 停電・断水で店を閉めた日 | 閉めた時間帯を行ごと外す。使い始め0として学習しない |
| 機械を入れ替えて機種や台数が変わった | 台帳を直し、入れ替えの日を記録。直後の数週は印を付ける |
| 中央と上振れが交わる | 大きいほうを上振れとして使い、件数を記録 |
| 作り直したモデルが前より外れる | 前のモデルのまま使い、作り直しの記録を残す |
| 新しく開いた店 | 記録が半年たまるまで、近い立地の店のモデルの値を参考として出す |
4行目を間違えると、雨の効き方が乱れます。 台風で店を閉めた時間を「使い始め0」として学習すると、モデルは「大雨の日は誰も来ない」と覚え、乾燥機の単調性の制約とも食い違います。
記録を残す
- 実行の日時、使ったモデルの作成日、読み込んだ記録の期間
- 店・機種・1時間ごとの中央・上振れの使い始め、稼働、使える台数、印
- 計画係が組んだ巡回の時間と、候補から変えた理由
- 翌週の実績(使い始め、満台の枠、巡回の時間に店にいた客の数の目安)
- 前日のやり直しの有無と、やり直す前と後の候補
- 月ごとの当たり方(中央の外れの大きさ、上振れを上回った枠の割合)と、モデルの作り直しの結果
上振れを上回った枠の割合は、0.8の線なら5枠に1枠ほどが目安です。 それより多ければ上振れの線が低すぎます。満台の印を信じてよいかを見る、一番わかりやすい物差しです。
04実装レベルの3段階
本記事の想定は本格構成です。 半自動化では稼働の表までで、巡回の時間帯を選ぶのは計画係の手に残ります。 それでも見比べの時間は減りますが、9店分の表を読む時間がかかります。 半自動化で1件20分が10分ほどに、本格構成で5分になります。 差が大きいのは、空きの枠が続く時間を探して候補にする作業が、規則があれば機械で出せるからです。 段階を飛ばさないでください。 半自動化の表を1か月見ると、どの店・どの機種の予測が当たり、どこが外れるかが分かります。外れる店の記録を直してから本格構成に進みます。
05工数削減シミュレーション
導入後 36件 × 5分 ÷ 60 = 3 時間/月
自社条件で導入効果を整理したい方へ
このユースケースを自社に当てはめた場合の前提値と削減見込みを、業務ヒアリングをもとに整理します。
06向いている企業・向いていない企業
- 無人のコインランドリーを数店から十数店営み、機械ごとの利用の始まりの時刻とコースを決済の端末や管理の仕組みから CSV で書き出せる事業者。清掃・集金・洗剤の補充・乾燥機のフィルターの掃除に回る時間帯を、担当者が店舗ごとの混み方の勘で決めていて、混んでいる時間に作業がぶつかる、雨の日に乾燥機がふさがって客が帰る、ということが繰り返されている場合。
- 店舗が1〜2店で、オーナーが毎日店に出て様子を見ている場合。利用の記録が日ごとの売上の合計しか残らない古い機械が多い場合。開店から1年未満で、季節と天気の動きが記録に無い場合。なお、機械の増設や入れ替え、料金の改定、故障のときの修理の手配の判断は、この構成では代替できません。
07最小構成で試す方法
- 乾燥機の多い1店を選び、去年の秋の2か月分の機械の利用の記録を書き出す
- その期間の故障の記録を、担当の記憶と修理の伝票から拾える分だけ拾う
- 気象庁の過去の気象データ・ダウンロードで、近くの地点の日ごとの降水量・日照時間・湿度・最高気温を落とす
- Python で第7章の設定を動かし、その2か月の最後の2週を「翌週」として予測させる
- 稼働を積み上げ、当時の巡回の時間と、実際の利用の記録と並べる
1店・2か月で十分です。 確かめたいのは、「雨とその翌日の乾燥機の動きを、計画係の見当と同じくらい拾えるか」です。
| 出てきた内容 | 判断 |
|---|---|
| 雨の日と翌日の乾燥機の増え方が当時と合う | 店を増やし、故障の記録を付け始める段階に進む |
| 平日は合うが、雨の夕方が低めに出る | 満台の天井を覚えている。満台の枠を中央の学習から外す |
| 雨の効き方がばらばら | 店を閉めた日や止まっていた機械を外しているかを確かめる |
2行目は、乾燥機の少ない店ほど出ます。 失敗ではなく、記録の頭打ちが数字で見えたということです。
08実装時につまずきやすいポイント
| 問題 | 対策 |
|---|---|
| 稼働を直接学習して天井を覚える | 使い始めを予測し、コースの長さで稼働を積み上げる |
| 止まっていた機械の分だけ需要が少なく出る | 故障の記録で使える台数を引く |
| 店を閉めた時間を使い始め0で学習する | 行ごと外す |
| 店全体で予測して乾燥機の満台を見落とす | 機種ごとに分ける |
| 雨の翌日の混み方を拾えない | 前日の降水量を項目に入れる |
| ふつうの交差検証で当たり方が良く見える | TimeSeriesSplit で学習を検証より前にする |
| 気象庁の CSV を列の位置で読む | 品質情報などの列が並ぶ。列名で選ぶ |
early_stopping が効かない | 行が10,000以下だと既定では無効。明示して有効にする |
| 単調性の制約を洗濯機にも付ける | 乾燥機のモデルだけに付ける |
| 会員の番号を読み込む | 読み込むときに列ごと捨てる |
上の3行が、この構成の失敗のほとんどです。 どれも、記録に残っている数が、使える台数と営業の状態に縛られていることから起きます。ここを押さえれば、残りは他の予測と同じ注意で足ります。
下の方の行は、作ってからの運用で出てくるものです。 とくに単調性の制約は、付ける機種を間違えても学習は通り、エラーにはなりません。洗濯機の予測が雨の日に不自然に増えていたら、制約の付け先を疑います。 毎月の当たり方の確認を、店と機種に分けて見る習慣にしておけば、どれも早いうちに気づけます。
店を増やしたときも同じ順で確かめます。 新しい店は記録が少なく、近い立地の店のモデルの値を参考に出すだけなので、最初の半年は計画係の見当と並べて使います。 半年たまったら、全店をまとめて学習し直します。
09セキュリティ・AIガバナンス上の注意点
この構成で扱うデータ: 機械ごとの使い始めの時刻・コース・金額、故障の記録、巡回の予定です。決済の仕組みによっては、会員の番号やポイントのカードの番号が利用の記録に含まれます。
- 会員の番号を予測に使わない … 読み込むときに列ごと捨てます。予測に要るのは機械と時刻とコースだけです
- データを外に出さない … 予測は事務所のパソコンの中で動き、生成AIや外部のサービスに記録を送りません
- 巡回は人が確定する … 候補はあくまで候補で、どの担当がいつ回るかは計画係が担当の都合を聞いて決めます
- 増設や料金の判断に予測を直接使わない … 満台の枠の需要は少なめにしか見えていません。投資と料金は、別の材料もあわせて経営の判断で決めます
- 気象庁のデータの使い方を確かめる … 気象庁のホームページのコンテンツは、権利表記の無いものは公共データ利用規約(第1.0版)に沿って使え、使うときは出典を記載し、加工したものは加工したことを書くとされています。国が作ったように見せる使い方はできません
誤りが起きた場合のリスクは、混む時間に巡回がぶつかって客の邪魔になることと、掃除を飛ばして乾燥の効きが落ちることの2つです。 どちらも満台の帯の読み違いから起きるので、故障の記録と前日のやり直しで抑えます。
10まず何から始めるか
1週目:機械の台帳と故障の記録を作る
店ごとの機械の番号・機種・容量・コースの長さを台帳にします。担当が店で機械を止めたら、機械の番号と止めた時刻・戻した時刻を入れる決まりを始めます。
2週目:1店・2か月で試す
第8章のとおり、乾燥機の多い1店の去年の秋の2か月分で、最後の2週を予測させます。雨とその翌日の乾燥機の動きが当時と合うかを見ます。
3週目:巡回の候補の規則を決める
計画係と一緒に、店ごとに巡回の邪魔にならない稼働の線と、作業に要る時間の長さを決めます。
4週目:全店の稼働の表を毎週出す
木曜の朝に全店の翌週の機種ごとの稼働の表を出す半自動化を始め、計画係はこれまでどおり自分で組みながら、表と見比べます。 翌週の月曜に、計画係の見込みと表のどちらが実績に近かったかを、店と機種ごとに書き残します。
2か月目以降: 巡回の候補を出し、前日のやり直しを足します。計画係が候補から変えた時間と理由、上振れを上回った枠の割合を毎月見ます。 計画係が印の付いた店だけを見て巡回を組めるようになり、店を1つ増やしても計画の時間がほとんど増えなくなった時点で、この構成は完成です。
11関連ユースケース
12この仕組みを理解するための記事
13技術仕様の確認日・参考情報
| 確認した内容 | 情報源 | 確認日 |
|---|---|---|
HistGradientBoostingRegressor の loss に 'poisson'(目的の値が0以上であることが要る)と 'quantile' があり quantile で分位を指定すること。categorical_features の既定が 'from_dtype' であること。monotonic_cst で1が増える向き・-1が減る向き・0が制約なしで、辞書なら項目の名前で対応させること。early_stopping='auto' は行が10,000を超えるときに有効になること(版 1.9.1) | scikit-learn: HistGradientBoostingRegressor | 2026-10-28 |
TimeSeriesSplit が時系列の順に並んだデータで学習を検証より前に分け、後の分割の学習が前の分割の学習を含むこと。gap で学習の末尾から除く数を指定できること。比べ方をそろえるには等間隔に並んでいることが要ること | scikit-learn: TimeSeriesSplit | 2026-10-28 |
| 過去の気象データ・ダウンロードで地点と項目を複数選び、検索の結果を CSV で落とせること。CSV に品質情報・均質番号の列が並び、降水量に現象なし情報の列があること | 気象庁: 過去の気象データ・ダウンロード(このページでできること) | 2026-10-28 |
| 気象庁のホームページのコンテンツが、権利表記の無い限り公共データ利用規約(第1.0版)に準拠して使え、出典の記載と、加工した場合はその旨の記載が求められること。国が作成したかのような態様で使えないこと | 気象庁: 気象庁ホームページについて | 2026-10-28 |
| 国民の祝日の CSV が昭和30年から令和9年までを収録し、翌年の分を前年の2月に掲載するとされていること | 内閣府: 国民の祝日について | 2026-10-28 |
巡回の確定、機械の増設や料金の判断は、事業者の判断で行ってください。 本記事は公開されている仕様で確認できた範囲だけを扱っています。
実装ステータス:構成例。 公開仕様に基づいて設計した構成であり、当社で実際に構築・検証したものではありません。工数の数値はモデル条件による試算です。
自社の業務に使えるAI活用候補を整理します
このユースケース(UC-2220)についてのご相談はこちらから。
