SAS Viyaによる機械学習パイプラインを体験する流れ

SAS ViyaはAIプラットフォームを提供しています。デモもあるのですが、全体が英語なので利用するまでに躊躇してしまう人も多いかと思います。そこで、Pythonで機械学習パイプラインを利用するまでの流れを紹介します。

# 利用開始まで

まず SASの開発者サイトにアクセスします。開発者サイトは [SAS for Developers](https://developer.sas.com/home.html) です。

![Screenshot_ 2018-06-27 14.59.58.png](https://qiita-image-store.s3.amazonaws.com/0/197026/8acfe222-35ea-79bc-d098-77e42347902e.png)

そして、 [Get started with your SAS Viya Developer Trial](https://www.sas.com/en_us/trials/software/viya-developer/form.html) を押します。

![Screenshot_ 2018-06-27 15.00.52.png](https://qiita-image-store.s3.amazonaws.com/0/197026/5a595a61-9133-90bc-9dfa-6ac5569e6909.png)


試すためには SAS Profile （SASプロファイル） というのが必要です。まず [Create one](https://login.sas.com/opensso/UI/Login?realm=/extweb&goto=https://www.sas.com/en_us/trials/software/viya-developer/form.html) をクリックします。

<img width="2970" alt="Screenshot_ 2018-06-27 15.04.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/197026/1ee63a5b-a81e-0e22-17c8-90deb0c58019.png">

SASプロファイルを登録するをクリックします。

![Screenshot_ 2018-06-27 15.05.26.png](https://qiita-image-store.s3.amazonaws.com/0/197026/ef1c48e1-5274-85b4-83b4-50519b28408f.png)


情報を入力します。

![Screenshot_ 2018-06-27 15.05.36.png](https://qiita-image-store.s3.amazonaws.com/0/197026/b6167273-8309-eac3-6cb8-f3d9d88ecb9f.png)



フォームを送信するとメールが送られてきます。

![Screenshot_ 2018-06-27 15.06.23.png](https://qiita-image-store.s3.amazonaws.com/0/197026/89461c01-9991-1861-a09c-4bdb6b2fd8ae.png)


メールに書かれている **SASプロファイルをアクティベートする** をクリックします。

![Screenshot_ 2018-06-27 15.08.01.png](https://qiita-image-store.s3.amazonaws.com/0/197026/bb5ed70b-931a-f4c2-4d56-b04094bba800.png)


そしてパスワードを設定します。

![Screenshot_ 2018-06-27 15.08.34.png](https://qiita-image-store.s3.amazonaws.com/0/197026/5e631d6b-92df-949c-683d-f23ecbbea39b.png)


SASプロファイルがアクティベートされます。 **続ける** をクリックします。

![Screenshot_ 2018-06-27 15.09.03.png](https://qiita-image-store.s3.amazonaws.com/0/197026/8acd3639-0522-d3ba-7570-08fe31d3bf4c.png)


そうすると先ほどの SAS® Viya® Developer Trial の画面に戻ってきますので、 今度はSign In をクリックします。

![Screenshot_ 2018-06-27 15.09.43.png](https://qiita-image-store.s3.amazonaws.com/0/197026/d70b2da0-634a-3e99-2200-7de7b76b2001.png)

先ほど登録したSASプロファイルのID、パスワードでログインします。

![Screenshot_ 2018-06-27 15.10.15.png](https://qiita-image-store.s3.amazonaws.com/0/197026/064c9340-36fd-792f-9eb8-14da0d58c5dc.png)


ログインすると SAS® Viya® Developer Trial の画面に戻ってきますが、今回はプロファイルの内容が入力されているはずです。一番下にある Sign me upボタンをクリックします。

![Screenshot_ 2018-06-27 15.11.20.png](https://qiita-image-store.s3.amazonaws.com/0/197026/40903d65-8cd9-a359-5be4-881317f32db4.png)


これで SAS® Viya® Developer Trial の申し込みが終わりました。数分後にメールが送られてきます。

![Screenshot_ 2018-06-27 15.12.24.png](https://qiita-image-store.s3.amazonaws.com/0/197026/c0ac5de5-2f22-1c9a-a37c-ce7fed3363f1.png)


送られてきたメールにある **Log in to your Trial Portal** のリンクをクリックします。

<img width="1824" alt="Screenshot_ 2018-06-27 15.13.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/197026/186feb88-d04a-5fc4-2a3a-d5feb89ab0a3.png">


利用規約が表示されますので、問題なければAcceptボタンを押します。

![Screenshot_ 2018-06-27 15.14.21.png](https://qiita-image-store.s3.amazonaws.com/0/197026/777cb262-975b-05f6-fd17-94f799d120fb.png)


そうするとログインフォームが出るので、先ほど登録したID、パスワードでログインします。

![Screenshot_ 2018-06-27 15.14.55.png](https://qiita-image-store.s3.amazonaws.com/0/197026/a855abd5-63f7-b96d-3f1f-4e499fb17713.png)


ログインすると Getting Started: SAS® Viya™ Developer Trial が表示されます。

![Screenshot_ 2018-06-27 15.15.39.png](https://qiita-image-store.s3.amazonaws.com/0/197026/b06118e0-bcfb-1864-58c9-5ac897d57c97.png)



下の方にある Get started with Python, R, and SAS API via Jupyter Notebook をクリックします。

![Screenshot_ 2018-06-27 15.16.30.png](https://qiita-image-store.s3.amazonaws.com/0/197026/7b9c13ac-18fc-0825-2663-a390c06564ab.png)


さらに Start My Trial Now をクリックします。

<img width="2436" alt="Screenshot_ 2018-06-27 15.16.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/197026/5fe09c63-be6c-880b-c380-2ae0c25c9d24.png">


そうすると見慣れたJupyter Notebookの画面が出ます。Pythonフォルダの中にある TitanicPipefitter.ipynb をクリックします。

![Screenshot_ 2018-06-27 15.16.57.png](https://qiita-image-store.s3.amazonaws.com/0/197026/48c4b49c-e513-73c8-c19d-6b9c559a9b34.png)


----

ここからは TitanicPipefitter.ipynb に書かれている内容の意訳です。英語の後に日本語を参考として載せています。

# Machine Learning Pipeline: Using Pipefitter with SAS 9 or SAS Viya （機械学習パイプライン：SAS 9またはSAS ViyaでPipefitterを利用する）

The goal is to supply a uniform set of high-level APIs built on top of SAS 9.4 and SAS Viya that help users create and tune practical machine learning pipelines.  The idea is currently applied in open source framework scikit-learn and spark.ml.

このJupyter Notebookの目標はSAS 9.4とSAS Viya上に構築された実用的なパイプラインを作成し、高度かつ統一されたAPIセットを体験します。この手法はオープンソース・フレームワークのscikit-learnとspark.mlで用いられています。

The three primary components used in the workflow are:

このワークフローで使用される主なコンポーネントは次の3つです。

* Transformer （変換器）
* Estimator （推定器）
* Pipeline （パイプライン）

First, we setup paths to development versions of packages.  This is just for development purposes.  Customers would install these packages in the normal fashion.

まず最初にパッケージにおける開発バージョンのパスを設定します。これは開発のためだけです。ユーザは通常、これらのパッケージをインストールします。

## Create Connections and Load Data （接続の作成とデータの読み込み）

The `PipelineConnection` object is a thin wrapper around the saspy and SWAT connection objects.  While these objects use very different connection parameters, methods such as `read_csv` can be normalized between them using this object.

`PipelineConnection` オブジェクトは、saspyとSWAT接続オブジェクトを扱う薄いラッパーです。これらのオブジェクトはまったく異なる接続パラメータを使用しますが、このオブジェクトを使用して `read_csv` などのメソッドを扱えるようになります。

### SAS Viya Version （SAS Viya のバージョン）

```python
import swat as sw

cashost='localhost'
casport=5570
casauth='~/.authinfo'
conn = sw.CAS(cashost, casport, authinfo=casauth, caslib="casuser")
data = conn.read_csv('../data/train.csv')
```

```python
data.head()
```

```python
data.info()
```

## Pipefitter Classes （Pipefitterクラス）

These classes are agnostic across connection types.  They simply proxy all method calls to the appropriate classes in the registered backends.  New backends can be registered using the name of the data type of the table object as the key. Currently, Pipefitter supports `SASdata` from the saspy package and `CASTable` from the SWAT package.

これらのクラスは、接続タイプに関係しません。登録したバックエンドの適切なクラスへのすべてのメソッド呼び出しをプロキシします。新しいバックエンドは、テーブルオブジェクトのデータ型の名前をキーとして登録できます。 現在、Pipefitterはsaspyパッケージの `SASdata`とSWATパッケージの` CASTable`をサポートしています。

> The SAS Pipefitter project provides a Python API for developing machine learning pipelines. The pipelines are built from stages that perform variable transformation, parameter estimation, and hyperparameter tuning.
> 「SAS PipeFitter」は、機械学習パイプライン（≒プロセスフロー）を作成するためのPythonのAPIです。機械学習パイプラインとは、変数の変換、パラメータ推定、ハイパーパラメーターのチューニングなどの処理で構成されます。

### Estimator（推定器）


```python
from pipefitter.estimator import DecisionTree, DecisionForest, GBTree
```

Create a DecisionTree object.  This object is the high-level object that has no knowledge of CAS or SAS.

DecisionTreeオブジェクトを作成します。CASまたはSASの知識がなくても使える、上位レベルのオブジェクトです。

```python
params = dict(target='Survived', 
              inputs=['Sex','Age','Fare'], 
              nominals=['Sex', 'Survived'])
```


```python
dtree = DecisionTree(max_depth=6, **params)
dtree
```

#### Decision Tree Fit and Score of CAS Table（CASテーブルの決定木の適合度とスコア）

Run the ``fit`` method against the data set.  This ``fit`` method does some parameter validation, then looks up the appropriate sub-package for the given table object to locate the correct backend implementation to call.  The ``fit`` method of that object is then called.

データセットに対して ``fit`` メソッドを実行します。 この ``fit``メソッドは、いくつかのパラメータ検証を行い、指定されたテーブルオブジェクトの適切なサブパッケージを検索します。そして、そのオブジェクトの ``fit`` メソッドを実行します。

Using the `DecisionTree` instance, we'll first run the `fit` method on the data set.  This will return a model object.

まず `DecisionTree` インスタンスを使って、データセットに対して `fit`メソッドを実行します。 これはモデルオブジェクトを返します。

```python
model = dtree.fit(data)
model
```


```python
vars(model)
```

The ``score`` method can then be called on the resulting model object using a different data set for scoring.

スコアリングのために別のデータセットを使用して結果のモデルオブジェクトに対して ``score`` メソッドを呼び出せます。

```python
score = model.score(data)
score
```

Fields from the output can be selected using standard DataFrame techniques.  There are a common set of fields for all backends, but other fields may be available depending on what the backend model can produce.

出力にあるフィールドは、標準の DataFrame 技術を使用して選択できます。すべてのバックエンドに共通のフィールドセットがありますが、バックエンドモデルが生成できるものに応じて他のフィールドを利用できます。

```python
score.loc['MisClassificationRate']
```

Other estimator objects can be created using the same set of parameters.

他の推定器オブジェクトは、同じパラメータセットを使用して作成できます。

```python
rf = DecisionForest(**params)
rfmodel = rf.fit(data)
rfmodel
```

```python
rfmodel.score(data)
```

You can even take it down to a one-liner.

一行で記述することもできます。

```python
GBTree(**params).fit(data).score(data)
```

### Generic Imputer （一般的な代入）

Imputing can also be done using classes that work with multiple backends.

複数のバックエンドで動作するクラスを使用して、代入を行えます。

```python
from pipefitter.transformer import Imputer
```


```python
imp = Imputer(value=Imputer.MODE)
imp
```


```python
data.info()
```


```python
datamode = imp.transform(data)
datamode.info()
```

Impute measures using **mean** values.

**平均** 値を利用して、連続変数（間隔変数）を補完します。

```python
datamean = Imputer(value=Imputer.MEAN).transform(datamode)
datamean.info()
```

Here is a sample of the data set before imputing missing values.

欠損値を代入する前のデータセットのサンプルです。

```python
data.head(10)
```

Here is a sample of the data set after imputing missing values.

欠損値を代入した後のデータセットのサンプルです。

```python
datamean.head(10)
```

## Pipeline（パイプライン）

Pipelines can be constructed using multiple transformers and estimators.  The flow of a sample pipeline is shown in the diagram below.

パイプラインは、複数の変換器と推定器を使用して構築できます。 サンプルパイプラインのフローを下の図に示します。

![pipeline.png](https://qiita-image-store.s3.amazonaws.com/0/197026/7afd0fea-8c91-7815-79dd-4fd5e7b4dba9.png)


```python
from pipefitter.pipeline import Pipeline
```

### Defining the Pipeline（パイプラインの定義）

Each component of a pipeline consists of tuples that specify a label for the component and a class instance for that step in the pipeline.

パイプラインの各コンポーネントは、コンポーネントのラベルとパイプラインの中にある各ステップのクラスインスタンスという組み合わせで構成されています。

First we define the `Imputer` objects. 

最初に `Imputer` オブジェクトを定義します。

```python
from pipefitter.transformer import Imputer

mode_imputer = Imputer(value=Imputer.MODE)
mean_imputer = Imputer(value=Imputer.MEAN)
```

Now we define the estimators.  In this case, we'll use the same parameters for all of them.

ここで 推定器を定義します。この場合、すべて同じパラメータを使用します。

```python
from pipefitter.estimator import DecisionTree, DecisionForest, GBTree

params = dict(max_depth=6, 
              target='Survived', 
              nominals='Survived', 
              inputs=['Age', 'Fare', 'Sex'])

tree = DecisionTree(**params)
tree2 = DecisionTree(**params)
rf = DecisionForest(**params)
```

A pipeline is constructed using the imputer and estimator objects.  Note that we can use one or more of any of them.  In the case of imputers, the `transform` method is called at each step and the resulting table is used as the input for the next step.  In the case of estimators, the `fit` method is called to get a model, then the `transform` method on the model object is called to get the output table for the next step.  By default, the table that was passed in is just sent to the next step.

パイプラインは、imputerオブジェクトと推定器オブジェクト（いずれか1つ以上）を使用して構築されます。imputerオブジェクトの場合、各ステップで `transform`メソッドが呼び出され、結果は次のステップの入力として使用されます。 推定器オブジェクトの場合、 `fit` メソッドでモデルが取得され、そのモデルの `transform` メソッドを呼び、次のステップの出力テーブルが取得されます。 デフォルトでは渡されたテーブルは次のステップに送られます。

```python
pipeline = Pipeline([mode_imputer, tree, mean_imputer, tree2, rf])
```

### Call the `fit` Method using the Pipeline（パイプラインを使って `fit` メソッドを呼び出す）


```python
model = pipeline.fit(data)
model
```

We can now score the data using the model produced by the pipeline.  The data passed in goes through the same transformation steps as the training data.  Note that we get a separate row in the resulting data set for each estimator in the pipeline.

パイプラインで生成されたモデルを使用してデータをスコアリングできます。渡されたデータはトレーニングデータと同じ変換ステップを経ます。パイプラインの各推定器について、結果のデータセットには異なる行があるのに注意してください。

```python
model.score(data)
```

It is also possible to pass in parameter overrides to the `fit` method.  These parameters are only used for this `fit` invocation and are not presserved.

`fit` を上書きしてパラメータを渡すこともできます。これらのパラメータは、この `fit` メソッドを呼ぶためにだけに使われ、保存されません。

```python
model = pipeline.fit(data, {tree2.max_depth: 6, 'max_depth': 1, 'inputs': ['Age', 'Sex']})
```

Here we are scoring the data and retrieving just two columns from the output

ここではデータをスコアリングし、2列だけを出力から取得しています。

```python
model.score(data).loc[:, ['NObsUsed', 'MisClassificationRate']]
```

You can set new parameters in the pipeline object using the `set_params` method.

`set_params` メソッドを使って、パイプラインオブジェクトに新しいパラメータを設定できます。

```python
pipeline.set_params({tree2.max_depth: 6, 'max_depth': 1, 'inputs': ['Age', 'Sex']})
```

These parameters will now be used in any call to the `fit` and `score` methods.

これらのパラメータは、 `fit` メソッドと `score` メソッドで使えるようになります。

```python
model = pipeline.fit(data)
```


```python
model.score(data).loc[:, ['NObsUsed', 'MisClassificationRate']]
```

## HyperParameter Tuning （ハイパーパラメータの調整）

The hyper-parameter tuning classes allow you to test multiple sets of parameters across a set of estimators.  These can be used both with individual estimator classes as well as full pipelines.

ハイパーパラメータチューニングクラスを使用すると、一連の推定器に対して複数のパラメータセットをテストできます。 これらは、個々の推定器クラスとすべてのパイプラインで使用できます。

```python
from pipefitter.estimator import DecisionTree
from pipefitter.model_selection import HyperParameterTuning
```

First we set up the parameter grid.  This can be done as a single dictionary where each of the fields is a list.  Or, it can be done as a list of dictionaries where each element in the list is a complete set of parameters.

最初にパラメータグリッドを設定します。 これは、各フィールドがリストになっている単一の辞書として扱えます。また、リストの各要素が完全なパラメーターセットである辞書リストとしても扱えます。

```python
param_grid = dict(
    max_depth=[6, 10],
    leaf_size=[3, 5],
)
```

Here we are using a `DecisionTree` with the parameter grid.

ここではパラメータグリッドとともに `DecisionTree` を使用しています。

```python
hpt = HyperParameterTuning(
          estimator=DecisionTree(target='Survived',
                                 inputs=['Age', 'Fare', 'Sex', 'SibSp', 'Parch', 'Ticket', 'Cabin'],
                                 nominals=['Survived', 'Cabin', 'Sex']),
          param_grid=param_grid, 
          score_type='MisClassificationRate', 
          cv=3)
```


```python
hpt.gridsearch(data)
```

Here we are using the same pipeline as defined in the previous section with this parameter grid.

ここでは、前のセクションで定義したパイプラインに対して、パラメータグリッドを適用しています。

```python
hpt = HyperParameterTuning(
          estimator=pipeline,
          param_grid=param_grid, 
          score_type='MisClassificationRate', 
          cv=3)
```

In this case, we get a line for each of the estimators in the pipeline

この場合、パイプライン内の各推定器が得られます

```python
hpt.gridsearch(data)
```

It is also possible to use a separate thread for each grid point in the parameter grid.  This will only work if the table is globally available in CAS.  Currently, saspy does not allow multiple threads.

パラメータグリッド内の各グリッドポイントで個別のスレッドを使用することもできます。 これは、テーブルがCASの中でグローバルに使用可能な場合にのみ有効です。 現在、saspyは複数のスレッドを許可していません。

```python
try:
    data.table.promote()
except:
    pass
```


```python
hpt.gridsearch(data, n_jobs=4)
```

## Clean up（片付け）


```python
conn.terminate()
```


```python

```

----

ここまでの内容が TitanicPipefitter.ipynb で書かれているデモになります。Jupyter Notebookなので、Webブラウザ上でコードを実行して結果を確認できます。ぜひSAS Viyaで体験してみてください。

[SAS for Developers | SAS](https://developer.sas.com/home.html)