はじめに
みなさん、こんにちわ。さて、引き続きPLSを実装していきます。前回、PLSでの潜在変数(PLS成分)の最適な数を調査し最適な数は、"6"とわかりました。今回は、そのパラメータ値を使って拡張モデルノードでPLSモデルを実装します。
※ 2025/03/14 記事で使用したストリームをGitHubにアップロードしました。
データについては、以下のリンクより"gasoline.csv"をダウンロードしてください。
1. PLSモデルを実装していく
①. ストリーム全体
以下が、ストリーム全体です。
途中の特徴量選択ノードまでは、前回とほぼ同じです。
特徴量選択ナゲットから、上側のストリームはモデル作成用、下側のストリームはスコアリング用となっています。
②. データ入力から、特徴量選択まで
i. データ入力
同じ "gasoline.csv" を使います。ダウンロードは以下よりお願いします。
可変長ファイルノードで入力します。設定は、
・NIR 1246 nm
・NIR 1248 nm
・NIR 1348 nm
上記3つのフィールドの ストレージ を "実数" に変更してください。
また、不要なフィールドである "1"フィールドをフィルタータブで除外していおきましょう。
ii. 学習データ・テストデータ分割
データ区分ノードで、
学習 80
テスト 20
と値を変更してください。
(※. この値は任意です。ユーザーさんで自由に設定してください。)
iii. インスタンス化
データ型ノードで、インスタンス化してます。
フィールドの ロール を以下のように設定し、値の読み込み をてください。
octane "対象"
octane以外 "入力" (デフォルトで入力になっています。)
iv. 説明変数の絞り込み
特徴量選択ノードで、octane への影響が強い変数に絞り込みます。
特に設定は変更せずに 実行 してください。
先ほどデータ型ノードで
フィールドの ロール を
octane "対象"
octane以外 "入力"
と設定しています。
特徴量選択ノードは、対象フィールドと入力フィールドとの関係性を分析して、有意な相関があればそれをランク付けしてくれるのです。
今回 octane と 説明変数であるスペクトル変数は、どちらも数値データですので 相関係数に基づいた t 統計 を計算してランクを付けています。
対象の変数がカテゴリデータの場合は、以下のように、カイ二乗値などの指標が使われます。
(ユーザーが選択できます。)
v. 説明変数の絞り込み その2
octane と相関が認められない変数や相関が弱い変数はチェックが外れてスクリーニングされます。
(※. ユーザーが自由にチェックは入れたり外したりできます。)
③. PLS回帰モデルの作成
続いては、学習データでPLS回帰モデルを作成していきます。
i. データの絞り込み
条件抽出ノードで、学習データのみ選択します。
ii. 不要フィールド削除
フィルターノードで"データ区分"フィールドを除外しておきます。
iii. PLSモデル作成 - モデル作成シンタックス
a. シンタックス全体
まずは、シンタックス全体です。
#-------------------------------------------------------
# ライブラリインポート
#-------------------------------------------------------
# Modeler用ライブラリ
import modelerpy
# NumpyとPandas
import numpy as np
import pandas as pd
# モデル関連
# sklearn - PLS回帰
from sklearn.cross_decomposition import PLSRegression
# 精度検証用 R2乗、MSE、MAE
from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error
#-------------------------------------------------------
# データ入力
#-------------------------------------------------------
# 事前にデータ区分で学習・テストデータは分けているのでそのまま入力
# Pandasで入力
modelerData = modelerpy.readPandasDataframe()
# 説明変数 - 一番最後のoctaneを除いた全て
# ロールを対象に指定した"octane"が一番最後の列に移動しているので注意
xdata = modelerData.iloc[:, :-1] # 最後の列を除外
# 目的変数 - octane
ydata = modelerData['octane']
#ydata = modelerData.iloc[:, 0] # 1列目(index=0)を選択
#-------------------------------------------------------
# データ加工
#-------------------------------------------------------
# PLSで使用するために、説明変数をNumpyのndarrayに変換
input_data = xdata.values
# 目的変数はPandas.SeriesなのでそのままでOK
target_data = ydata
#-------------------------------------------------------
# パラメータ設定
#調査結果を反映。今回は 6
#-------------------------------------------------------
# n_componentsの設定
cnt_comp = 6
#-------------------------------------------------------
# PLSモデル作成
#-------------------------------------------------------
# 事前に分析したc_componentsを設定
pls_model = PLSRegression( n_components = cnt_comp )
# PLSモデル作成
pls_model.fit( input_data, target_data )
#-------------------------------------------------------
# PLSモデルの保存
#-------------------------------------------------------
#モデルオブジェクト
modelerModel = pls_model
#モデル名
modelName = "pls_predict_model"
#保存処理
modelerpy.saveModel(modelerModel, modelName)
#-------------------------------------------------------
# 各種統計量や情報の表示<不要なら削除してください>
# 拡張モデルノードのコンソール出力から確認できます。
#
# 1.予測値
# 2.精度確認
# 3.モデル回帰係数
# 4.モデル情報
#
#-------------------------------------------------------
#-------------------------------------------------------
# 1. 予測値
#-------------------------------------------------------
target_pred = modelerModel.predict( input_data )
print("Model Build Predict : " , target_pred )
#-------------------------------------------------------
# 2. 精度計算
#-------------------------------------------------------
#R2乗
r2 = r2_score(target_data, target_pred)
#MSE
mse = mean_squared_error(target_data, target_pred)
#MAE
mae = mean_absolute_error(target_data, target_pred)
# 結果出力
print("Model Build R2 : " ,r2 )
print("Model Build MSE : " ,mse )
print("Model Build MAE : " ,mae )
#-------------------------------------------------------
# 3. 回帰係数
#-------------------------------------------------------
#モデル回帰係数
print("Model Build PLS coef_ :", modelerModel.coef_)
#-------------------------------------------------------
# 4. モデル情報
#-------------------------------------------------------
# モデルタイプ
print("Model Build Type : " ,type(modelerModel))
# c_components値
print("Model Build PLS n_components: " ,modelerModel.n_components)
b. シンタックス詳細
では、詳細をみていきましょう。
b-1. ライブラリの追加
まずは、必要なライブラリをインポートしています。
精度確認のライブラリは任意で構いません。
#-------------------------------------------------------
# ライブラリインポート
#-------------------------------------------------------
# Modeler用ライブラリ
import modelerpy
# NumpyとPandas
import numpy as np
import pandas as pd
# モデル関連
# sklearn - PLS回帰
from sklearn.cross_decomposition import PLSRegression
# 精度検証用 R2乗、MSE、MAE
from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error
b-2. データ入力と加工
ModelerからデータをPandasで受け取り、モデルに投入するためにデータ加工します。
#-------------------------------------------------------
# データ入力
#-------------------------------------------------------
# 事前にデータ区分で学習・テストデータは分けているのでそのまま入力
# Pandasで入力
modelerData = modelerpy.readPandasDataframe()
# 説明変数 - 一番最後のoctaneを除いた全て
# ロールを対象に指定した"octane"が一番最後の列に移動しているので注意
xdata = modelerData.iloc[:, :-1] # 最後の列を除外
# 目的変数 - octane
ydata = modelerData['octane']
#ydata = modelerData.iloc[:, 0] # 1列目(index=0)を選択
#-------------------------------------------------------
# データ加工
#-------------------------------------------------------
# PLSで使用するために、説明変数をNumpyのndarrayに変換
input_data = xdata.values
# 目的変数はPandas.SeriesなのでそのままでOK
target_data = ydata
ポイントは、以下の記事で書いたとおり、データのフィールド順序が変わってしまうところです。
気をつけましょう。
目的変数と説明変数の設定、説明変数はモデル投入用にPandasからNumpyの配列に変換します。
Modeler特有の記述は、Modelerからデータを取り込むときの以下のコードとだけです。
modelerData = modelerpy.readPandasDataframe()
b-3. モデル作成
潜在変数の数を "6" に設定してから、モデルを構築します。
設定したらfit()でモデルを学習させています。
#-------------------------------------------------------
# パラメータ設定
#調査結果を反映。今回は 6
#-------------------------------------------------------
# n_componentsの設定
cnt_comp = 6
#-------------------------------------------------------
# PLSモデル作成
#-------------------------------------------------------
# 事前に分析したc_componentsを設定
pls_model = PLSRegression( n_components = cnt_comp )
# PLSモデル作成
pls_model.fit( input_data, target_data )
b-4. モデル保存
この部分の記述はModeler特有のものになります。
#-------------------------------------------------------
# PLSモデルの保存
#-------------------------------------------------------
#モデルオブジェクト
modelerModel = pls_model
#モデル名
modelName = "pls_predict_model"
#保存処理
modelerpy.saveModel(modelerModel, modelName)
作成したモデルを、任意の名前を付けて保存します。ここでは、"pls_predict_model"としています。
最後にモデルを保存します。
ここも、Modeler特有のコードです。覚えてください。
modelerpy.saveModel(modelerModel, modelName)
b-5. 各種指標など
最後は、任意で記述してください。
精度や、予測値、モデルタイプなどを出力する処理です。
このようにPrint()で記述すると、拡張モデルノードのコンソール出力の部分で内容が確認できます。
#-------------------------------------------------------
# 各種統計量や情報の表示<不要なら削除してください>
# 拡張モデルノードのコンソール出力から確認できます。
#
# 1.予測値
# 2.精度確認
# 3.モデル回帰係数
# 4.モデル情報
#
#-------------------------------------------------------
#-------------------------------------------------------
# 1. 予測値
#-------------------------------------------------------
target_pred = modelerModel.predict( input_data )
print("Model Build Predict : " , target_pred )
#-------------------------------------------------------
# 2. 精度計算
#-------------------------------------------------------
#R2乗
r2 = r2_score(target_data, target_pred)
#MSE
mse = mean_squared_error(target_data, target_pred)
#MAE
mae = mean_absolute_error(target_data, target_pred)
# 結果出力
print("Model Build R2 : " ,r2 )
print("Model Build MSE : " ,mse )
print("Model Build MAE : " ,mae )
#-------------------------------------------------------
# 3. 回帰係数
#-------------------------------------------------------
#モデル回帰係数
print("Model Build PLS coef_ :", modelerModel.coef_)
#-------------------------------------------------------
# 4. モデル情報
#-------------------------------------------------------
# モデルタイプ
print("Model Build Type : " ,type(modelerModel))
# c_components値
print("Model Build PLS n_components: " ,modelerModel.n_components)
こんな感じです。
iv. スコアリングシンタックス
続いて、作成したモデルをロードして結果を出力するスコアリングシンタックスを記述します。
a.シンタックス全体
#-------------------------------------------------------
# ライブラリインポート
#-------------------------------------------------------
# Modeler用ライブラリ
import modelerpy
# NumpyとPandas
import numpy as np
import pandas as pd
# sklearn - PLS回帰
from sklearn.cross_decomposition import PLSRegression
#---------------------------------------------------------
#モデル取得用設定
#---------------------------------------------------------
# 予測値格納フィールド名
predictField = "$PLS-octane"
#モデル名
modelName = "pls_predict_model"
#--------------------------------------------------------------
#データモデル定義処理
#--------------------------------------------------------------
if modelerpy.isComputeDataModelOnly():
#--------------------------------------------------------------
#データモデル取得
#--------------------------------------------------------------
modelerDataModel = modelerpy.getDataModel()
#--------------------------------------------------------------
#モデル用変数フィールドを追加
#--------------------------------------------------------------
#予測値用フィールドを追加 - predictField
modelerDataModel.addField(modelerpy.Field( predictField, "real", measure="continuous"))
#修正したデータモデルをModelerへ戻します。
modelerpy.setOutputDataModel(modelerDataModel)
#--------------------------------------------------------------
#PLSモデル 予測処理
#--------------------------------------------------------------
else:
#-------------------------------------------------------
# データ入力
#-------------------------------------------------------
modelerData = modelerpy.readPandasDataframe()
# 説明変数 - 2列目以降を説明変数とする
xdata = modelerData.iloc[:, 1:] # 2列目(index=1)以降を選択
#-------------------------------------------------------
# データ加工
#-------------------------------------------------------
# PLSで使用するために、説明変数をNumpyのndarrayに変換
input_data = xdata.values
#-------------------------------------------------------
# スコアリングモデル呼び出し
#-------------------------------------------------------
#モデルをロード
modelerModel = modelerpy.loadModel( modelName )
#-------------------------------------------------------
# スコアリング実行
#-------------------------------------------------------
# predict()で予測値を取得
target_pred = modelerModel.predict( input_data )
#-------------------------------------------------------
# スコアリング結果を戻す
#-------------------------------------------------------
# 予測値を DataFrame に変換し、カラム名を設定
target_pred_df = pd.DataFrame( target_pred, index=modelerData.index, columns=[ predictField ])
# 入力データに統合
outputData = pd.concat([ modelerData, target_pred_df ], axis=1)
# Modelerに結果を戻す
modelerpy.writePandasDataframe( outputData )
b.シンタックス詳細
では詳細をみていきましょう。
b-1. ライブラリ導入
ここは、必要なライブラリをインポートしている部分ですね。
まぁ、モデル作成時と同じです。精度確認用などは削除しています。
#-------------------------------------------------------
# ライブラリインポート
#-------------------------------------------------------
# Modeler用ライブラリ
import modelerpy
# NumpyとPandas
import numpy as np
import pandas as pd
# sklearn - PLS回帰
from sklearn.cross_decomposition import PLSRegression
b-2. 定数設定 - モデル取得用設定
予測結果を格納するためのフィールド名と、
モデル作成時に定義したモデル名を設定しています。
"$-対象フィールド名" として予測結果フィールドを定義しておくと、精度分析ノードで簡単に利用ができるようになります。
なので、**"$PLS-octane"**としています。
#---------------------------------------------------------
#モデル取得用設定
#---------------------------------------------------------
# 予測値格納フィールド名
predictField = "$PLS-octane"
#モデル名
modelName = "pls_predict_model"
b-3. データモデル定義
後続ノードへデータを渡すためにデータモデル定義をしています。
データモデルを取得して、予測値を格納するためのフィールドを追加しています。
ここでの、データモデルの取得や、Modelerへ戻すコードは必須なので覚えておきましょう。
#--------------------------------------------------------------
#データモデル定義処理
#--------------------------------------------------------------
if modelerpy.isComputeDataModelOnly():
#--------------------------------------------------------------
#データモデル取得
#--------------------------------------------------------------
modelerDataModel = modelerpy.getDataModel()
#--------------------------------------------------------------
#モデル用変数フィールドを追加
#--------------------------------------------------------------
#予測値用フィールドを追加 - predictField
modelerDataModel.addField(modelerpy.Field( predictField, "real", measure="continuous"))
#修正したデータモデルをModelerへ戻します。
modelerpy.setOutputDataModel(modelerDataModel)
b-4. スコアリング処理
少し長いですが、それほど難しいことをしていません。
#--------------------------------------------------------------
#PLSモデル 予測処理
#--------------------------------------------------------------
else:
#-------------------------------------------------------
# データ入力
#-------------------------------------------------------
modelerData = modelerpy.readPandasDataframe()
# 説明変数 - 2列目以降を説明変数とする
xdata = modelerData.iloc[:, 1:] # 2列目(index=1)以降を選択
#-------------------------------------------------------
# データ加工
#-------------------------------------------------------
# PLSで使用するために、説明変数をNumpyのndarrayに変換
input_data = xdata.values
#-------------------------------------------------------
# スコアリングモデル呼び出し
#-------------------------------------------------------
#モデルをロード
modelerModel = modelerpy.loadModel( modelName )
#-------------------------------------------------------
# スコアリング実行
#-------------------------------------------------------
# predict()で予測値を取得
target_pred = modelerModel.predict( input_data )
#-------------------------------------------------------
# スコアリング結果を戻す
#-------------------------------------------------------
# 予測値を DataFrame に変換し、カラム名を設定
target_pred_df = pd.DataFrame( target_pred, index=modelerData.index, columns=[ predictField ])
# 入力データに統合
outputData = pd.concat([ modelerData, target_pred_df ], axis=1)
# Modelerに結果を戻す
modelerpy.writePandasDataframe( outputData )
データ加工部分では、説明変数の設定部分が異なります。要注意です。
スコアリングシンタックスでは、"octane" フィールドの位置は 最後に移動しない ので、一番先頭にあります。
そのため、octaneを除く 2列目以降 を設定しています。
その他は、モデル作成シンタックスと一緒ですね。
#-------------------------------------------------------
# データ入力
#-------------------------------------------------------
modelerData = modelerpy.readPandasDataframe()
# 説明変数 - 2列目以降を説明変数とする
xdata = modelerData.iloc[:, 1:] # 2列目(index=1)以降を選択
#-------------------------------------------------------
# データ加工
#-------------------------------------------------------
# PLSで使用するために、説明変数をNumpyのndarrayに変換
input_data = xdata.values
モデルのロードは、モデル作成時に保存した名前を指定します。
ロードの仕方もModeler特有ですので覚えておいてください。
予測値の算出は、predict()を使い実行します。
#-------------------------------------------------------
# スコアリングモデル呼び出し
#-------------------------------------------------------
#モデルをロード
modelerModel = modelerpy.loadModel( modelName )
#-------------------------------------------------------
# スコアリング実行
#-------------------------------------------------------
# predict()で予測値を取得
target_pred = modelerModel.predict( input_data )
データは、Pandasで戻す必要があるので、予測値をデータフレーム形式に変換してから、入力データと結合します。
そして、Modelerへ戻します。
Modelerへデータを戻すコードも覚えておいてください。
#-------------------------------------------------------
# スコアリング結果を戻す
#-------------------------------------------------------
# 予測値を DataFrame に変換し、カラム名を設定
target_pred_df = pd.DataFrame( target_pred, index=modelerData.index, columns=[ predictField ])
# 入力データに統合
outputData = pd.concat([ modelerData, target_pred_df ], axis=1)
# Modelerに結果を戻す
modelerpy.writePandasDataframe( outputData )
v. モデルの作成
シンタックスを記述後にモデルオプションタブで、スコアリング用ナゲットの名称を指定しておきます。
ここでは、"PLS_MODEL"としています。
※.任意です。デフォルトでは"Script"という名称でナゲットが生成されます。
注釈タブで、ノード名称を"PLS"と指定しています。
※.こちらも任意です。自由に設定してください。しなくてもOKです。
"実行" します。
正常終了すると、スコアリング用のナゲットが作成され、キャンバスに追加されます。
普通のモデル作成ノードと同じですね。
ナゲットの中身は先ほど記述したスコアリングシンタックスがコピーされています。
ここに、直接シンタックスを記述してもよいのですが、モデル作成を再度実行すると上書きされてしまいます。注意しましょう。
④. 結果の確認
i. 予測結果の確認
テーブルノードで予測結果を確認します。きちんと結果が出力されていますね。
ii. 精度の確認
精度分析ノードで結果を精度を確認します。
予測フィールドの検出設定は、
フィールド名の形式(たとえば "$-<対象フィールド>")
を選択し実行します。
線形相関及び誤差を確認します。結構いい精度がでていますね。
⑤. テストデータでの確認
i. テストデータの選択、フィールド削除
モデル作成時のストリームと同じように、今回はテストデータのみにします。
条件抽出ノードはモードを 破棄 に変更しただけですね。
フィルターノードは、データ区分を削除
ii. テストデータでのスコアリング
スコアリング用ナゲットをコピーして、フィルターノードからリンクします。
iii. 予測結果の確認
テーブルノードで結果を確認します。きちんとテストデータで予測値が算出されていますね。
iv. 精度の確認
精度分析ノードもコピーして流用しましょう。
結果を確認すると、若干精度は落ちていますが、よいのではないでしょうか?
v. 精度の確認 - 散布図
散布図でも予測値と、実測値の関係を確認しましょう。
以下のように設定して、実行しましょう。
・X軸 に "octane"(実測値)
・Y軸 に "$PLS-octane"(予測値)
・オーバーレイ に 関数 y = x を設定
以下のような結果になりました。
2. まとめ
ちょっと、長い記事となりましたがいかがでしたでしょうか。
SPSS ModelerにはPLS回帰のモデルノードはありませんが、Pythonを使ってモデルを作成してみました。
途中、はまってしまった箇所もありましたが、なんとか実装までたどり着いた感じです。
実は、今回のように拡張ノードを使わなくてもPLS回帰は実装できます。
それは、SPSS StatisticsをSPSS Modelerと連携させて利用する方法です。
次回以降は、そちらを紹介していく予定です。
参考
SPSS Modeler ノードリファレンス目次
SPSS Modeler 逆引きストリーム集
SPSS funさん記事集
SPSS連載ブログバックナンバー
SPSSヒモトクブログ
今後は、ヒモトクブログなどは以下のTechXchangeのコミュニティに統合される予定です。
ご興味がある方は、ぜひiBM IDを登録して参加してみてください!!!お待ちしています。
IBM TechXchange Data Science Japan