2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SPSS ModelerでPLSを実装してみる。その2 PLS回帰モデルを作成する

Last updated at Posted at 2025-03-07

はじめに

みなさん、こんにちわ。さて、引き続きPLSを実装していきます。前回、PLSでの潜在変数(PLS成分)の最適な数を調査し最適な数は、"6"とわかりました。今回は、そのパラメータ値を使って拡張モデルノードでPLSモデルを実装します。

※ 2025/03/14 記事で使用したストリームをGitHubにアップロードしました。

データについては、以下のリンクより"gasoline.csv"をダウンロードしてください。

1. PLSモデルを実装していく

①. ストリーム全体

以下が、ストリーム全体です。
途中の特徴量選択ノードまでは、前回とほぼ同じです。
特徴量選択ナゲットから、上側のストリームはモデル作成用、下側のストリームはスコアリング用となっています。

image.png

②. データ入力から、特徴量選択まで

i. データ入力

image.png

同じ "gasoline.csv" を使います。ダウンロードは以下よりお願いします。

可変長ファイルノードで入力します。設定は、
・NIR 1246 nm
・NIR 1248 nm
・NIR 1348 nm
上記3つのフィールドの ストレージ"実数" に変更してください。

image.png

また、不要なフィールドである "1"フィールドをフィルタータブで除外していおきましょう。

image.png

ii. 学習データ・テストデータ分割

image.png

データ区分ノードで、
学習 80
テスト 20
と値を変更してください。
(※. この値は任意です。ユーザーさんで自由に設定してください。)

image.png

iii. インスタンス化

image.png

データ型ノードで、インスタンス化してます。
フィールドの ロール を以下のように設定し、値の読み込み をてください。

octane "対象"
octane以外 "入力" (デフォルトで入力になっています。)

image.png

iv. 説明変数の絞り込み

image.png

image.png

特徴量選択ノードで、octane への影響が強い変数に絞り込みます。
特に設定は変更せずに 実行 してください。

image.png

先ほどデータ型ノードで

フィールドの ロール
octane "対象"
octane以外 "入力"
と設定しています。

特徴量選択ノードは、対象フィールドと入力フィールドとの関係性を分析して、有意な相関があればそれをランク付けしてくれるのです。

今回 octane と 説明変数であるスペクトル変数は、どちらも数値データですので 相関係数に基づいた t 統計 を計算してランクを付けています。

対象の変数がカテゴリデータの場合は、以下のように、カイ二乗値などの指標が使われます。
(ユーザーが選択できます。)

image.png

v. 説明変数の絞り込み その2

image.png

image.png

octane と相関が認められない変数や相関が弱い変数はチェックが外れてスクリーニングされます。
(※. ユーザーが自由にチェックは入れたり外したりできます。)

③. PLS回帰モデルの作成

続いては、学習データでPLS回帰モデルを作成していきます。

image.png

i. データの絞り込み

image.png

条件抽出ノードで、学習データのみ選択します。

image.png

ii. 不要フィールド削除

フィルターノードで"データ区分"フィールドを除外しておきます。

image.png

image.png

iii. PLSモデル作成 - モデル作成シンタックス

image.png

image.png

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)

こんな感じです。

image.png

iv. スコアリングシンタックス

続いて、作成したモデルをロードして結果を出力するスコアリングシンタックスを記述します。

image.png

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"という名称でナゲットが生成されます。

image.png

注釈タブで、ノード名称を"PLS"と指定しています。
※.こちらも任意です。自由に設定してください。しなくてもOKです。

image.png

"実行" します。

image.png

正常終了すると、スコアリング用のナゲットが作成され、キャンバスに追加されます。
普通のモデル作成ノードと同じですね。

image.png

ナゲットの中身は先ほど記述したスコアリングシンタックスがコピーされています。
ここに、直接シンタックスを記述してもよいのですが、モデル作成を再度実行すると上書きされてしまいます。注意しましょう。

image.png

④. 結果の確認

i. 予測結果の確認

image.png

テーブルノードで予測結果を確認します。きちんと結果が出力されていますね。

image.png

ii. 精度の確認

image.png

精度分析ノードで結果を精度を確認します。
予測フィールドの検出設定は、
フィールド名の形式(たとえば "$-<対象フィールド>")
を選択し実行します。

image.png

線形相関及び誤差を確認します。結構いい精度がでていますね。

image.png

⑤. テストデータでの確認

i. テストデータの選択、フィールド削除

image.png

モデル作成時のストリームと同じように、今回はテストデータのみにします。
条件抽出ノードはモードを 破棄 に変更しただけですね。

image.png

フィルターノードは、データ区分を削除

image.png

ii. テストデータでのスコアリング

スコアリング用ナゲットをコピーして、フィルターノードからリンクします。

image.png

iii. 予測結果の確認

image.png

テーブルノードで結果を確認します。きちんとテストデータで予測値が算出されていますね。

image.png

iv. 精度の確認

image.png

精度分析ノードもコピーして流用しましょう。
結果を確認すると、若干精度は落ちていますが、よいのではないでしょうか?

image.png

v. 精度の確認 - 散布図

image.png

散布図でも予測値と、実測値の関係を確認しましょう。

以下のように設定して、実行しましょう。

X軸"octane"(実測値)
Y軸"$PLS-octane"(予測値)
オーバーレイ関数 y = x を設定

image.png

以下のような結果になりました。

image.png

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

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?