拡張モデルノードで作成したモデルの予測結果がおかしい
みなさんこんにちわ。今回は拡張モデルノードでモデル作成後に予測結果をスコアリングノードで出力させたときに、結果が予想と異なり、かなりはまった事例を紹介します。
1. PLSモデルの予測結果がおかしい。。
上記の記事からの続きでモデルを実装していたのですが、なぜか予測結果がおかしくなる事象が発生しました。
①. 拡張ノードでPLSモデルを作成して結果を確認
拡張モデルノードでモデルを作成して、同じ学習データをそのまま生成されたスコアリングノードに投入して結果を精度分析ノードで確認した結果が下記画像です。$PLS-octaneが予測値です。
※.octane値を各スペクトルフィールドの値で予測するPLS回帰モデルです。
線形相関が下がっていることに?と思ったのですが、何より誤差がひどい。
テーブルノードで予測値を確認したのが、次の画像です。
なんで??予測値が12??。実測値は85等なので。おかしい。。
2. 原因調査を実施
①. 学習時とスコアリング時のモデルを比較
さて、これはおかしいと思いモデルの内容を確認しました。
考えられることとしては、
-
そもそも作成したモデルの精度が低い
-
学習モデルとスコアリング用モデルの整合性がとれていない?
①. 学習モデルとスコアリング用モデルは同一のものか?
②. 学習モデルとスコアリング用モデルの回帰係数は同じか?
③. 学習モデルとスコアリング用モデルの予測値は同じか?
④. 入力データは正しいか?
上記の内容を確認しました。
i.学習モデルの精度確認
使っていたストリームの全体は以下の通りです。これは、前回の記事で作成したストリームとほぼ同じです。
モデル作成用の部分が追加されただけです。
まずは、前回と同様に拡張の出力ノードでモデルの確認
n_components = 6 で作成すると以下の通りの精度です。これは、同じですね。
続いて拡張モデルノードでの精度を確認
ん?精度が違いいますね。
ただ、スコアリング時のような相関係数や誤差ほどではないので、この時点では気にしていませんでした。
※.ここがまずかったです。
ii.学習モデルとスコアリング用モデルの整合性確認
もしかすると、学習モデルは大丈夫だけど、スコアリング用モデルとしてロードした際に、
何か不具合でうまくロードできていないのでは?と考え回帰係数や、モデル詳細を確認しました。
モデル作成時の詳細は以下の通り
モデルのタイプ、n_components、回帰係数になります。
つづいてスコアリング用にロードしたモデルの詳細
まったく一緒です。保存したモデルを正常にロードできています。
iii.学習モデルとスコアリング用モデルの予測値の確認
ストリームを見てもらえばわかる通り、まったく同じデータを投入しています。
なので、予測値が異なることはないと思います。が
まずは、モデル作成時の"octane"の予測値
88や85など、12などの数値は見当たりません。
つづいて、スコアリング時の予測値
あーーー。やっぱり12とかになっていますね。これはおかしい。
モデルは一緒で、データも一緒のはず?なのに予測値が違う。
iv. 学習時とスコアリング時の入力データの確認
なんで?
さて、こうなるとモデルに投入したデータが異なることが一番考えられます。
そこで、確認してみました。
まず、データ投入前にテーブルノードで確認
下記画像のように、予想通りの入力データです。
目的変数の "octane" が一番最初にあり、そこから61個の説明変数であるスペクトルフィールドがあります。
このデータを入力データとしています。
さて、PLSモデルを作成するときに、拡張ノードのPythonでは以下の処理をしています。
#-------------------------------------------------------
# データ入力
#-------------------------------------------------------
# 事前にデータ区分で学習・テストデータは分けているのでそのまま入力
# Pandasで入力
modelerData = modelerpy.readPandasDataframe()
# 説明変数 - NIR.900 rm以降の列を全て
xdata = modelerData.iloc[:, 1:] # 2列目(index=1)以降を選択
# 目的変数 - octane
ydata = modelerData['octane']
目的変数は、ydata = modelerData['octane'] と、そのまま "octane"フィールドを指定しています。
が
説明変数は、フィールド名指定ではなく、xdata = modelerData.iloc[:, 1:] と、
2列目(index=1)以降を全てを選択するように記述しています。
さて、拡張モデルノードで入力変数である、xdata の中身を出力してみます。
つづいて、スコアリングナゲットでの xdata の中身です。
ここで、やっと気づきました。
フィールドがずれている。
"octane"フィールドが一番最後に移動したため、"NIR 1126 nm"が除外され(1列目になってしまったため)、それ以外(octaneも含め)が説明変数となってしまいました。
ええー??
スコアリング時は、予想通りの説明変数のフィールドになっています。こちらは問題なし。
問題は、モデル作成時です。なぜか、"octane" が一番最後にいますね。そして、フィールドの"NIR 1126 nm"がなく、"NIR 1128 nm"からになっています。
モデル作成時の説明変数が違うので、精度も違えば、予測値も違うはずですよ。
でもなぜ?
v. 学習時とスコアリング時の入力データの差異の原因(あくまで個人の見解です。)
目的変数の"octane"が一番最後に移動していることで、ピンときました。
ここの、特徴量選択ノードのところで、フィールドのロールを設定していました。
"octane"は "対象"(目的変数) にロールを設定しています。
検証のために、"NIR 1128 nm" を"対象"にして、拡張モデルノードに投入し入力データ全てを確認すると
下記画像の通りに、"octane"の位置はそのままで、"NIR 1128 nm"は一番最後に移動しています。
スコアリング時は位置は変化なく正常に入力されていますね。
もう、これが原因でしょう!
フィールドが勝手に違う順番になってしまったため、モデル作成時の説明変数が変わってしまったためです。
このフィールド順が変わってしまうことですが、仕様なのか?は分かりません。とほほ。
気を取り直して、最後に修正して確認すると、精度・予測値ともに想定通りの結果となりました。
"octane"が一番最後の列なので、それを除外したものを説明変数としました。
# 説明変数 - 一番最後のoctaneを除いた全て
xdata = modelerData.iloc[:, :-1] # 最後の列を除外
3. 原因についてまとめ
原因については、検証した範囲でまとめると、
-
環境
①. SPSS Modeler v18.5 / v18.6 (ともにWindows版)で発生を確認しました。 -
発生する問題
①. 入力フィールドのロール設定が "対象" の場合、拡張モデルノードで
modelerData = modelerpy.readPandasDataframe()
というように、データ入力した場合、ロールが"対象"のフィールドが 一番最後へ移動 する。 -
発生するノード
①.問題の発生するのは、拡張モデルノード の モデル作成のシンタックスです。
※.スコアリングシンタックスでは発生しないようです。
②.言語は、Python です。(R, Python for Sparkでは確認しておりません。)
みなさん、気をつけましょう。
4. 最後に
次回は、その2 モデルを実装編を記載する予定です。
あと、SPSS Statisticsと連携することで、拡張ノードでなくてもPLSを実装できます。そちらも紹介する予定です。
参考
SPSS Modeler ノードリファレンス目次
SPSS Modeler 逆引きストリーム集
SPSS funさん記事集
SPSS連載ブログバックナンバー
SPSSヒモトクブログ
今後は、ヒモトクブログなどは以下のTechXchangeのコミュニティに統合される予定です。
ご興味がある方は、ぜひiBM IDを登録して参加してみてください!!!お待ちしています。
IBM TechXchange Data Science Japan