信用金庫が支店ごとの預金の入出金の日次の集計から、月末・給与日・年金の支払日の資金と現金の流出を Python で予測し、現金の準備と資金繰りの案を出す
信用金庫の支店ごとの預金の入出金の日次の集計と営業日の暦から、Python で翌月の営業日ごとの預金の純流出と現金の純払出しを、中央と上振れの幅で予測します。支店の現金の準備の量と、本部の資金繰りの山の日の案を出します。
- 連携・自動化
- Python
- 対象業界
- 金融
- 対象部門
- 経営企画/財務
- 対象業務
- 集計・分析
- 主な課題
- データ分析に時間がかかる/判断に時間がかかる/属人化している
- AIで行う処理
- 予測
- 主な効果
- 判断支援/属人化解消/工数削減
- 導入難易度
- ★★★★★
- 実装レベル
- 本格構成
- 費用感
- 個別開発(大)
- 人間の確認
- 条件付き
01導入前 / 導入後の業務フロー
- 毎月の中ごろと月末に、業務の担当が情報系から支店ごとの日次の入出金の集計を書き出す
- 支店ごとに、前年の同じ月と先月の表を並べ、山の日の流出と現金の払出しを見比べる
- 翌月の暦を見て、25日・月末・年金の支払日が何曜日に当たるか、休日でずれるかを確かめる
- 支店の役席から、大口の予定(法人の賞与の振込、決済、公金の払出し)を電話とメールで聞く
- 支店ごとの現金の準備の量を決め、現送の予定に入れる
- 資金の担当が全店の合計の流出を積み上げ、山の日の資金の手当てを決める
- 人支店の役席が、大口の予定(日・入りか出か・おおよその額)を大口の予定の表に入れる。過去の大口の実績にも印を付ける
- 自動毎月の10日と25日の朝、Python が情報系から支店ごと・取引の種類ごとの日次の集計を読み込む
- 自動営業日の暦を作り、各営業日に「月末から何営業日目か」「給与の日の位置」「年金の支払日の位置」を付ける
- 自動過去の大口の実績を差し引いた平常の動きで学習したモデルで、翌期の営業日ごとの純流出と現金の純払出しを、中央と上振れで予測する
- 自動大口の予定を足し戻し、支店ごとの現金の準備の量の案と、全店の合計の流出の山の日を出す
- 人業務の担当が、印の付いた支店(年金の支払日の上振れが大きい、大口の予定が未入力など)を中心に見て、現金の準備の量と現送の予定を決める
- 人資金の担当が、全店の合計の山の日を見て、資金の手当てを決める
各工程の詳しい説明を読む
- 毎月の中ごろと月末に、業務の担当が情報系から支店ごとの日次の入出金の集計を書き出す
- 支店ごとに、前年の同じ月と先月の表を並べ、山の日の流出と現金の払出しを見比べる
- 翌月の暦を見て、25日・月末・年金の支払日が何曜日に当たるか、休日でずれるかを確かめる
- 支店の役席から、大口の予定(法人の賞与の振込、決済、公金の払出し)を電話とメールで聞く
- 支店ごとの現金の準備の量を決め、現送の予定に入れる
- 資金の担当が全店の合計の流出を積み上げ、山の日の資金の手当てを決める
(a)山の日が毎月ずれる。 3番目の暦の確かめは毎回手作業です。25日が日曜の月は給与の山が23日に、年金の15日が土曜の月は14日に寄ります。 前年の同じ月の表と並べると、山の日が1〜2日ずれていて、見比べに時間がかかります。
(b)年金の支払日の現金を読み切れない。 年金の支払月は偶数月だけで、前年の同じ月と比べるにしても、間の奇数月の様子は参考になりません。 現金の払出しが前回より多かった支店に、昼過ぎに現金を追加で運ぶことがあります。
(c)見込みが担当の経験に寄っている。 2番目の見比べで「この支店は年金の日に多めに」「あの支店は月末に法人が動く」と補うのは、長く担当している職員です。担当が替わると、最初の数か月は見込みが大きく外れます。 なぜその量にしたのかが残っていません。
(d)大口の予定と平常の動きが混ざっている。 前年の同じ日に大口の決済があった支店は、その年だけの動きが「毎年の山」に見えます。 大口の予定を聞いても、過去の表のどの日が大口だったかが分からないので、差し引けません。
- 【人】 支店の役席が、大口の予定(日・入りか出か・おおよその額)を大口の予定の表に入れる。過去の大口の実績にも印を付ける
- 【自動】 毎月の10日と25日の朝、Python が情報系から支店ごと・取引の種類ごとの日次の集計を読み込む
- 【自動】 営業日の暦を作り、各営業日に「月末から何営業日目か」「給与の日の位置」「年金の支払日の位置」を付ける
- 【自動】 過去の大口の実績を差し引いた平常の動きで学習したモデルで、翌期の営業日ごとの純流出と現金の純払出しを、中央と上振れで予測する
- 【自動】 大口の予定を足し戻し、支店ごとの現金の準備の量の案と、全店の合計の流出の山の日を出す
- 【人】 業務の担当が、印の付いた支店(年金の支払日の上振れが大きい、大口の予定が未入力など)を中心に見て、現金の準備の量と現送の予定を決める
- 【人】 資金の担当が、全店の合計の山の日を見て、資金の手当てを決める
1番目の大口の印が、この設計の土台です。 過去の記録のどの日が大口だったかが分からないと、モデルは1回きりの大口を毎年の山として覚えます。 最初の作業は、過去2年分の大口の実績に印を付けることです。
6番目と7番目で決めるのは人です。 モデルが出すのは量の案で、現金をいくら運ぶか、資金をどう手当てするかは、金庫の方針と当日の市場の状況を知っている担当が決めます。
02今回想定するシステム構成
情報系のデータベース(支店・取引の種類ごとの日次の入出金の集計) + 大口の予定と過去の大口の実績(支店の役席が入れる表) + 営業日の暦(祝日の CSV と金庫の休業日)+ 年金の支払月 │ ▼【トリガー】毎月10日と25日の朝(業務の端末の定時実行) Python(pandas) ├──▶ 営業日の位置(月末・給与・年金)を付ける ├──▶ 過去の大口の実績を差し引き、平常の動きにする ▼ scikit-learn(HistGradientBoostingRegressor) │ 翌期の営業日ごとの純流出・現金の純払出し:中央・上振れ(分位点) ▼ Python ── 大口の予定を足し戻し、現金の準備の量の案と全店の山の日 ▼ 【人】業務の担当が現金の準備を、資金の担当が資金の手当てを決める
| 役割 | 想定する製品 | 代替候補 |
|---|---|---|
| 実行環境 | Python(pandas・scikit-learn) | R、SAS |
| 処理エンジン | scikit-learn の HistGradientBoostingRegressor(分位点損失) | LightGBM、statsmodels |
| 集計 | Python(営業日の位置の付与、大口の差し引きと足し戻し、全店の積み上げ) | 情報系のデータベースの SQL |
| 保管 | 情報系のデータベース(予測の結果と実績)、スプレッドシート(大口の予定、現金の準備の表) | - |
新しく足すのは、Python の処理と、大口の予定・実績の表、営業日の暦の表です。 勘定系と情報系はこれまでどおりで、この構成は勘定系に何も書き込みません。 出すのは量の案と山の日の一覧です。
予測のエンジンに HistGradientBoostingRegressor を選んだのは、分位点の損失で幅を出せるからです。 純流出は流入が多い日には負の値になるので、0以上の値を求めるポアソン損失は使えません。loss="quantile" は負の値も扱え、quantile で何分位を出すかを指定できます。 中央は0.5、現金の準備には0.9を使います。
金庫の外にデータを出しません。 予測は金庫の中の業務の端末か情報系のサーバーで動かし、生成AIや外部のサービスは使いません。 扱うのは支店ごとの合計の数で、顧客ごとの記録は使いません。
03どうやって実装するのか
処理の起点を決める
毎月10日と25日の朝に動かします。 10日の実行で当月の後半(16日から月末と翌月の初めの数営業日)を、25日の実行で翌月の前半(1日から15日と、その月の年金の支払日)を見込みます。現送の依頼を前もって出せる時期に、半月ずつ区切るためです。 業務の端末の定時実行の仕組みで、日次の締めの集計が情報系に入った後の時刻に起動します。
10日や25日が休業日の月は、前の営業日に動かします。 営業日の暦の表を見て、その日が休業日なら前の営業日に実行するよう、起動の時刻に毎朝チェックだけを走らせます。
月に1回、モデルを作り直します。 毎月の最初の実行の前に、先月までの記録で学習し直し、作り直す前と後で、先月の当たり方を比べた結果を残します。悪くなっていれば、前のモデルのまま使います。
結果の表には作った日時と、使った記録の最終日を必ず印字します。 日次の締めが遅れた日に、前日までの記録で作った表を使わないためです。
入力データを集める
| データ | 中身 | 取得元 |
|---|---|---|
| 日次の入出金の集計 | 支店、営業日、取引の種類(窓口の現金・ATMの現金・振込・口座振替・給与の受け入れ・年金の受け入れ)ごとの入金と出金の額と件数 | 情報系のデータベース |
| 店舗外ATMの対応 | 出張所のATMと、その現金を受け持つ支店 | 業務の担当の表 |
| 大口の予定 | 支店、日、入りか出か、おおよその額、種類(法人の賞与・決済・公金) | 大口の予定の表(支店の役席が入れる) |
| 過去の大口の実績 | 支店、日、額、種類 | 大口の実績の表(新しく作る) |
| 営業日の暦 | 祝日、金庫の休業日(年末年始など)、各月の最終営業日 | 内閣府の祝日の CSV と金庫の休業日の表 |
| 年金の支払月と支払日 | 偶数月の15日。土日・祝日なら直前の平日 | 暦の表に組み込む |
質を決めるのは、過去の大口の実績と、取引の種類の分け方です。 大口の実績が無ければ、1回きりの動きが平常の山として学習されます。取引の種類を合計で持つと、年金の受け入れと現金の払出しの関係が見えません。
顧客ごとの記録は使いません。 集計は支店・営業日・取引の種類ごとの合計で、どの顧客がいくら動かしたかは、この構成には入りません。 大口の予定の表にも、顧客名ではなく種類とおおよその額だけを入れます。
年金の支払日は、日本年金機構の説明に沿って暦に組み込みます。 年金は原則として年6回、偶数月の15日に支払われ、15日が土日または祝日のときは、その直前の平日に支払われるとされています。各支払月には、原則として前月までの2か月分が支払われます。「原則」とあるので、暦の表には年金の支払日を機械で決めた日として入れたうえで、業務の担当が年金の振込のデータが届いた日と毎回見比べます。 食い違えば、暦の表のほうを直します。
データの取得方法を決める
| 取るもの | どこから | 何に使うか |
|---|---|---|
| 日次の集計 | 情報系のデータベースから、読み取りだけの権限で SQL で取る | 目的の値と、過去の動きの項目 |
| 大口の予定・実績 | 共有の表から読む | 差し引きと足し戻し |
| 祝日 | 年に1回、内閣府の CSV を入れ替える | 営業日の暦 |
| 金庫の休業日 | 業務の担当の表 | 営業日の暦 |
情報系への接続は、読み取りだけの専用の権限にします。 取るのは集計の表だけで、明細の表への権限は付けません。 権限を絞っておけば、スクリプトの誤りで顧客の明細を読むことがありません。
祝日の CSV は、翌年の分が前の年の2月に載るとされています。年に1回、2月に入れ替え、年末年始の休業日など金庫の休業日は、業務の担当が別の表で持ちます。 暦の表に翌期の分が無ければ、実行を止めて知らせます。
AIへ渡す前に整形する
- 営業日だけの並びにする … 支店・営業日ごとに1行にします。休業日の行は作りません
- 店舗外ATMを支店に寄せる … 出張所のATMの入出金を、現金を受け持つ支店に足します
- 大口を差し引く … 過去の大口の実績の日の額を、その支店のその日の動きから引きます
- 目的の値を作る … 純流出=(出金の合計)-(入金の合計)、現金の純払出し=(窓口とATMの現金の出金)-(現金の入金)
- 営業日の位置を付ける … 月の最終営業日から数えて何営業日前か、月初から何営業日目か、25日(休日なら前の営業日)からの営業日の差、年金の支払日からの営業日の差、連休の前後の印
- その他の項目 … 支店、曜日、月、賞与の時期の印、年金の支払月か、直近の同じ位置の平均、前年の同じ位置の値
- 支店・曜日を Categorical にする … pandas の Categorical の型にしておけば、既定の設定でカテゴリとして扱われます
5番目が、この構成の肝です。 「25日」という暦の日ではなく、「給与の日から何営業日後か」で表せば、25日が日曜の月も月曜の月も、山の形が同じ位置にそろいます。 年金の支払日も同じです。給与の日を前の営業日に寄せるのは多くの会社の扱いですが、後ろに寄せる会社もあります。 どちらに寄るかは決め打ちせず、「25日の前の営業日」と「後の営業日」の両方の差を項目にして、記録から学ばせます。
3番目を省くと、モデルは大口を覚えます。 前年の6月の月末に、ある法人の決済で数億円が出た支店は、今年の6月の月末にも同じ流出を見込みます。 差し引いた平常の動きで学習し、今年の大口の予定は後で足し戻します。
支店の統廃合で記録の続かない支店は、統合した日から先だけを使うか、統合した支店の合計に組み直します。 組み直したことは、表の上に印で出します。
AIに処理させる
させるのは、翌期の支店・営業日ごとの平常の純流出と現金の純払出しを、分位で予測することだけです。 目的の値ごとに2本ずつ、合わせて4本のモデルを作ります。
| 出すもの | 損失 | 使いみち |
|---|---|---|
| 純流出の中央 | loss="quantile"、quantile=0.5 | 全店の山の日の見込み |
| 純流出の上振れ(0.9) | loss="quantile"、quantile=0.9 | 資金の手当ての余裕 |
| 現金の純払出しの中央 | loss="quantile"、quantile=0.5 | 現金の準備の基準 |
| 現金の純払出しの上振れ(0.9) | loss="quantile"、quantile=0.9 | 現金の準備の量の案 |
現金の準備の量の案は、上振れに大口の予定を足した額にします。 中央で準備すると、2日に1日は足りない側に外れます。どの分位で準備するかは、現金を持ちすぎる負担と足りないときの手間を比べて、業務の担当が決めます。 0.9は出発点です。
全店の合計の上振れは、支店の上振れを足し合わせて作りません。 支店ごとの上振れが同じ日にそろって出るとは限らず、足し合わせると、全店では起きにくい大きさになります。 全店の合計は、全店の合計の動きで別にモデルを作って予測します。
| させないこと | 理由 |
|---|---|
| 資金の調達・運用の判断 | 金庫の方針と市場の状況で資金の担当が決める |
| 現送の量の確定 | 支店の金庫の容量と警備の都合で業務の担当が決める |
| 顧客ごとの流出の見込み | この構成は合計だけを扱う。個々の顧客への働きかけに使わない |
| 大口の予定の推測 | 支店の役席が聞いた予定だけを使う |
| 流動性の管理の方針の判断 | 金庫の規程と経営の判断 |
3行目は、とくに気を付けてください。 支店ごとの流出が大きく出ると、「どの顧客が出ていくのか」を調べたくなります。 この構成は合計の動きを見るためのもので、顧客ごとの記録は入れていません。取引先への働きかけは、別の判断と別の手続きで行います。
指示内容を固定する
生成AIを使わないので、プロンプトはありません。 かわりに、予測の中身を示します。
from sklearn.ensemble import HistGradientBoostingRegressor
from sklearn.model_selection import TimeSeriesSplit
FEATURES = ["branch", "weekday", "month", "bd_to_month_end", "bd_from_month_start",
"bd_from_payday_prev", "bd_from_payday_next", "bd_from_pension",
"is_pension_month", "is_bonus_season", "pre_long_holiday", "post_long_holiday",
"recent_same_pos_mean", "last_year_same_pos"]
# branch・weekday は pandas の Categorical にしておく
def make(q):
return HistGradientBoostingRegressor(
loss="quantile", quantile=q, max_iter=1000, learning_rate=0.03,
early_stopping=True, validation_fraction=0.15, random_state=0)
cash_mid, cash_up = make(0.5), make(0.9)
cash_mid.fit(train[FEATURES], train["cash_net_out_ex_large"]) # 大口を差し引いた現金の純払出し
cash_up.fit(train[FEATURES], train["cash_net_out_ex_large"])
# 当たり方は時系列の順を守って確かめる。検証の前に半月分の間を空ける
tscv = TimeSeriesSplit(n_splits=6, gap=24 * 10) # 24支店 × 10営業日分の行
TimeSeriesSplit は、時系列の順に並んだデータで、学習が常に検証より前になるように分けます。 公式の説明では、ふつうの交差検証は未来のデータで学習して過去で評価することになり不適切とされ、後の分割の学習は前の分割の学習を含みます。 gap で学習の末尾と検証の間を空けられ、本番では半月先を見込むので、検証でも半月分を空けます。 行を支店と営業日の順に並べ、全支店がそろった営業日ごとに行が等間隔になるようにしてから分けます。公式は、比べ方をそろえるには等間隔に並んでいることが要るとしています。
early_stopping を明示的に有効にしているのは、既定の 'auto' では学習の行が10,000を超えるときにしか有効にならないからです。 24支店で2年分あれば超えますが、支店を絞って試す段階では超えないことがあります。
欠けた値は埋めずに渡します。 開いて間もない支店は「前年の同じ位置の値」がありません。公式の説明では、HistGradientBoostingRegressor は欠けた値を分岐ごとに左右どちらへ送るかを学習するので、0で埋めて「前年は動きが無かった」と読ませるより実態に近くなります。
年金の支払日の効き方は、支店ごとに大きく違います。 年金の受取の口座の多い支店では現金の山が高く、事業所の多い支店では小さくなります。branch をカテゴリの項目にし、bd_from_pension との組み合わせを木に学ばせます。 支店ごとに別のモデルを作るより、記録の少ない支店でも他の支店の形を借りられます。
出力形式を固定する
業務の担当と資金の担当に渡すのは、次の2つの表です。
【支店ごとの現金の準備の案(1支店・半月分の例)】
| 営業日 | 位置の印 | 現金の純払出し(中央) | 上振れ(0.9) | 大口の予定 | 準備の量の案 | 印 |
|---|---|---|---|---|---|---|
| 14日(金) | 年金の支払日 | 3,800万円 | 5,200万円 | - | 5,200万円 | 年金:上振れ大 |
| 15日(月) | 年金の翌営業日 | 1,600万円 | 2,500万円 | - | 2,500万円 | - |
| 24日(金) | 給与の日(前寄せ) | 600万円 | 1,100万円 | 1,500万円 | 2,600万円 | 大口の予定あり |
【全店の流出の山の日】
| 営業日 | 位置の印 | 全店の純流出(中央) | 上振れ(0.9) | 大口の予定の合計 | 印 |
|---|---|---|---|---|---|
| 月の最終営業日 | 月末・口座振替 | 18.2億円 | 24.5億円 | 3.0億円 | 山 |
| 25日の翌々営業日 | 給与の後 | 9.6億円 | 13.1億円 | - | - |
金額は例示です。 実際の値は金庫の規模と支店の構成で大きく違います。
「印」の列で、担当が見る先を決めます。 年金の支払日の上振れが前回の実績を大きく超える支店には「年金:上振れ大」、大口の予定が入っている日には「大口の予定あり」、大口の予定の表が前回から更新されていない支店には「大口の予定未確認」、統廃合で記録を組み直した支店には「記録の組み直しあり」を出します。
機械で読む用には、同じ内容を情報系の予測の表に残します。 列は、支店、営業日、位置の印、中央・上振れ、大口の予定、準備の量の案、モデルの作成日、使った記録の最終日です。翌月に実績と並べて当たり方を見るのは、この表です。
システムへ連携する
| つなぎ先 | 方式 | 内容 |
|---|---|---|
| 情報系のデータベース | 読み取りだけの権限で SQL で集計の表を読む。予測の表にだけ書き込む | 日次の集計と、予測の結果 |
| 大口の予定・実績の表 | 共有の表を読む | 差し引きと足し戻し |
| 営業日の暦の表 | 共有の表を読む | 営業日の位置 |
| 現金の準備の表・資金繰りの表 | 書き込まない(担当が案を見て決める) | - |
| 勘定系 | 接続しない | - |
勘定系には接続しません。 日次の集計は、締めの後に情報系に入ったものを使います。予測のために勘定系に負荷をかけたり、権限を広げたりすることはしません。
人が確認する
- 作った日時と記録の最終日を見る … 締めの遅れで前日の記録が入っていない表を使わないためです
- 「大口の予定未確認」の支店に聞く … 予定の表の更新が漏れていないかを、支店の役席に確かめます
- 「年金:上振れ大」の支店の準備の量を決める … 支店の金庫の容量と警備の都合と合わせて、案のとおり準備するかを決めます
- 全店の山の日を資金の担当が見る … 上振れと大口の予定を足した額で、資金の手当てを決めます
- 予測の外の事情を足し引きする … 地元の大きな催し、取引先の工場の稼働の変化、他の金融機関の店舗の閉鎖
目標は、48件をならして1件7.5分です。 印の無い支店は案を写すだけで、時間を使うのは年金の支払月の上振れの大きい支店と、大口の予定のある日です。
例外に対処する
| 起きること | 対応 |
|---|---|
| 日次の締めが遅れ、前日の集計が入っていない | 実行を止めて担当に知らせる。古い記録で予測しない |
| 暦の表に翌期の祝日・休業日が無い | 実行を止めて知らせる |
| 大口の予定の表が前回から更新されていない | 予測は出し、「大口の予定未確認」 |
| システムの障害でATMが止まった日 | その日の現金の行を学習から外す。払出し0として学習しない |
| 支店の統廃合 | 統合した支店の合計に組み直し、印を付ける |
| 中央と上振れが交わる | 大きいほうを上振れとして使い、件数を記録 |
| 作り直したモデルが前より外れる | 前のモデルのまま使い、作り直しの記録を残す |
| 年金の振込の受け入れの日が暦の表の支払日と違う | 暦の表を直し、その月の予測をやり直す |
4行目を間違えると、山の読みが崩れます。 ATMの障害で払出しが止まった日を「払出し0」として学習すると、その日の翌日に引き出しが集中した記録とあわせて、山の位置を誤って覚えます。
記録を残す
- 実行の日時、使ったモデルの作成日、読み込んだ記録の期間と最終日
- 支店・営業日ごとの中央・上振れ、大口の予定、準備の量の案、印
- 業務の担当が決めた準備の量と、案から変えた理由
- 実績(純流出、現金の純払出し、追加の現送の有無)
- 月ごとの当たり方(中央の外れの大きさ、上振れを上回った日の割合)と、モデルの作り直しの結果
上振れを上回った日の割合は、0.9の線なら10営業日に1日ほどが目安です。 それより多ければ線が低すぎ、追加の現送が増えます。少なすぎれば現金を持ちすぎています。 どちらに寄せるかは、業務の担当がこの割合を見て決めます。
04実装レベルの3段階
本記事の想定は本格構成です。 半自動化では支店ごとの見込みまでで、大口の扱いと全店の積み上げは担当の手に残ります。 それでも見比べの時間は減りますが、第3章の(d)の問題は残ります。 半自動化で1件25分が15分ほどに、本格構成で7.5分になります。 差が大きいのは、大口の差し引きと準備の量への換算が、表があれば機械で出せる作業だからです。 段階を飛ばさないでください。 半自動化を2〜3か月回すと、どの支店のどの山が当たり、どこが外れるかが分かります。外れる支店の大口の印を直してから、本格構成に進みます。
05工数削減シミュレーション
導入後 48件 × 7.5分 ÷ 60 = 6 時間/月
自社条件で導入効果を整理したい方へ
このユースケースを自社に当てはめた場合の前提値と削減見込みを、業務ヒアリングをもとに整理します。
06向いている企業・向いていない企業
- 支店が十数から数十あり、月末・25日前後・年金の支払日に支店ごとの預金の流出と現金の払出しの山が来る信用金庫・信用組合。勘定系から支店ごと・取引の種類ごとの日次の入出金の集計を取り出せ、現金の準備の量と本部の資金繰りの見込みを、資金の担当と支店の役席が前年と先月の表を見比べて決めている場合。年金の受取の口座が多く、偶数月の支払日の現金の払出しが読み切れずに、現金の追加の手配が繰り返されている場合。
- 支店が数か店で、資金の担当が全店の動きを毎日見て足りている金融機関。勘定系から日次の集計を取り出す仕組みが無く、月次の残高しか使えない場合。合併や店舗の統廃合の直後で、支店ごとの記録が1年に満たない場合。なお、資金の調達・運用の判断、流動性の管理の方針、個々の取引先への働きかけは、この構成では代替できません。
07最小構成で試す方法
- 年金の受取の口座が多い支店と、事業所の多い支店を1つずつ選ぶ
- その2支店の過去2年分の日次の入出金の集計を書き出す
- 支店の役席の記憶と記録から、大口の実績に分かる範囲で印を付ける
- Python で第7章の設定を動かし、去年の4月・6月の年金の支払日と月末を「翌期」として予測させる
- 当時の現金の準備の量と、実際の払出しと、追加の現送の有無と並べる
2支店・2年分で十分です。 確かめたいのは、「営業日の位置で表すと、年金の日と月末の山が担当の見当と同じくらい読めるか」です。
| 出てきた内容 | 判断 |
|---|---|
| 年金の日と月末の山の高さと位置が当時の実績と合う | 全支店に広げ、大口の予定の表を始める段階に進む |
| 山の位置は合うが、特定の月だけ大きく外れる | 大口の印の漏れを疑う。その月の大口を支店に聞き直す |
| 山の位置が1〜2日ずれる | 営業日の位置の項目が暦の日のままになっていないかを確かめる |
2行目は、ほとんどの支店で一度は出ます。 失敗ではなく、大口の実績の記録がどれだけ抜けていたかが数字で分かったということです。
08実装時につまずきやすいポイント
| 問題 | 対策 |
|---|---|
| 暦の日で学習して山の位置がずれる | 営業日の位置(月末・給与・年金からの営業日の差)で表す |
| 1回きりの大口を毎年の山として覚える | 過去の大口の実績に印を付けて差し引く |
| 給与の日の寄り方を決め打ちする | 前と後の両方の差を項目にして記録から学ばせる |
| 純流出にポアソン損失を使う | 負の値になる。分位点の損失を使う |
| 支店の上振れを足して全店の上振れにする | 全店の合計は別のモデルで予測する |
| ふつうの交差検証で当たり方が良く見える | TimeSeriesSplit で学習を検証より前にし、半月分を空ける |
| ATMの障害の日を払出し0で学習する | その日を外す |
| 店舗外ATMを別の店として扱う | 現金を受け持つ支店に寄せる |
| 統廃合の前後で記録が切れる | 統合した支店の合計に組み直す |
| 締めの遅れた日に古い記録で予測する | 記録の最終日を印字し、足りなければ止める |
| 顧客ごとの記録を読める権限で接続する | 集計の表だけを読む権限にする |
上の3行が、この構成の失敗のほとんどです。 どれも、金融機関の資金の動きが暦ではなく、営業日と決まった支払いの日に縛られていることから起きます。ここを押さえれば、残りは他の予測と同じ注意で足ります。
4行目と5行目は、作ってから気づくことが多い失敗です。 ポアソン損失は目的の値が0以上であることを求めるので、純流出に使うと流入の多い日でエラーになるか、流入の日を外した偏った学習になります。全店の上振れを支店の上振れの和で出す誤りは、エラーにならずに通ります。 和で出した山は大きすぎ、資金を必要以上に手当てすることになります。どちらも、最初の検証の段階で全店の上振れを上回った日の割合を見れば気づけます。
下の方の行は、運用の決まりで防ぐものです。 記録の最終日の印字と、集計の表だけを読む権限は、最初の設計で入れておかないと、後から足すのが難しくなります。 動き始めてから権限を絞ると、それまで動いていた処理が止まるからです。
09セキュリティ・AIガバナンス上の注意点
この構成で扱うデータ: 支店ごと・取引の種類ごとの日次の入出金の合計、大口の予定(種類とおおよその額)、営業日の暦です。元になる勘定系と情報系には顧客ごとの取引の記録があり、接続の仕方を誤るとそれに触れます。
- 集計の表だけを読む … 情報系への接続は読み取りだけの専用の権限にし、明細の表への権限を付けません
- 顧客ごとの見込みに使わない … この構成は合計の動きを見るためのもので、個々の顧客の預金の流出を見込んだり、それをもとに働きかけたりする用途には使いません
- 大口の予定の表に顧客名を書かない … 種類とおおよその額だけを入れます。誰の取引かは支店の中にとどめます
- データを金庫の外に出さない … 予測は金庫の中の端末かサーバーで動かし、生成AIや外部のサービスに記録を送りません
- 判断は人が行う … 現送の量、資金の手当て、流動性の管理は、担当と金庫の規程で決めます。モデルの案をそのまま確定させる仕組みにしません
- モデルの管理の手続きに乗せる … 当たり方の記録、作り直しの履歴、外れたときの対応を残し、金庫のモデルの管理やシステムの規程に沿って承認を受けてから使います
誤りが起きた場合のリスクは、現金が足りずに窓口とATMで払出しに応じにくくなることと、資金の山を読み違えて手当てが遅れることの2つです。 前者は年金の支払日の上振れと大口の予定で、後者は全店の別のモデルと人の確認で抑えます。
10まず何から始めるか
1週目:営業日の暦を作る
祝日の CSV と金庫の休業日から、過去2年と翌年の営業日の暦を作ります。各営業日に、月の最終営業日・25日の前後の営業日・年金の支払日の位置を付けます。
2週目:大口の実績に印を付ける
2支店について、過去2年分の大口の実績を、支店の役席の記録と記憶から拾います。全部はそろわなくてかまいません。 拾えた分で始めます。
3週目:2支店で試す
第8章のとおり、去年の年金の支払月と月末を予測させ、当時の準備の量と実績と並べます。
4週目:情報系の権限と使い方の決まりを決める
システムの担当と、集計の表だけを読む権限の作り方を決めます。あわせて、どの分位で準備するか、誰が当たり方を確かめるかを、業務の担当と資金の担当で決めます。
2か月目以降: 全支店に広げて半自動化の表を出し、担当はこれまでどおり自分で決めながら、表と見比べます。 3か月分の当たり方がそろったら、大口の差し引きと準備の量の案を足します。担当が印の付いた支店だけを見て現金の準備を決められるようになり、当日の追加の現送が月に数えるほどになった時点で、この構成は完成です。
11関連ユースケース
12この仕組みを理解するための記事
13技術仕様の確認日・参考情報
| 確認した内容 | 情報源 | 確認日 |
|---|---|---|
HistGradientBoostingRegressor の loss に 'quantile'(ピンボール損失)があり quantile で分位を指定すること、'poisson' は目的の値が0以上であることが要ること。categorical_features の既定が 'from_dtype' であること。欠けた値を分岐ごとに左右どちらへ送るか学習すること。early_stopping='auto' は行が10,000を超えるときに有効になること(版 1.9.1) | scikit-learn: HistGradientBoostingRegressor | 2026-10-28 |
TimeSeriesSplit が時系列の順に並んだデータで学習を検証より前に分け、ふつうの交差検証は未来で学習して過去で評価するため不適切とされること。後の分割の学習が前の分割の学習を含むこと。gap で学習の末尾から除く数を指定できること。比べ方をそろえるには等間隔に並んでいることが要ること | scikit-learn: TimeSeriesSplit | 2026-10-28 |
| 年金が原則年6回、偶数月の15日に支払われ、15日が土日または祝日のときは直前の平日に支払われること。各支払月に原則として前月までの2か月分が支払われること | 日本年金機構: 年金はいつ支払われますか。 | 2026-10-28 |
| 国民の祝日の CSV が昭和30年から令和9年までを収録し、翌年の分を前年の2月に掲載するとされていること | 内閣府: 国民の祝日について | 2026-10-28 |
資金の調達・運用、現送の量、流動性の管理は、金庫の規程と担当の判断で行ってください。 本記事は公開されている仕様で確認できた範囲だけを扱っています。
実装ステータス:構成例。 公開仕様に基づいて設計した構成であり、当社で実際に構築・検証したものではありません。工数の数値はモデル条件による試算です。
自社の業務に使えるAI活用候補を整理します
このユースケース(UC-2221)についてのご相談はこちらから。
