このシリーズで繰り返し現れた厄介者がいます——遷移(過渡)モードです。


FGMMもHMMも、定常モードの監視は得意でした。しかし起動・停止・グレード切替の最中——システムがモードAからモードBへ移っている過渡状態——では、どの定常モデルにも当てはまらず、誤報の温床になります。誤報が積み重なればオペレーターはアラートを無視し、本物の異常を見逃す。マルチモード監視の実用化を阻む、最大の難所です。
この記事は、その遷移モードに正面から取り組みます。アイデアは3つ——遷移を独立モードとして扱う、適応(再帰)PCAでモデルを少しずつ更新する、そして本命のJust-in-Time(JIT)局所モデリングです。

上図のように、運転点はモードA(青)とモードB(緑)の間を、遷移(橙)を通って行き来します。遷移は正常な過渡です。これを異常としないことが、本記事のゴールです。
この手法が効く場面は明確です。
- 起動・停止が頻繁なバッチプロセス: 過渡が運転時間の多くを占める系
- グレード切替のある連続プロセス: 製品切替で運転点が大きく動く系
- 負荷追従運転: 需要に応じて運転点が連続的に変わる設備
この記事の内容
- なぜ定常モデルは遷移で破綻するのか
- 対策1:遷移を独立の「遷移モード」として扱う
- 対策2:適応(再帰)PCA — モデルを少しずつ更新
- 故障と遷移を取り違えるジレンマ
- 対策3:Just-in-Time局所モデリング — スケジューリング変数に基づく局所モデル
- NumPy実装 — 定常のみモデル(誤報率0.156・AUC0.69)に対しJIT局所モデル(誤報0.03・AUC0.99)の効果を実測
前提知識


1. なぜ定常モデルは遷移で破綻するのか
マルチモード監視の素直な実装は、「各定常モード(A, B)の正常範囲を学び、そこから外れたら異常」です。ところが遷移期のデータは、AでもBでもない中間の運転点にあります。

上図の赤い楕円は、定常データ(A, B)だけで作った正常範囲です。橙の遷移点は、この楕円の外側に落ちます。モデルから見れば「見たことのない運転点」——だから異常と誤判定します。しかし実際には、これは正常な過渡にすぎません。
問題の本質は、定常モデルが「運転点は2か所(AとB)にしか存在しない」と仮定していることです。現実には運転点はAとBの間を連続的に動きます。この連続的な軌跡をモデルに教えなければ、過渡はすべて異常に見えてしまいます。
では、どう教えるか。3つのアプローチを順に見ます。
2. 対策1:遷移を独立の「遷移モード」として扱う
もっとも直接的な対策は、遷移区間そのものを1つのモードとして学習することです。

モードA・モードBに加えて「遷移モード」の専用モデルを用意し、過渡のデータをそこで学習します。こうすれば遷移期も正常範囲を持てます。
シンプルですが弱点もあります。遷移の経路が複数あったり(A→B、B→A、A→C…)、遷移ごとに微妙に違ったりすると、遷移モードの数が爆発します。また「いつ遷移モードに切り替えるか」の判定自体が難しい。より柔軟な方法が要ります。
3. 対策2:適応(再帰)PCA
運転点がゆっくり連続的に変わるなら、モデルを少しずつ更新し続けるのが自然です。これが適応(再帰)PCA / 適応モデルです。

忘却係数 $\lambda$ で、平均と共分散をオンライン更新します。
$$ \begin{equation} \mu_t = (1-\lambda)\,\mu_{t-1} + \lambda\, x_t, \qquad \Sigma_t = (1-\lambda)\,\Sigma_{t-1} + \lambda\,(x_t – \mu_t)(x_t – \mu_t)^\top \end{equation} $$
$\lambda$ が大きいほど速く新しい運転点に追従し、小さいほどゆっくり。これで「ゆっくりした運転点の変化」には追従できます。
しかし、ここに深刻なジレンマが潜んでいます。

適応が速すぎる($\lambda$ 大)と、故障による変化まで「新しい正常」として吸収してしまい、故障を見逃します。 逆に適応が遅すぎる($\lambda$ 小)と、遷移に追従できず誤報します。「正常な運転点変化には追従し、故障には追従しない」を両立させる $\lambda$ を選ぶのは、本質的に困難です。
この困難を解く鍵は、「正常な運転点変化」を時間でなく運転状況そのもので説明することです。それがJIT局所モデリングです。
4. 対策3:Just-in-Time局所モデリング
適応PCAの問題は「時間」で適応することでした。代わりに、いまの運転状況(スケジューリング変数)に応じて、その場で局所的な正常モデルを作る——これがJust-in-Time(JIT)局所モデリング(遅延学習、局所モデリングとも)です。
多くのプロセスには、運転点を駆動するスケジューリング変数 $L$ があります。負荷指令、setpoint、生産量など、運転状況を表すゆっくり動く変数です。

$L$ が分かれば、遷移は「$L$ が中間値を取っている状態」にすぎません。JITのアイデアは、クエリ点が来るたびに、過去の正常データから $L$ が近いものを集め、その局所集合で正常モデル(局所ガウス/局所PCA)を作ることです。

遷移中のクエリ点(赤星)に対しても、$L$ が近い過去の正常な遷移点が近傍として集まり、そこに局所モデル(緑の楕円)が当たります。だから遷移点も正常な局所モデルでカバーされ、誤報しません。一方、その局所モデルから外れる本物の故障は、ちゃんと検出されます。

各 $L$ の値ごとに局所モデルを当てれば、軌跡全体(遷移を含む)が滑らかにカバーされます。これは前々記事の「条件付き」の発想を、明示的なモデルを持たずに局所データで実現したものとも言えます。実装で効果を確かめます。
5. NumPy実装 — JIT局所モデルで遷移を誤報しない
スケジューリング変数 $L$ が運転点を動かすプロセスを作ります。$L$ は台形波で、モードA定常 → 遷移 → モードB定常 → 遷移、を繰り返します。
import numpy as np
def path(L): # L:0..1 でA→Bへ動く正常な軌跡(2次元)
x1 = -2.0 + 4.0 * L
x2 = 1.6 * np.sin(np.pi * L) - 0.5 + 0.8 * L
return np.stack([x1, x2], -1)
def make_data(seed=0):
rng = np.random.default_rng(seed); Ls = []; N = 5000
while len(Ls) < N:
Ls += [0.0] * rng.integers(60, 140) # モードA定常
Ls += list(np.linspace(0, 1, rng.integers(40, 80))) # 遷移A→B
Ls += [1.0] * rng.integers(60, 140) # モードB定常
Ls += list(np.linspace(1, 0, rng.integers(40, 80))) # 遷移B→A
L = np.array(Ls[:N]); X = path(L) + rng.normal(0, 0.18, (N, 2))
phase = np.where(L < 0.05, 0, np.where(L > 0.95, 2, 1)) # 0=A,1=遷移,2=B
return X, L, phase, rng
X, L, phase, rng = make_data(0)
n_tr = 3500
Xtr, Ltr = X[:n_tr], L[:n_tr]
Xte, Lte, phte = X[n_tr:].copy(), L[n_tr:], phase[n_tr:].copy()
故障を、正常軌跡から外れる形で注入します(遷移中も含む各所に)。
label = np.zeros(len(Xte), int)
cand = rng.choice(np.arange(10, len(Xte)-3), size=60, replace=False)
for st in cand:
off = rng.normal(0, 1, 2); off = off / np.linalg.norm(off) * 0.75 # 軌跡から外す
Xte[st] = path(Lte[st]) + off + rng.normal(0, 0.18, 2); label[st] = 1
2つの監視を比べます。(1) 定常のみモデル(A・Bの定常データで単一ガウス)、(2) JIT局所モデル($L$ の近傍で局所ガウス)。
# (1) 定常のみモデル
steady = phase[:n_tr] != 1
mu_s = Xtr[steady].mean(0); inv_s = np.linalg.inv(np.cov(Xtr[steady].T))
s_steady = np.einsum("ij,jl,il->i", Xte - mu_s, inv_s, Xte - mu_s)
# (2) JIT局所モデル: L の近傍 k 点で局所ガウス
k = 80
order = np.argsort(Ltr); Ls_sorted = Ltr[order]; Xs_sorted = Xtr[order]
s_jit = np.zeros(len(Xte))
for i in range(len(Xte)):
pos = np.searchsorted(Ls_sorted, Lte[i])
lo = max(0, min(pos - k // 2, len(Ls_sorted) - k)); hi = lo + k
loc = Xs_sorted[lo:hi]
mu = loc.mean(0); cov = np.cov(loc.T) + 1e-3 * np.eye(2)
diff = Xte[i] - mu
s_jit[i] = diff @ np.linalg.inv(cov) @ diff
def auc(score, y):
order = np.argsort(score); ranks = np.empty(len(score)); ranks[order] = np.arange(1, len(score)+1)
npos = y.sum(); nneg = len(y) - npos
return (ranks[y==1].sum() - npos*(npos+1)/2) / (npos*nneg)
# 遷移期の誤報率(正常な遷移点で、各モデルの95%点を超える割合)
norm_trans = (label == 0) & (phte == 1)
far_s = (s_steady[norm_trans] > np.percentile(s_steady[label==0], 95)).mean()
far_j = (s_jit[norm_trans] > np.percentile(s_jit[label==0], 95)).mean()
print(f"定常のみ : 故障AUC={auc(s_steady,label):.3f} 遷移誤報率={far_s:.3f}")
print(f"JIT局所 : 故障AUC={auc(s_jit,label):.3f} 遷移誤報率={far_j:.3f}")
実行結果(seed固定):
定常のみ : 故障AUC=0.692 遷移誤報率=0.156
JIT局所 : 故障AUC=0.990 遷移誤報率=0.030

時系列で見ると一目瞭然です。上段の定常のみモデルは、遷移期(黄帯)のたびにスコアが大きく持ち上がり、正常な過渡を異常と誤報しています。本物の故障(赤点)はその誤報の山に埋もれます。下段のJIT局所モデルは、遷移期も静かで、故障だけがくっきり突出します。

数字の読み取りです。
- 遷移期の誤報率:0.156 → 0.030:JITは遷移期の誤報を約1/5に減らしました。正常な過渡を、$L$ が近い過去の遷移データで正しく「正常」と認識するからです。
- 故障検知AUC:0.692 → 0.990:定常のみモデルは遷移期の誤報で故障が埋もれAUCが伸びませんが、JITは遷移を説明できるぶん、故障だけを鋭く捉えます。
教訓は明快です。遷移を「異常」でも「やっかいな例外」でもなく、スケジューリング変数で説明できる正常な運転点変化として扱う。 そうすれば、過渡の誤報を抑えながら本物の故障を捉えられます。これは、操作・運用で動いた分を条件(ここでは $L$ の局所近傍)で吸収するという、本シリーズ共通の原理の、もっとも実務的な現れです。
6. まとめ — シリーズの締めくくり
マルチモード監視の最難所である遷移(過渡)の異常検知を見てきました。
- 問題:定常モデルは「運転点は定常モードにしか存在しない」と仮定するため、過渡を誤報する。
- 対策1:遷移を独立モードとして学習(経路が多いと破綻)。
- 対策2:適応(再帰)PCA(速い適応は故障を吸収、遅い適応は遷移を誤報するジレンマ)。
- 対策3:JIT局所モデリング。スケジューリング変数 $L$ の近傍で局所モデルを作り、遷移を正常な運転点変化として扱う。
- 実証:定常のみ(誤報0.156・AUC0.69)に対し、JIT局所(誤報0.03・AUC0.99)。
このマルチモード3部作(FGMM=空間クラスタ、HMM=時間追跡、JIT=遷移の局所化)と、先のCPS/制御系4本(残差・状態遷移・適合性・条件付きフロー)を合わせ、「運用・操作で動いた分を異常としない」という一つの原理を、9本の記事で多面的に掘り下げてきました。すべては親サーベイに地図としてまとまっています。



主な参考文献
- W. Li, H. H. Yue, S. Valle-Cervantes, S. J. Qin, “Recursive PCA for adaptive process monitoring,” Journal of Process Control, 10(5), 471–486, 2000.
- S. J. Qin, “Survey on data-driven industrial process monitoring and diagnosis,” Annual Reviews in Control, 36(2), 220–234, 2012.
- C. Cheng, M.-S. Chiu, “A new data-based methodology for nonlinear process modeling (Just-in-Time learning),” Chemical Engineering Science, 59(13), 2801–2810, 2004.
- X. Wang, U. Kruger, G. W. Irwin, “Process monitoring approach using fast moving window PCA,” Ind. Eng. Chem. Res., 44(15), 5691–5702, 2005.