AlteryxのNaive Bayesツールの中身を見てみる
こんにちは、小澤です。
Alteryxでは、一部のマクロで実装されたツールの中身をみることができます。 これによって、Predictive系など複雑な処理を行っているツールが何をしているのかを確認することが可能です。
今回はNaive Bayesツールがどのように実装されているのかを見てみましょう。
マクロの中身を表示する方法
マクロの中身を確認する方法は簡単です。 上部のツール一覧か、ワークフロー上に配置されたツールを右クリックするとマクロを開くための項目が用意されています。
これを選択することで、マクロのワークフローが表示されます。
開いてみると、複雑そうには見えますが普通のワークフローと同様の方法で実装されている様子が確認できるかと思います。
Naive Bayesツールの入出力を確認する
さて、ではこのワークフローの中身を確認して...の前にまずはこのツールがどのような入出力が必要なのか確認しておきます。
ワークフローは以下のようになります。
内容としては
- 入力データをトレーニング用とテスト用に分割
- トレーニング用データでNaive Bayesのモデル作成
- テストデータでスコアを出力
と、よくある流れになっています。
Naive Bayesツールの設定は
のようになっており、設定する項目は
- モデルに関する設定
- モデル名
- 目的変数
- 説明変数
- スムージングのパラメータ
- グラフィックに関する設定
- インチ/センチ
- 高さ/幅
- dpi
となっています。
出力は、学習したモデルと以下のようなレポート出力の2つとなっています。
マクロの中身を追ってみる
では、Naive Bayesツールの中身を確認してみましょう。 Zoom > All でワークフロー全体を表示すると、以下のようによくわからないことになります。
大まかに分けて、上部のインターフェスツールと下部の実装部分に分かれています。 インターフェース部分は、さらにパラメータに関する設定と、グラフィックに関する設定の2つに分かれています。
このワークフローを順に見ていきましょう。
変数の抽出
まずは最初のDynamic Selectツールまでの部分です。
マクロの入力は2つのインターフェースツールに繋がっています。
このインターフェース2つは
位置 | ツール | 入力元 |
---|---|---|
左側 | Drop Down | 目的変数として選択するもの |
右側 | List Box | 説明変数として選択するもの |
となっており、Macro Inputツールに接続されることで、実際のデータから選択肢となる項目が決定されています。
続いて、上下のSelectツールに分かれています。 まず、上側は以下のように目的変数のDrop DownツールとActionツールで接続されています。
Actionツールの設定は以下のようになっており、Selectツールで選択する項目を目的変数のみにしていることがわかります。
下側の2つのSelectツールはそれぞれActionツールを経由して以下のように接続されています。
左側はActionツールの設定で説明変数として選択されたカラムのみに絞っています。
また、このActionツールはError Messageツールに接続され、説明変数が選択されていない場合はエラーになるようになっています。
そこから接続されている右側のSelectツールでは以下のようにXMLをFomulaで書き換えています。
Fomulaの具体的な内容は以下のようになっており、目的変数として選択されているものは、説明変数からは外すような処理を行っています。
続いてのJoinツールでは、上下2つのデータを位置で結合しています。 これによって、必要な変数のみが選択された状態かつ、目的変数が一番左側にある状態になります。
最後にDynamic Selectツールで利用可能な型のデータのみに絞り込んでいます。
Rツールを使ったモデリング
続いて、Rツールの部分を見ていきます。
まず最初に
- 必要なライブラリの読み込み
- 目的変数の取得と取りうる値の範囲を取得
- 説明変数の取得とエラーチェック
をしています。
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ツールに対応しており、マクロ利用時インターフェースにおけるモデル名とスムージングのパラメータに対応しています。
Qestionの後に続く、「laplace.val」や「model.name」はツールのAnnotationかワークフローの設定で行うことができます。
続いて、実行する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)
作成したモデルは次の部分で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ツールで生成したもののうち、モデルはそのまま出力するのみとなります。
レポート出力の組み立て(テキスト部分)
次にレポート出力を作成する部分を見ていきます。 こちらは、まずテキスト部分から見ていきましょう。
最初のFomulaツールでは、出力1のうち、grpがconfusionのものと、そうでないものに分かれています。 上部はconfusion以外のものとなっており、出力結果における以下の部分を作成します。
Cross Tabツールでデータを横持ちに変換しています。
これによって、fomulaツールによってconfusionを除いた1の出力結果が以下のように変形されます。
続いて、Report Textツールでこれらの値をカラム名を指定して、レポートのテキスト部分に埋め込んでいきます。
その後、Selectツールでこのレポート出力のみを残して、元の情報を持つカラムを削除します。
最後にFomulaツールでDescriptionの項目を追加して完了となります。
さて、続いては、confusionの部分ですが、見慣れないツールが登場します。
こちらのツールはPipe to Table Rowsツールという名前のようで、内部はマクロになっているのですが、通常のツール一覧には表示されません。「DEPLICATED」と書かれているので、あまり後悔したくないタイプのツールなのではないかと思われます。 そのため、内部の詳細には立ち入らず、入出力でどんなことができるツールなのかを見る程度に止めておきます。
- 入力
- 出力
この入出力からもわかる通り、カラム名も含めて「|(パイプ)」で区切られているものをそれぞれの列に展開するツールのようです。
そのあとのFilterツールとSelectツールでConfusion Matrixとして必要な情報のみを抜き出し、 Tableツール、Render Textツールでレポートの形式に体裁を整えています。
最後に、Unionツールで先ほどのテキスト部分と結合することで1つにまとめています。
レポート出力の組み立て(グラフ部分)
さて、このマクロ最後の部分はレポートのグラフ部分の組み立てとなります。
とは言っても特に難しい処理はありません。
グラフは説明変数と同じ数出力されるので、Record IDツールとFomulaツールで一意なIDを設定しています。
それにRender Textツールで作成した説明文を付け足しておしまいです。
最後に全体をUnionでまとめ上げて、レポート部分の出力にしています。
これを知って何になるか?
さて、これでマクロ内の動きを一通り確認することが出来ました。 機械学習系のツールはものによって微妙な違いはあるものの、どれもほぼ似たような流れになります。 また、それ以外のツールでもここまでの流れが追えれば、問題なく内容を確認することが可能かと思います。
さて、ではこのような既存のツールの中身を知っておくと何が嬉しいのでしょうか? その答えは主に2つあるかと思います。
1つ目は、似たようなマクロを作成する際に参考になるという部分です。 利用したいけどAlteryxのツールとしては実装されていない手法などがある際には、既存のツールのような作りを参考にすることでその場限りではなく、汎用的に使えるツールにする際に参考になるかと思います。
2つ目は、既存のツールの挙動を変更したい時にそれが可能になることです。 例えば、レポート出力する内容を変更しい、といったことがあった場合にもツールの流れがわかっていれば、似たようなツールを一から作り直すのではなく、既存のものを一部変更して別名で保存してしまうだけで済みます。
この他にも、ワークフロー作成のテクニック的な部分を学ぶこともできるかもしれません。
終わりに
今回は、Naive Bayesツールの実態がどのようになっているのかを解説しました。 少々難しいないようになってしまったかもしれませんが、今すぐではなくても将来的に自分でマクロを作りたいといった要望が出た際などに参考になるかと思います。