【検証：GPT-4o】Assistantsで時系列異常検知 ②多変量データ

本記事は[【検証：GPT-4o】Assistantsで時系列異常検知](https://qiita.com/motonobu_ut/items/31884a184721c0c32ac3)の多変量版です（本記事のみで完結した内容になっています）。

# はじめに
ChatGPTといった大規模言語モデル(LLM)の発展に伴い、一部のデータ分析はノーコードのエージェントに置き換えられる可能性があります。エージェントによる自動化のユースケースの一つとして、可視化されたグラフ画像を見た担当者が、異常を感じ取り、詳細な数値データで原因を特定するといったシナリオが想定されます。
今回はGPT-4o[[参考1](#参考)]をベースとしたAssistants[[参考2-4](#参考)]を使って、多変量時系列データの異常検知タスクについて、テキスト入力・画像入力でどこまでやれるかを検証しました(2024/12時点では本記事の対象は二変量のみ)。

（今回の検証では1アシスタントに複数の候補処理を与えるのではなく、1アシスタントに1処理を与えて、適切に対応してくれるかを調べます）

# Assistantsに期待すること
OpenAIのAssistantsは、モデルなどのいくつかのパラメータを設定することで目的を遂行するエージェントを作成できます（詳細は[[参考2-4](#参考)]）。今回、モデルにはビジョン機能を備えた以下を選択します。

-	ChatGPT API (gpt-4o) [[参考1](#参考)]
-	ChatGPT API (gpt-4o-mini) [[参考5](#参考)]（比較用）

今回の検証でAssistantsに期待することは以下2点です。

**コーディング**
- テキスト指示により人がコーディングした処理を再現してくれる
- 結果の評価を自動で実行してくれる

**画像認識**
- 画像を読み取って提示する異常検知手法から適切なものを選択してくれる

# 問題設定
本記事では、可視化された時系列データを確認した担当者がその中に含まれている異常箇所を抽出するタスクを想定します(担当者は元の数値データにもアクセスできます)。

<img width="400" alt="図1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/892617/a6b5c3d7-2de1-3bb8-6e40-315816ec1265.png">

<strong>図1. 可視化された時系列データの確認イメージ</strong>

今回の検証では、タスクを「数値データからの検知」と「グラフ画像に含まれる異常の判別」の2種類に分け、それぞれ実験を行います。前者はベースラインとの比較、後者は想定する解答との比較、によって評価します。

検証の流れは以下の通りです。

1.	**データ作成**：多変量時系列データについて、典型的な異常を含んだデータを作成
2.	**ベースライン作成**：異常種類ごとに対応した異常検知手法(非深層学習)をコーディング
3.	**Assistants作成**：異常検知手法のテキストを設定したAssistantsとグラフ画像判定用のAssistantsを作成
4.	**実験と評価**：性能比較、Assistantsがグラフ画像で手法のあたりをつけられるかを確認
5.	**考察**：実験をする中で感じたことや結果についてコメント


# 1．データ作成

本検証では、多変量時系列異常検知に対応した手法を選定した上で、それぞれの手法に対応したデータを生成させる方針を取ります(選定理由は下部の補足に記載)。

**データ作成の流れ**
1.	ChatGPTを利用して、それぞれのモデルに適合する二変量時系列データを生成
2.	生成した二変量時系列データに、適当な異常を5％の割合で含むよう一部編集

今回の検証におけるデータ作成方法、および作成結果の図を以下に示します。

|二変量時系列データの作成結果|異常の説明とデータ作成方法|
|---|---|
|<img width="500" alt="shapelet.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/892617/00988334-0207-da06-e078-c23c6526d6a1.png">|**for Hotelling T2**　<br>- 2変量間の相関が大きく外れる外れ値<br>- 正の相関を持つ分布に異なる相関を持つ分布を異常値として追加し作成|
|<img width="500" alt="shapelet.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/892617/b7f8c77c-09a1-58e2-5360-79488f3dc2a2.png">|**for kNN**　<br>- 周辺の時間のデータと比較した際に大きく乖離する外れ値<br>- 同じ周波数の2つの正弦波に、それぞれノイズと外れ値用の乱数を加えて作成|
|<img width="500" alt="shapelet.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/892617/6fd0e55e-4289-1e5e-9456-f6a38635cc7a.png">|**for OCSVM**　<br>- 周辺の時間のデータと比較した際に大きく乖離する外れ値<br>- 異なる周波数の2つの正弦波に、それぞれノイズと外れ値用の乱数を加えて作成|
|<img width="500" alt="shapelet.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/892617/9a4a9d02-91b4-2de7-c3a8-c05dbd777177.png">|**for VAR**　<br>- 周辺の時間のデータと比較した際に大きく乖離する外れ値<br>- 周期的な波にノイズと外れ値用の乱数を加えて作成|

# 2．ベースライン作成
選定した異常検知手法を実装します[[選定理由](#補足)]。ハイパーパラメータは経験的に決定します。

**異常検知手法とハイパーパラメータ**
- **Hotelling T2**：percentile=0.95
- **kNN**：n_neighbors=2, percentile=0.95
- **OC-SVM**： kernel='rbf', nu=0.05, gamma=1
- **VAR**：　maxlags=5, percentile=0.95

```python:例：Hotelling T2のコード
import numpy as np
import pandas as pd
# 入力データからパラメータを計算
mean = df[['value1', 'value2']].mean().values # value1とvalue2の平均値を計算
cov = df[['value1', 'value2']].cov().values # value1 と value2 の共分散行列を計算
inv_cov = np.linalg.inv(cov) # 共分散行列の逆行列を計算
# テストデータに対するホテリングのT^2統計量を計算
values = df[['value1', 'value2']].values
T2_scores = [np.dot(np.dot((x - mean), inv_cov), (x - mean).T) for x in values]
anomaly_scores = np.array(T2_scores)
# 異常スコアの95パーセンタイルを閾値として設定
threshold = np.percentile(anomaly_scores, 95)
# 異常の検知
anomalies_detected = anomaly_scores > threshold
```

# 3．Assistants作成
### 3.1　検知用Assistants
<strong>2.</strong>の手法をテキスト化したものをinstructionsとして、Assistantsを4つ作成します (Assitantsについては[[参考6](#参考)]を参照、instructionsの作り方は[[参考7](#参考)]を参照)。

```markdown:例：Hotelling T2のinstructions
# Role: You are an AI anomaly detection analyst.
# Your task
## Progression
Perform the anomaly detection task according to the following strategy.
- 1. Read the data.
- 2. Detect anomalies with the 'value1' and 'value2' columns as inputs by using Hotelling T^2 method.
- 3. Compare and evaluate the detection results(AUC and F1-score) with the 'labels' column(anomaly target = 1).
## Output
- **AUC**: <analysis result>
- **F1-score**: <analysis result> - **detected index**: <analysis result>
```

### 3.2　グラフ画像判定用Assistants
異常検知手法をinstructionsに記載し、グラフ画像にどの異常検知手法が適切かを判定します(**適切な検知手法 Assistants**)。また、入力した画像から異常の割合を定量的に推定します(**異常割合 Assistants**)。

```markdown:グラフ画像判定用 instructionsイメージ
# Role
You have to estimate the anomalies in the graphs in the image. Explain which anomaly detection model you would prefer to apply, along with your rationale. Guess how many anomalies are contained in the image.
# Input three image data. Two-dimensional time series data containing <anomalies> or none at all.
# Input : Three image data
## Format: image file
## Variables: time, value1, value2
## File details: "time-value1 graph", "time-value2 graph", "value1-value2 graph"
# Type of Anomaly detection model: "Hotelling T^2", "KNN", "OCSVM", "VAR"
# Output:
- **Best model for detecting anomalies in the image**: <detection model>
- **Percentage of anomalies in the image**
```

# 4．実験と結果
作成したデータとグラフ画像を入力に、ベースライン、Assistantsの性能を確認しました。

### 検知結果（AUC, F1）　
検知結果（AUCとF1-score）について、それぞれのデータに対し、手入力でコーディングしたモデルとAssistantsとの比較を以下の表に示します(例えばfor HotellingT2の列では、「HotellingT2用のデータでHotellingT2モデルを実験している」ことを意味します)。

|検知結果（AUC）|for HotelligT2|for kNN|for OCSVM|for VAR|
|---|:-:|:-:|:-:|:-:|
|ベースライン(コーディング)      |*0.934*|**0.878**|**0.854**|**0.871**|
|検知 Assistants(GPT-4o)     |**0.942**|*0.863*|0.688|0.587|
|検知 Assistants(GPT-4o-mini)|0.816|0.830|0.676|0.520|

|検知結果（F1）|for HotelligT2|for kNN|for OCSVM|for VAR|
|---|:-:|:-:|:-:|:-:|
|ベースライン(コーディング)     |*0.660*|*0.680*|**0.612**|**0.480**|
|検知 Assistants(GPT-4o)     |*0.611*|*0.624*|0.318|0.228|
|検知 Assistants(GPT-4o-mini)|**0.670**|**0.703**|0.232|0.072|

### 画像判定結果　
||for HotelligT2|for kNN|for OCSVM|for VAR|
|---|:-:|:-:|:-:|:-:|
|異常割合 Assistants(GPT-4o)     |4%  |5-10%|3%|5-7%|
|異常割合 Assistants(GPT-4o-mini)|3-5%|5-15%|5%|5-10%|
|適切な検知手法 Assistants(GPT-4o)     |○|△|△|×|
|適切な検知手法 Assistants(GPT-4o-mini)|△|△|△|×|

※ 3回実行して、全て正解：○, 一回以上正解：△, すべて不正解：×

# 5．考察
- **コーディングによる検知性能について**
ホテリングのT2法、kNNの結果では、ベースラインと同等のスコアが得られています。解析手法が提案されている場合には、手によるコーディングをある程度再現できていると考えられます。この二つのモデルに関しては、基本的かつ代表的な異常検知の手法であるため、理論的な解析が多くなされていることから、知見が蓄積されているのではないかと思います。GPT-4oとGPT-4o-miniを比較すると、概ね似た傾向を示していますが、OCSVM、VAR等の複雑な処理を要する手法についてはGPT-4oに軍配が上がっています。
また、以前検証した単変量時系列データの異常検知[[参考8](#参考)]と同様、比較のためにinstructionsに何も設定しないAssistantsを用いて検証してみました。各データに対し3回実行しましたが、今回の検証においてはAUCとF1-scoreともに数値結果が得られませんでした。何かしら定量的な値を算出してくれるものと期待していましたが、異常検知の手法を提案してくれるばかりで、それ以上のことは難しいようです。
<br>

- **画像検知による検知性能について**
データに含まれる異常の割合については、バラツキはあるものの5％に近い値で推測できています。また、以前の検証と比較して、画像の認識能力も良いように思われます。gptのモデル性能が良くなっているというよりは、入力に各変量の時系列データおよび変量間の散布図を入力したため、総合的に異常の割合を算出できたものと考えられます。
また、あらかじめ検知手法を提示すれば適切な手法を選択してくれたことから、画像からデータの分布を認識できるように思われます(VAR用に作成したデータについては、頑なにOCSVMによる異常検知をお勧めしてくるので、より丁寧に指示する等の工夫が必要そうです）。

# まとめ
本記事では、二変量データを対象に、異常検知の性能をベースライン手法とGPT-4o（およびGPT-4o-mini）を活用したAssistantsで比較しました。その結果、以下のような知見が得られました。
-	**検知性能**：基本的な異常検知手法では理論的な解析に基づく再現性があり、人によるコーディングと同程度の結果を得られる可能性がある
-	**グラフ画像の認識**：データの分布を捉えられている印象があり、複数の入力を与えることで多角的に判別できる可能性がある
-	**その他**：複雑な指示に関してGPT-4oはGPT-4o-miniより柔軟に対応できる印象がある

# 参考
1. https://openai.com/index/hello-gpt-4o/
2. https://platform.openai.com/docs/assistants/overview
3. OpenAI Assistants apiとは？使い方や料金、Retrieval機能について紹介！https://aitechworld.info/assistants-api/
4. Azure OpenAI の Assistants API によるエージェント開発メモ① https://qiita.com/nohanaga/items/fa9f5260cf85a7fddc52
5. https://platform.openai.com/docs/models
6. https://cookbook.openai.com/examples/assistants_api_overview_python
7. https://speakerdeck.com/hirosatogamo/chatgpt-azure-openai-da-quan
8. https://qiita.com/motonobu_ut/items/31884a184721c0c32ac3


# 補足：異常検知手法の選定
検証にあたっては異常検知や時系列分析に用いられる代表的な手法を選定しました。以下にそれぞれの特徴を簡単にまとめました。

### ホテリングのT2法
異常検知において基礎的かつ代表的な手法です。データの平均と共分散を利用し、統計的に異常値を検出することができます。入力データが単一の正規分布に従うような場合にはとても有効な手法です。一方で、分布が複数ある、局所的に異常値がある場合においては正しく検知ができないこともあります。
### k近傍法(kNN)
ホテリングのT2法と異なり、データの分布仮定を必要としない手法です。判別するデータに対し、k個の近傍点との距離に基づいてスコアを計算するため、局所的な異常も検出することができます。しかし、データの分布を仮定しないために、kの値などハイパーパラメータを適切に決める必要があります。
### One Class SVM(OCSVM)
クラス分類に用いられるサポートベクターマシン(SVM)を応用した手法です。通常のSVMは二値（または多値）の分類を行うのに対し、OCSVMでは一つの入力データに基づいて、そのパターンから外れたデータを異常として検出します。
### ベクトル自己回帰モデル(VAR)
単変量時系列分析に用いられる自己回帰モデルを、多変量時系列データにも使えるよう一般化した手法です。モデルで予測したデータを入力データと比較することで異常を検出します。周期性がある時系列などデータ間に依存性があるようなデータに対して有効ですが、トレンドのような非定常的な変化に弱いなどの欠点もあります。