AlteryxのNaive Bayesツールの中身を見てみる

こんにちは、小澤です。

Alteryxでは、一部のマクロで実装されたツールの中身をみることができます。 これによって、Predictive系など複雑な処理を行っているツールが何をしているのかを確認することが可能です。

今回はNaive Bayesツールがどのように実装されているのかを見てみましょう。

マクロの中身を表示する方法

マクロの中身を確認する方法は簡単です。 上部のツール一覧か、ワークフロー上に配置されたツールを右クリックするとマクロを開くための項目が用意されています。

スクリーンショット 2017-07-19 11.18.37

これを選択することで、マクロのワークフローが表示されます。

スクリーンショット 2017-07-19 11.20.28

開いてみると、複雑そうには見えますが普通のワークフローと同様の方法で実装されている様子が確認できるかと思います。

Naive Bayesツールの入出力を確認する

さて、ではこのワークフローの中身を確認して...の前にまずはこのツールがどのような入出力が必要なのか確認しておきます。

ワークフローは以下のようになります。

スクリーンショット 2017-07-19 11.32.52

内容としては

  • 入力データをトレーニング用とテスト用に分割
  • トレーニング用データでNaive Bayesのモデル作成
  • テストデータでスコアを出力

と、よくある流れになっています。

Naive Bayesツールの設定は

スクリーンショット 2017-07-19 11.43.49

スクリーンショット 2017-07-19 11.44.06

のようになっており、設定する項目は

  • モデルに関する設定
    • モデル名
    • 目的変数
    • 説明変数
    • スムージングのパラメータ
  • グラフィックに関する設定
    • インチ/センチ
    • 高さ/幅
    • dpi

となっています。

出力は、学習したモデルと以下のようなレポート出力の2つとなっています。

スクリーンショット 2017-07-19 11.47.47

マクロの中身を追ってみる

では、Naive Bayesツールの中身を確認してみましょう。 Zoom > All でワークフロー全体を表示すると、以下のようによくわからないことになります。

スクリーンショット 2017-07-19 11.52.56

大まかに分けて、上部のインターフェスツールと下部の実装部分に分かれています。 インターフェース部分は、さらにパラメータに関する設定と、グラフィックに関する設定の2つに分かれています。

このワークフローを順に見ていきましょう。

変数の抽出

まずは最初のDynamic Selectツールまでの部分です。

スクリーンショット 2017-07-19 13.35.41

マクロの入力は2つのインターフェースツールに繋がっています。

スクリーンショット 2017-07-19 13.37.30

このインターフェース2つは

位置 ツール 入力元
左側 Drop Down 目的変数として選択するもの
右側  List Box 説明変数として選択するもの

となっており、Macro Inputツールに接続されることで、実際のデータから選択肢となる項目が決定されています。

続いて、上下のSelectツールに分かれています。 まず、上側は以下のように目的変数のDrop DownツールとActionツールで接続されています。

スクリーンショット 2017-07-19 13.47.28

Actionツールの設定は以下のようになっており、Selectツールで選択する項目を目的変数のみにしていることがわかります。

スクリーンショット 2017-07-19 13.47.46

下側の2つのSelectツールはそれぞれActionツールを経由して以下のように接続されています。

スクリーンショット 2017-07-19 13.50.59

左側はActionツールの設定で説明変数として選択されたカラムのみに絞っています。

スクリーンショット 2017-07-19 13.54.25

また、このActionツールはError Messageツールに接続され、説明変数が選択されていない場合はエラーになるようになっています。

そこから接続されている右側のSelectツールでは以下のようにXMLをFomulaで書き換えています。

スクリーンショット 2017-07-19 13.56.08

Fomulaの具体的な内容は以下のようになっており、目的変数として選択されているものは、説明変数からは外すような処理を行っています。

スクリーンショット 2017-07-19 13.57.54

続いてのJoinツールでは、上下2つのデータを位置で結合しています。 これによって、必要な変数のみが選択された状態かつ、目的変数が一番左側にある状態になります。

スクリーンショット 2017-07-19 14.00.01

最後にDynamic Selectツールで利用可能な型のデータのみに絞り込んでいます。

Rツールを使ったモデリング

続いて、Rツールの部分を見ていきます。

スクリーンショット 2017-07-19 14.03.13

まず最初に

  • 必要なライブラリの読み込み
  • 目的変数の取得と取りうる値の範囲を取得
  • 説明変数の取得とエラーチェック

をしています。

library(e1071)
library(plotmo)


the.data <- read.Alteryx("#1", mode="data.frame")
the.target <- names(the.data[1])
the.preds <- names(the.data[2:ncol(the.data)])

if (length(the.preds) == 1)
  stop.Alteryx("Two or more predictor fields need to be selected.")

target.data <- eval(parse(text = paste("the.data$", the.target, sep = "")))
if (class(target.data) == "factor")
  target.levels <- levels(target.data)

続いて、fomulaを組み立てています

formula.string <- paste(the.target, paste(the.preds, collapse = " + "), sep = " ~ ")

続いて、スムージングの値と、モデル名を取得しています。

val<-'%Question.laplace.val%'
model.name <- validName('%Question.model.name%')

ここで、「%Question.xxx%」の形式でインターフェースツールで設定された値を取得しています。 この2つはそれぞれどこにも接続されていないText BoxツールとNumeric Up Downツールに対応しており、マクロ利用時インターフェースにおけるモデル名とスムージングのパラメータに対応しています。

スクリーンショット 2017-07-19 14.21.36

Qestionの後に続く、「laplace.val」や「model.name」はツールのAnnotationかワークフローの設定で行うことができます。

スクリーンショット 2017-07-19 14.22.36

スクリーンショット 2017-07-19 14.22.52

続いて、実行するnaiveBayes関数を文字列として作成して、eval関数で実行しています。

command.string <- paste("naiveBayes(formula = ", formula.string, ", data = the.data, laplace=",val,")" , sep = "")
the.model <- eval(parse(text = command.string))

その後、モデルの中に様々な値を追加しています。

getLevels <- function(x) {
  out <- NULL
  if (class(x) == "factor")
    out <- levels(x)
  out
}

xlevels <- sapply(the.data, getLevels)
for (i in names(xlevels)) {
  if(is.null(xlevels[[i]]) || !(i %in% the.preds))
    xlevels[[i]] <- NULL
}

the.model$x <- the.data[the.preds]
the.model$y <- the.data[the.target]
the.model$xlevels <- xlevels
the.model$xvars <- the.preds
the.model$yvars <- the.target
the.model$laplace <- val

その後は、レポート出力に必要な値を組み立てて、1に出力しています。 この部分は、一見複雑そうに見えますが、それほど処理として難しいことをしているわけではないため、出力例と合わせて見ていただけると雰囲気がつかめるかと思います。

# Create the components of the grp/out table for report creation
# The basic model summary

the.call <- formula.string
the.inputs <- paste(paste(the.preds, collapse = ", "))
the.outputs <- paste(paste(the.target, collapse = ", "))
out <- c(model.name, the.call, the.inputs, the.outputs)
grp <- c("Model_Name", paste("summary", 1:(length(out) - 1), sep = ""))

#Confusion Matrix
class.pred <- predict(the.model, newdata = the.data, type = "class")
confusion.mat1 <- as.vector(table(the.data[[the.target]], class.pred))
confusion.mat <- as.data.frame(matrix(confusion.mat1, ncol = length(the.model$levels), nrow = length(the.model$levels), byrow = TRUE))
names(confusion.mat) <- the.model$levels
confusion.mat <- cbind(data.frame(the.names = the.model$lev), confusion.mat)
confusion.mat$Good <- rep(1, nrow(confusion.mat))
names(confusion.mat) <- c(" ", names(confusion.mat[-1]))
confusion.vec <- wrapTable(confusion.mat, ncol(confusion.mat))
grp <- c(grp, rep("confusion", length(confusion.vec)))
out <- c(out, confusion.vec)

write.Alteryx(data.frame(grp = grp, out = out), nOutput=1)

スクリーンショット 2017-07-19 14.55.10

作成したモデルは次の部分で3に出力しています

the.obj <- vector(mode="list", length=2)
the.obj[[1]] <- c(model.name)
the.obj[[2]] <- list(the.model)
names(the.obj) <- c("Name", "Object")
write.Alteryx(the.obj, nOutput = 3)

最後にグラフを2に出力してRツールで行っていることは終了です。 graphWHR関数はAlteryxで定義されている、インチやセンチなど指定されている情報のみを取得する関数となっています。

whr <- graphWHR(inches = '%Question.inches%', in.w = '%Question.in.w%', in.h = '%Question.in.h%', cm.w = '%Question.cm.w%', cm.h = '%Question.cm.h%', resolution = '%Question.graph.resolution%', print.high = FALSE)
AlteryxGraph(2, width = whr[1], height = whr[2], res = whr[3])
layout(matrix(1, 1, 1))

if(length(the.model$levels)==2){
  plotmo(the.model, type = "raw", ylim = NA, degree1 = 1, degree2 = FALSE, nresponse = 1, caption = "", col.degree1 = 1, lwd.degree1 = 2)
  for (i in 2:length(the.preds))
    plotmo(the.model, type = "raw", ylim = NA, degree1 = i, degree2 = FALSE, nresponse = 1, caption = "", col.degree1 = 1, lwd.degree1 = 2)
} else {
  for (i in the.model$levels) {
    plotmo(the.model, type = "raw", ylim = NA, degree1 = 1, degree2 = FALSE, nresponse = i, caption = paste("Effects Plots for Response", i), col.degree1 = 1, lwd.degree1 = 2)
    for (j in 2:length(the.preds)) {
      plotmo(the.model, type = "raw", ylim = NA, degree1 = j, degree2 = FALSE, nresponse = i, caption = "", col.degree1 = 1, lwd.degree1 = 2)
    }
  }
}

plotmo詳細な利用方法を知りたい場合はドキュメントを参照してください

モデルの出力

Rツールで生成したもののうち、モデルはそのまま出力するのみとなります。

スクリーンショット 2017-07-19 15.22.58

レポート出力の組み立て(テキスト部分)

次にレポート出力を作成する部分を見ていきます。 こちらは、まずテキスト部分から見ていきましょう。

スクリーンショット 2017-07-19 15.42.36 2

最初のFomulaツールでは、出力1のうち、grpがconfusionのものと、そうでないものに分かれています。 上部はconfusion以外のものとなっており、出力結果における以下の部分を作成します。

スクリーンショット 2017-07-19 15.46.43

Cross Tabツールでデータを横持ちに変換しています。

スクリーンショット 2017-07-19 15.48.41

これによって、fomulaツールによってconfusionを除いた1の出力結果が以下のように変形されます。

スクリーンショット 2017-07-19 15.50.07

スクリーンショット 2017-07-19 15.50.24

続いて、Report Textツールでこれらの値をカラム名を指定して、レポートのテキスト部分に埋め込んでいきます。

スクリーンショット 2017-07-19 15.52.16

その後、Selectツールでこのレポート出力のみを残して、元の情報を持つカラムを削除します。

スクリーンショット 2017-07-19 15.58.57

最後にFomulaツールでDescriptionの項目を追加して完了となります。

スクリーンショット 2017-07-19 15.59.48

さて、続いては、confusionの部分ですが、見慣れないツールが登場します。

スクリーンショット 2017-07-19 16.06.45

こちらのツールはPipe to Table Rowsツールという名前のようで、内部はマクロになっているのですが、通常のツール一覧には表示されません。「DEPLICATED」と書かれているので、あまり後悔したくないタイプのツールなのではないかと思われます。 そのため、内部の詳細には立ち入らず、入出力でどんなことができるツールなのかを見る程度に止めておきます。

  • 入力 スクリーンショット 2017-07-19 16.09.44
  • 出力 スクリーンショット 2017-07-19 16.09.54

この入出力からもわかる通り、カラム名も含めて「|(パイプ)」で区切られているものをそれぞれの列に展開するツールのようです。

そのあとのFilterツールとSelectツールでConfusion Matrixとして必要な情報のみを抜き出し、 Tableツール、Render Textツールでレポートの形式に体裁を整えています。

最後に、Unionツールで先ほどのテキスト部分と結合することで1つにまとめています。

レポート出力の組み立て(グラフ部分)

さて、このマクロ最後の部分はレポートのグラフ部分の組み立てとなります。

スクリーンショット 2017-07-19 15.42.36 3

とは言っても特に難しい処理はありません。

グラフは説明変数と同じ数出力されるので、Record IDツールとFomulaツールで一意なIDを設定しています。

スクリーンショット 2017-07-19 16.30.09

それにRender Textツールで作成した説明文を付け足しておしまいです。

スクリーンショット 2017-07-19 16.32.55

最後に全体をUnionでまとめ上げて、レポート部分の出力にしています。

これを知って何になるか?

さて、これでマクロ内の動きを一通り確認することが出来ました。 機械学習系のツールはものによって微妙な違いはあるものの、どれもほぼ似たような流れになります。 また、それ以外のツールでもここまでの流れが追えれば、問題なく内容を確認することが可能かと思います。

さて、ではこのような既存のツールの中身を知っておくと何が嬉しいのでしょうか? その答えは主に2つあるかと思います。

1つ目は、似たようなマクロを作成する際に参考になるという部分です。 利用したいけどAlteryxのツールとしては実装されていない手法などがある際には、既存のツールのような作りを参考にすることでその場限りではなく、汎用的に使えるツールにする際に参考になるかと思います。

2つ目は、既存のツールの挙動を変更したい時にそれが可能になることです。 例えば、レポート出力する内容を変更しい、といったことがあった場合にもツールの流れがわかっていれば、似たようなツールを一から作り直すのではなく、既存のものを一部変更して別名で保存してしまうだけで済みます。

この他にも、ワークフロー作成のテクニック的な部分を学ぶこともできるかもしれません。

終わりに

今回は、Naive Bayesツールの実態がどのようになっているのかを解説しました。 少々難しいないようになってしまったかもしれませんが、今すぐではなくても将来的に自分でマクロを作りたいといった要望が出た際などに参考になるかと思います。