SPSS Modelerで、様々な説明変数や目的変数の設定パターンでモデルを自動作成する。

説明変数の様々な組み合わせや目的変数の組み合わせを変えてモデルを作りたいことがあります。

説明変数や目的変数の組み合わせをあらかじめ定義したファイルを用意して、モデルまで一括で作成するスクリプトを作りました。

* テスト環境
    * Modeler 18.4
    * Windows 11 64bit

* サンプルストリーム

https://github.com/hkwd/spssmodelerscript/raw/master/221121automodeling/automodeling2.str

* サンプル学習データ

https://raw.githubusercontent.com/hkwd/spssmodelerscript/master/221121automodeling/KPI.csv

* サンプル定義データ

https://raw.githubusercontent.com/hkwd/spssmodelerscript/master/221121automodeling/%E3%82%BB%E3%83%83%E3%83%88%E5%AE%9A%E7%BE%A9.csv

# サンプルストリームの実行
学習データは以下のイメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/2943041e-93a7-8cb7-b3cb-bf4a932758b1.png)

以下のような定義ファイルを用意します。
1列目は説明変数と目的変数の組み合わせのセット名で、任意の文字列になります。
2列目以降は各変数をI（説明変数）、T（目的変数）、N（対象外）にするかの設定です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/f9015711-5e05-1330-3ee8-e8a6634f1fa8.png)




ファイルができたら、以下のように定義ファイルに「テーブル」ノードに接続し、学習データを単独で配置します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/15661de9-a15b-89d8-f39e-82dfcfd0dfbc.png)


以下のスクリプトをストリームのプロパティに入れます。

```python:automodeling.py
import modeler.api
stream = modeler.script.stream()

#説明変数定義のテーブルを読み出す
tablenode=stream.findByID("id8DAW4GC9YSD")
results = []
tablenode.run(results)
tableoutput = results[0]
# Access the table output's content model
tablecontent = tableoutput.getContentModel("table")

#学習データ読み込みノード
startnode   = stream.findByID("id2GDWUBHR75Z")


for row in range(tablecontent.getRowCount()):
    #説明変数と目的変数のセット名
    setname=tablecontent.getValueAt(row, 0)
    #データ型ノードの配置
    typenode  = stream.createAt("type",setname, startnode.getXPosition() + 120, startnode.getYPosition()+row*50)
    stream.link(startnode, typenode)
    #モデル作成ノードの配置
    modelnode  = stream.createAt("svm",'model', typenode.getXPosition() +120, typenode.getYPosition())
    stream.link(typenode, modelnode)

    #説明変数と目的変数の設定情報の取得
    for col in range(tablecontent.getColumnCount()):
        colname=tablecontent.getColumnName(col)
        #print tablecontent.getColumnName(col), tablecontent.getStorageType(col),  tablecontent.getValueAt(row, col)
        #目的変数
        if tablecontent.getValueAt(row, col)=='T':
            typenode.setKeyedPropertyValue("direction", colname, "Target")
        #説明変数
        elif tablecontent.getValueAt(row, col)=='I':
            typenode.setKeyedPropertyValue("direction", colname, "Input")
        #対象外
        else:
            typenode.setKeyedPropertyValue("direction", colname, "None")
    #モデル作成と配置
    modelnode.run([])
    stream.successors(typenode)[1].setXYPosition(modelnode.getXPosition() +120, modelnode.getYPosition())

```
「このスクリプトを実行」で実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/9080decb-dd83-d41f-8606-f5a5c331db46.png)

以下のように、データ型ノード、モデル作成ノード、モデルノードが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/5f3e83ce-d5d3-d8fa-643e-15d5f012a9cf.png)

設定ファイルには以下の3行の設定があったので、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/f9015711-5e05-1330-3ee8-e8a6634f1fa8.png)
以下の３つのデータ型ノードの設定を生成しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/927fe168-cb6d-d233-b6fc-9a3463f75c5a.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/71c30dea-e384-29db-f366-d8e67fca0052.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/0990b77d-c7ff-46bc-91ae-4c5274fa21a9.png)


# スクリプトの解説

説明変数目的変数定義のテーブルは以下で読みだしています。
tablenode=stream.findByID("id8DAW4GC9YSD")には「テーブル」ノードのIDを記入します。


```python:説明変数目的変数定義のテーブルを読み出す
tablenode=stream.findByID("id8DAW4GC9YSD")
results = []
tablenode.run(results)
tableoutput = results[0]
# Access the table output's content model
tablecontent = tableoutput.getContentModel("table")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/11232a8f-50c5-ce60-ad0e-f35a76049d64.png)

学習データのノードのIDは以下で取得して記入します。
```python:学習データ読み込みノード
startnode   = stream.findByID("id2GDWUBHR75Z")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223763/4b70b2e3-6894-8372-b32d-36727e56f439.png)



定義ファイルを読んで、データ型ノードのロールの説明変数（Input）、目的変数(Target)、対象外(None）を設定していきます。
```python:データ型のロール設定
#目的変数
if tablecontent.getValueAt(row, col)=='T':
    typenode.setKeyedPropertyValue("direction", colname, "Target")
#説明変数
elif tablecontent.getValueAt(row, col)=='I':
    typenode.setKeyedPropertyValue("direction", colname, "Input")
#対象外
else:
    typenode.setKeyedPropertyValue("direction", colname, "None")
```

モデル作成ノードを実行して、出来上がったモデルノードを並べます。
```python:モデル作成と配置
modelnode.run([])
stream.successors(typenode)[1].setXYPosition(modelnode.getXPosition() +120, modelnode.getYPosition())

```

# 参考
### テーブル コンテンツ モデル - IBM Documentation 

https://www.ibm.com/docs/ja/spss-modeler/18.4.0?topic=results-table-content-model

### typenode プロパティー - IBM Documentation 

https://www.ibm.com/docs/ja/spss-modeler/18.4.0?topic=properties-typenode

### Nodeオブジェクト - IBM Documentation 

https://www.ibm.com/docs/ja/spss-modeler/18.4.0?topic=supernodes-node-objects

### ストリーム内のノードのトラバース - IBM Documentation 

https://www.ibm.com/docs/ja/spss-modeler/18.4.0?topic=streams-traversing-through-nodes-in-stream