実案件/ポートフォリオ

勤怠・売上の異常検知は設計が9割|SLOとRules→Stats→MLで“静かな監視”を作る

異常検知は「驚きを、早く・静かに・正しく知らせる」ための仕組みづくり。

本記事は、勤怠/売上データの監視を“現場で使える形”に落とし込むための設計と実装テンプレをまとめました。結論から言うと、SLOを先に決め、Rules→Stats→MLの三層で小さく始め、運用でノイズを徹底的に減らすのが最短ルートです。

この記事でわかること

  • 勤怠/売上の監視でまず決めるべきSLOテンプレ
  • Rules(確定的な異常)→Stats(ロバストZ/STL)→ML(IsolationForest/OneClassSVM)の三層設計
  • 誤検知を抑える抑止窓・デダプ・Runbookの運用設計
  • コピペで動くPython実装(5分粒度の時系列前処理〜検知)

筆者コメント(ふみと)

データ/マーケ領域で10年、勤怠やEC売上の監視を数十案件で伴走しました。高度なアルゴリズムより効いたのは集計粒度の統一カレンダー抑止(祝日/連休/締め処理)、そしてアラートの単純化(1指標=1通知)。本記事ではその“現場の型”をテンプレ化しています。

監視の全体像:SLO → Rules/Stats/ML → 運用

Step1:SLO(何をどれだけ守るか)を先に決めます。次に、Step2:三層の検知で異常の取りこぼしと誤検知のバランスを取る。最後に、Step3:運用(抑止・デダプ・Runbook・通知窓口)でノイズを減らし“静かな監視”にします。

SLOテンプレ(すぐ使える例)

勤怠のSLO例

  • 目的:不正/ミスやシフト欠員を30分以内に検知
  • 指標:打刻の欠損率、日別総勤務時間早出/遅刻/早退件数、深夜残業時間
  • SLO:誤検知月3回以下、MTTD30分以下
  • 除外:会社休日/部署休業日/システムメンテ時

売上(EC)のSLO例

  • 目的:システム障害/在庫切れ/広告事故の急落15分以内に検知
  • 指標:5分売上CVRトラフィック在庫回転
  • SLO:Precision ≥ 0.8、Recall ≥ 0.6(主要障害を落とさない)

データ準備:粒度統一・欠損処理・カレンダー特徴

監視の8割は前処理で決まると言っても過言ではありません。まずは5分粒度に統一し、欠損や営業時間/祝日などの特徴量を付与します。

# 準備:5分粒度へのリサンプリング、祝日/営業時間フラグ
import pandas as pd

# df: DatetimeIndex、columns=\['sales','traffic','cvr'] 等

Five = df.resample('5T').sum(numeric\_only=True)
Five\['traffic'] = df\['traffic'].resample('5T').sum().fillna(0)
Five\['sales'] = df\['sales'].resample('5T').sum().fillna(0)

# カレンダー特徴(外部の社内CSVやAPIで統合)

Five\['dow'] = Five.index.dayofweek
Five\['hour'] = Five.index.hour

三層検知:Rules → Stats → ML

Rules(まず作る:確定的な異常)

「ゼロ売上が3連続」「勤怠CSV未着」「APIエラー率>5%」のような即断・説明可能なルールから着手します。

import pandas as pd
from pathlib import Path

def rule\_zero\_sales(df: pd.DataFrame, window=3):
z = (df\['sales'] == 0).astype(int)
streak = z.rolling(window).sum()
alert = streak >= window
return df\[alert]

def rule\_missing\_file(path: str):
p = Path(path)
return (not p.exists()) or (p.stat().st\_size == 0)

Stats(ロバストZ / STL)

外れ値に強いロバストZ(中央値・MAD)と、日内季節性を取り除くSTL分解で残差の外れを検知します。

import numpy as np
import pandas as pd
from statsmodels.tsa.seasonal import STL

def robust\_z(x: pd.Series):
med = np.median(x)
mad = np.median(np.abs(x - med)) or 1e-9
return 0.6745 \* (x - med) / mad

# ロバストZで急落のみ拾う例

z = robust\_z(Five\['sales'])
alerts\_z = Five\[z < -3.5]

# STL分解(5分×288=1日)

stl = STL(Five\['sales'], period=288)
res = stl.fit()
resid = res.resid
alerts\_stl = Five\[np.abs(robust\_z(resid)) > 3.0]

運用Tip

営業時間帯のみを判定対象にする/昼休み・閉店は抑止。しきい値はPrecision目標から逆算して決めます。

ML(IsolationForest / OneClassSVM)

多変量の相関を使って候補を拾い、Rules/Statsで再確認してから通知する二段構えが有効です。

from sklearn.ensemble import IsolationForest
from sklearn.svm import OneClassSVM
from sklearn.preprocessing import StandardScaler

feat = Five\[\['sales','traffic','cvr','hour','dow']].fillna(0)
X = StandardScaler().fit\_transform(feat)

# IsolationForest(軽量で堅牢)

iso = IsolationForest(n\_estimators=300, contamination=0.01, random\_state=42)
alerts\_iso = Five\[iso.fit\_predict(X) == -1]

# OneClassSVM(シャープだが調整が難しい)

oc = OneClassSVM(nu=0.01, kernel='rbf', gamma='scale')
alerts\_svm = Five\[oc.fit\_predict(X) == -1]

ユースケース:勤怠・売上での指標と検知

勤怠:未打刻/勤務時間逸脱/深夜残業の連続

未打刻はRulesで確定検知。勤務時間の逸脱は部署中央値との差をロバストZで評価します。

# attn: columns=['date','dept','work_hours', ...]
by_dept = attn.groupby(['date','dept'])['work_hours'].median().rename('dept_med')
X = attn.merge(by_dept, on=['date','dept'])
X['z'] = robust_z(X['work_hours'] - X['dept_med'])
alerts_attn = X[X['z'] > 3.5]

PII保護

氏名はハッシュ化、参照は最小権限、目的外の二次利用禁止。人事データの取り扱いは必ず社内規程に従ってください。

売上:ゼロ売上連続/CVR急落/トラフィック急落

CVR = sales / traffic(ゼロ割回避)の時系列で、移動平均からの偏差を監視します。

eps = 1e-9
Five['cvr'] = Five['sales'] / (Five['traffic'] + eps)
ma = Five['cvr'].rolling(288, min_periods=60).mean()
std = Five['cvr'].rolling(288, min_periods=60).std()
alerts_cvr = Five[(ma - Five['cvr']) > 3*std]

アラート運用:ノイズと疲弊を減らす設計

  • サプレッション:昼休み/閉店/締め処理の抑止窓を設定
  • デダプ:同一原因の連続通知は10〜30分で集約
  • 重大度:Rules > Stats > ML、S1/S2/S3を明記
  • 通知窓口:Slack #ops-alert や ops@ に一本化
  • Runbook:手順書URL・当番・エスカレーションを本文に同梱
[ALERT][S1] ゼロ売上が3連続(EC)
- 時刻: 2025-09-05 10:15 JST
- 影響: 決済/カート障害の可能性
- 対応: 1) ステータスページ確認 2) エラーログ検索 3) 決済ベンダーへ連絡
- Runbook: https://internal/wiki/alerts/zero-sales
- 抑止: なし

検知のKPIとチューニング

Precision(誤検知の少なさ)Recall(取りこぼしの少なさ)F1MTTDAlert/minを追いかけます。過去インシデントのラベルでバックテストし、しきい値や抑止窓を同時最適化します。

import numpy as np
import pandas as pd

ths = np.linspace(2.0, 4.0, 9)
rows = \[]
for t in ths:
pred = (np.abs(robust\_z(resid)) > t)
\# y\_true は 0/1 のラベル(ここでは擬似コード)
P = (pred & (y\_true==1)).sum(); FP = (pred & (y\_true==0)).sum(); FN = ((\~pred) & (y\_true==1)).sum()
prec = P / (P+FP+1e-9); rec = P / (P+FN+1e-9)
rows.append({"t"\:t, "precision"\:prec, "recall"\:rec, "alerts"\:int(pred.sum())})
res = pd.DataFrame(rows)

最小実装→運用のロードマップ

  • 監視ポリシー宣言:対象=勤怠/売上の時系列、方針=Rules→Stats→ML、抑止/デダプあり、SLO=Precision≥0.8・MTTD≤30分、体制=当番制度(平日9-18)
  • スケジュール:5分バッチ(集計→Rules→Stats)/30分バッチ(MLスコア)/毎朝(前日サマリPDF)
  • 可視化と共有:アラート件数・MTTD・Top原因・抑止状況のダッシュボード/週次レビューでルール更新

今日やること(60分)

  1. SLO/監視ポリシーを1ページにまとめて合意
  2. Rules(ゼロ売上連続/未打刻)を先に導入
  3. ロバストZ+STLで急落検知のプロトを作成(5分粒度)
  4. 抑止窓/デダプ/Runbookを整備し、週次レビュー開始

まとめ

設計が先、アルゴリズムは後。まずはSLOを明文化し、Rules→Stats→MLの順で最小構成を組む。運用で抑止とデダプを効かせ、Precision 0.8 を目標に静かな監視を実現しましょう。

伴走サポート

無料カウンセリング/体験で、監視対象の定義→三層検知→抑止/Runbook→自動化まで一気通貫で支援します。誤検知削減と検知速度のSLO達成を、現場起点で設計します。

TechAcademy データサイエンスコース(受講料:174,600円~ ※更に割引あり)

TechAcademy 無料相談

株式会社キカガク AI人材長期育成コース(受講料:237,600円~)

キカガク 無料相談

この記事から次に読むべきもの(内部リンク)

需要予測
コピペで動く需要予測|ARIMA×LightGBMでベースライン→運用まで

現場でちゃんと当たる需要予測って、どこから始めればいい? ベースライン→検証→運用まで、一気通貫で進める“型”で解説します。 この記事は、ARIMAとLightGBMを使った需要予測ミニプロジェクトの ...

データレポート納品
【保存版】データレポート納品の型:要件定義→ETL→検証→可視化→Excel/PDF→引き継ぎまで、失注しないワークフロー完全版

“いい分析”より“伝わる納品”。副業や実務で評価されるのは、意思決定に効く1枚と再現できるパッケージを期限通り出せること。 本記事は、未経験〜初学者が週10時間×2〜3週で、要件定義→データ受領→ET ...

自動化
“落ちない”社内自動化3選:再実行安全・ロック・JSONログで回す設計とテンプレ

社内の自動化、まず何から作ればいい? ちゃんと動き続けて、運用が楽になる設計が知りたい…! そんな悩みに対して、現場で短期に価値を出しやすい“3つの自動化”と、そのまま使える設計&コードの型をまとめま ...

自動化
自動化:スケジューリングと業務改善の型|「再実行安全×観測可能×静かに動く」を仕組みにする

夜中に動かしているPython、自動で止まってた…ログもなくて原因が追えない…。 「毎朝のレポート」や「在庫監視」を、壊れず静かに回したい…! 業務で落ちない自動化を作る鍵は、(1) 再実行安全(Id ...

スキルアップ
【実務で差がつく】pandas実践:欠損処理・結合・ウィンドウ関数・時系列・品質保証まで“読みやすく速い”型を習得

リード(結論)基礎を終えたら次は実務の現場で頻出する処理を“型”で覚える段階です。本記事は、pandas 2.x を前提に、欠損・外れ値・結合・ウィンドウ関数・時系列・カテゴリ処理・集計の自動化・大規 ...

機械学習
【保存版】scikit-learn基礎:回帰・分類・前処理・パイプライン・交差検証を“実務の型”で習得

機械学習で迷子になる最大の理由は、前処理→学習→評価→改善の順番が曖昧なまま個々のアルゴリズムに飛びつくこと。本記事は、未経験〜初学者が週10時間×2〜3週で到達できるscikit-learnの最短ル ...

モデル評価
【保存版】モデル評価:指標の選び方・交差検証・閾値最適化・ビジネス接続を“実務の型”で解説

精度が上がらない原因の多くは「評価設計の誤り」にあります。評価とは「何点取れたか」ではなく、意思決定に耐えるかを測る営み。この記事では、回帰/分類/ランキングの指標の選び方、交差検証の正しい使い分け、 ...

例外処理
Python実務の型:例外処理と構造化ログでエラーに強いコードを書く

例外処理って、結局どこまでやれば“実務で困らない”の? ログも整えるのって大変そう…最低限の型、ください! この記事は、pythonbunseki.comの実務トーンで「防ぐ→気づく→復旧する」をコー ...

最近のコメント

    • この記事を書いた人
    • 最新記事

    ふみと

    このブログでは、データサイエンティストとして市場価値を上げる方法を独自にまとめて発信しています。

    【プロフィール】
    ・大手企業データサイエンティスト/マーケティングサイエンティスト(10年、年収900万円台)/案件100件以上
    ・資格:JDLA E資格(日本ディープラーニング協会主催)/JDLA Community(CDLE会員)/Advanced Marketer/ビジネス統計スペシャリスト/統計検定2級/TOEIC 805
    ・スキル:Python/Tableau/SQL/機械学習/Deep Learning/RPA

    -実案件/ポートフォリオ