因果推論グラフを表示する(SPSS Modeler データ加工逆引き10-16)

# 因果推論グラフを表示する（Python for Spark拡張ノード）

PythonのCausalNexとpgmpyをつかって因果推論のグラフを書いてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/4fb23760-7fc4-3701-bdb4-16cfbd5067b4.png)

（この記事は2023年秋のSPSSユーザーイベント「ものづくり領域で活かされる　SPSS Modelerの今とこれから」でご紹介したデモの内容を少し深く説明しています。）

## 1.想定される利用目的

* フィールド間の因果関係の把握
* 原因、要因分析



## 2.サンプルストリームのダウンロード
* サンプルデータ

https://github.com/hkwd/210224PythonExtension/blob/master/240528causalnex_pgmpy/%E9%8B%B3%E9%80%A0%E4%B8%8D%E8%89%AF%E5%88%86%E6%9E%90.csv

* サンプルストリーム

https://github.com/hkwd/210224PythonExtension/raw/master/240528causalnex_pgmpy/%E9%8B%B3%E9%80%A0%E4%B8%8D%E8%89%AF%E5%9B%A0%E6%9E%9C%E6%8E%A8%E8%AB%96.str
* テスト環境
    * Modeler 18.5
    * Windows 11 64bit
    * causalnex-0.12.1
    * pgmpy-0.1.25
    * pyvis-0.3.2

## 3.サンプルストリームの説明

### 3.1. データ
鋳造の条件とNG判定の結果の入ったデータになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/362c046f-e33a-a60e-3182-e4026baadb0c.png)

### 3.2. CausalNex
以下の記事のコードを使ってCausalNexの因果推論のグラフを書いてみます。

https://cpp-learning.com/causalnex/

CausalNexは名義型の変数を使えないので、必要な変数はダミー変数化しています。
「データ型」ノードで「値の読み込み」を行い、フラグ設定ノードで「鋳型条件」を「1」「0」のダミー変数に変換しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/807f3b6f-55b4-3627-b886-f0d744316895.png)

カテゴリ型である「鋳型条件」「砂条件」は除外します。また、項目数が多いとグラフ見づらいので、NG判定に効果の大きそうな項目のみを「フィルター」ノードで絞りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/560d4616-353f-c88a-9555-5e4c7068aa65.png)

「拡張の出力」ノードで「Python for Spark」を選びシンタックスに入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/35a7e2f0-2ed6-b8ce-5e5d-c3140a1ba745.png)


ほぼ、[引用した記事](https://cpp-learning.com/causalnex/)そのままのコードなのでコードの内容はそちらをご覧ください。

ポイントはgetSparkInputDataで取ってきたデータをpandasのDataFrameに変換してfrom_pandasでDAG推定をしているところです。

```python
ascontext = spss.pyspark.runtime.getContext()
indf = ascontext.getSparkInputData()
df=indf.toPandas()

SM = from_pandas(df)
```

後は最後にグラフをshowしています。
```python
plt.show()
```

実行して、以下のように「グラフ出力」を開くとDAGのグラフが表示されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/ea9f45c0-ceba-9262-93b2-354a81bc55ac.png)

「鋳造条件_A」が「温度」や「電圧」に影響を与えています。
ただ、「NG判定」が「電圧」などに影響を与えているグラフになっているので、今回のグラフでは「NG判定」に影響を与える要因を特定することができませんでした。

### 3.3. pgmpy
以下の記事のコードを使ってpgmpyのBayesian Network(PCアルゴリズム)で因果推論のグラフを書いてみます。

https://kiseno-log.com/2021/07/09/python%E3%81%A7%E5%9B%A0%E6%9E%9C%E5%88%86%E6%9E%90%EF%BC%9Apgmpycausalnex/

PCアルゴリズムは、逆にカテゴリ型データの利用が基本なので、連続型変数はビニングして離散値化しています。
「データ分割」ノードで「ビンフィールド」に「温度」「圧力」「電圧」「速度」「回転数」の連続型変数をいれて、ここでは「4分位」でビニングしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/38c36aa6-f10a-8799-a0ad-309da0f46ede.png)

連続型である「温度」「圧力」「電圧」「速度」「回転数」は除外します。また、項目数が多いとグラフ見づらいので、NG判定に効果の大きそうな項目のみを「フィルター」ノードで絞りました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/7fde2c36-e99d-1d0c-bfba-bef9553b05f1.png)


「拡張の出力」ノードで「Python for Spark」を選びシンタックスに入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/534b16b9-d987-e136-b30d-ee9124cbcc5f.png)


ほぼ、[引用した記事](https://kiseno-log.com/2021/07/09/python%E3%81%A7%E5%9B%A0%E6%9E%9C%E5%88%86%E6%9E%90%EF%BC%9Apgmpycausalnex/)そのままのコードなのでコードの内容はそちらをご覧ください。

第一のポイントはgetSparkInputDataで取ってきたデータをpandasのDataFrameに変換してfrom_pandasでBayesian Network(PCアルゴリズム)のestimatorにセットをしているところです。

```python
ascontext = spss.pyspark.runtime.getContext()
indf = ascontext.getSparkInputData()
df=indf.toPandas()

pc = PC(df) # 離散値化後のデータセット
```

次に、Notebookには出力しないので、directed='True'のみを指定しています。
```python
#got_net = net.Network(notebook=True,directed=True)
got_net = net.Network(directed='True')
```

最後にhtmlで出力しています。"c:/temp2/pgmpy/example.html"というファイル名で出力しています。
```python
#got_net.show('gameofthrones.html')
#HTMLファイルの出力
html_filename="c:/temp2/pgmpy/example.html"
from IPython.display import display, HTML
html =got_net.generate_html()
with open(html_filename, mode='w', encoding='utf-8') as fp:
        fp.write(html)
print("'"+html_filename+"' was output.")
```

実行してもグラフ自体は表示されませんので、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/6576769b-970f-d5fb-80ee-8317b7ea0768.png)

フォルダからHTMLファイルをブラウザで開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/52f8b218-db75-90f1-4909-23a8ff16a78f.png)

以下のように「グラフ出力」を開くとベイジアンネットワークのグラフが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/8361920f-fbaa-73a1-56fe-4718356e4e5e.png)

以下のような因果が見えてきます。
「スイッチ２」→「砂条件」→「スイッチ１」→「鋳造条件」→「NG」
「スイッチ２」→「圧力_TILE4」→「鋳造条件」→「NG」
「スイッチ３」→「NG」


#### 注意事項

管理者権限でコマンドプロンプトを立ち上げて、pipでcausalnex、pgmpy、pyvisのパッケージをあらかじめ導入しておく必要があります。
```cmd
"C:\Program Files\IBM\SPSS\Modeler\18.5\python_venv\Scripts\python.exe" -m pip install causalnex
"C:\Program Files\IBM\SPSS\Modeler\18.5\python_venv\Scripts\python.exe" -m pip install pgmpy
"C:\Program Files\IBM\SPSS\Modeler\18.5\python_venv\Scripts\python.exe" -m pip install pyvis
```

## 4.参考情報

#### 【構造学習】CausalNexで有向非循環グラフ(DAG)推定 -説明変数(テーブルデータ)の因果推論に挑戦-｜はやぶさの技術ノート 

https://cpp-learning.com/causalnex/


#### pythonで因果分析：pgmpy,causalnex | kiseno-log 

https://kiseno-log.com/2021/07/09/python%E3%81%A7%E5%9B%A0%E6%9E%9C%E5%88%86%E6%9E%90%EF%BC%9Apgmpycausalnex/


#### ワインのデータを用いて各種ベイジアンネットワークの推論を比較した #Python - Qiita 

https://qiita.com/groovy-phazuma/items/89410d1bb9c09cce9c56

#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008