PLS回帰(部分的最小二乗法)とは?多重共線性に強い回帰をスクラッチ実装で理解する

近赤外(NIR)スペクトルから薬の成分濃度を当てたい、あるいは工場に並ぶ数百個のセンサーの値から製品の品質を予測したい——こうした場面では、説明変数の数がサンプル数より多く、しかも変数同士が強く相関していることがほとんどです。隣り合う波長の吸光度はほぼ同じ値になりますし、温度センサーと圧力センサーも連動して動きます。

このとき、素朴な最小二乗法(OLS)による重回帰はほぼ役に立ちません。変数同士が強く相関する(多重共線性)と、回帰係数が異常に大きな正負の値に暴れ、わずかなノイズで予測がガラリと変わってしまうからです。変数の数がサンプル数を超えると、そもそも解が一意に定まりません。

この困りごとを正面から解決するのが PLS回帰(部分的最小二乗法 / Partial Least Squares Regression) です。PLSは、説明変数 $X$ を「目的変数 $y$ の予測に効く少数の方向」へ圧縮してから回帰します。主成分分析(PCA)が $X$ の分散だけを見て圧縮するのに対し、PLSは $y$ との関係を見ながら圧縮する——この一点が、PLSを多変量解析の主役に押し上げています。

この記事では次の問いに答えていきます。

  • 問い1: なぜ多重共線性があるとOLSは破綻し、PLSは耐えられるのか?
  • 問い2: PLSは具体的にどんな計算で「$y$ に効く方向」を見つけるのか? そのアルゴリズム(NIPALS)はどう導かれるのか?

PLSの応用は広く、ケモメトリクス(分光スペクトルから成分濃度や品質を推定)と、プロセス産業のソフトセンサー(多数のプロセス変数から測りにくい品質をオンライン推定)が二大分野です。実際、製薬の粉体プロセスを対象にした最近のゼロショット回帰の研究でも、予測器の中核としてPLSが使われています。それだけ「高次元・共線性・少サンプル」という現実のデータに強い手法なのです。

PLS回帰の概念:Yとの共分散が大きい方向へXを圧縮する

上の図がPLSの全体像です。多数で共線性のある説明変数 $X$ を、少数の潜在変数 $T$($t = Xw$)へ圧縮し、その潜在変数で $y$ を予測します。鍵は中央の圧縮の仕方で、PCAが「$X$ の分散」だけを見るのに対し、PLSは「$Xw$ と $y$ の共分散」が最大になる方向 $w$ を選びます。この記事では、この一文を数式とコードで完全に解きほぐします。

前提知識

この記事は、以下を理解していると一段読みやすくなります。

  • 重回帰(最小二乗法)の考え方と正規方程式
  • 主成分分析(PCA)による次元圧縮の発想
  • 共分散・分散の意味

不安があれば、先に次の記事を眺めておくとよいでしょう。

まずは「なぜOLSが多重共線性で壊れるのか」を具体的に見て、PLSの必要性を体で感じるところから始めます。

多重共線性とOLSの限界

重回帰の最小二乗解は、説明変数行列を $X$(中心化済み、$n$ サンプル × $p$ 変数)、目的変数を $y$ として、正規方程式

$$ \begin{equation} \hat{\bm{\beta}}_{\text{OLS}} = (X^\top X)^{-1} X^\top \bm{y} \end{equation} $$

で与えられます。ここで問題になるのが $X^\top X$ の逆行列です。変数同士が強く相関していると、$X^\top X$ はほぼ特異(行列式がほぼ0)になります。逆行列の要素が爆発的に大きくなり、その結果、回帰係数 $\hat{\bm{\beta}}$ も極端な正負の値に振れます。変数の数 $p$ がサンプル数 $n$ を超える($p > n$)と、$X^\top X$ は正則ですらなくなり、解は一意に定まりません。

もう少し定量的に見ましょう。最小二乗推定量の分散は $X^\top X$ の固有値の逆数に比例します。共線性によって最小固有値 $\lambda_{\min}$ が0に近づくと、その固有ベクトル方向の係数の分散が $1/\lambda_{\min}$ で跳ね上がります。これが「係数の暴れ」の数学的な正体です。行列の最大固有値と最小固有値の比である条件数 $\kappa = \lambda_{\max}/\lambda_{\min}$ が大きいほど、入力のわずかなノイズが係数に大きく増幅される——つまり推定が不安定になります。PLSはこの「悪条件な逆行列」を避け、安定な少数方向だけで回帰する戦略だと言えます。

どれくらい相関が強いかを、実際のデータで見てみましょう。以下では、2つの「真の潜在因子」から20個の観測変数を作ることで、わざと強い多重共線性を持つデータを用意します。

import numpy as np

def make_chem_data(n=80, p=20, seed=0):
    """真の潜在因子2つ + 20観測変数(共線性)+ ノイズ。スペクトル風データ。"""
    rng = np.random.default_rng(seed)
    F = rng.normal(size=(n, 2))                       # 真の潜在因子(2次元)
    load = rng.normal(size=(2, p))                    # 因子 → 観測変数への混合
    X = F @ load + 0.3 * rng.normal(size=(n, p))      # 観測される20変数
    y = 3.0 * F[:, 0] - 2.0 * F[:, 1] + 0.2 * rng.normal(size=n)  # 品質値
    return X, y

X, y = make_chem_data()
corr = np.corrcoef(X.T)
print("変数間の相関の絶対値の平均:", np.mean(np.abs(corr[np.triu_indices(20, 1)])).round(3))

このデータは、20個の観測変数がたった2つの因子の線形結合でできているので、変数同士が強く相関します。相関の絶対値の平均はおよそ0.5前後になり、相関行列を可視化すると赤と青のブロックがはっきり現れます。

説明変数間の相関行列:強い多重共線性

この図は20変数間の相関行列です。対角を除く多くのセルが濃い赤(正の強い相関)や濃い青(負の強い相関)で埋まっており、変数が互いに強く連動していることがわかります。これがまさに多重共線性で、OLSが苦手とする状況です。本質的な情報は2次元しかないのに、20次元で無理に回帰しようとすると破綻するのです。

実際にOLSとPLSの回帰係数を比べると、その差は歴然です。

回帰係数の比較:共線性下でOLSは暴れ、PLSは安定

この図は、同じデータに対するOLS係数(灰)とPLS係数(青、2成分)を並べたものです。OLSの係数は変数ごとに大きな正負へ激しく振れているのに対し、PLSの係数はなだらかで安定しています。実際に係数ベクトルの大きさ(ノルム)を測ると、OLSが約1.02なのに対しPLSは約0.80と小さく抑えられています。OLSは共線性に引きずられて「打ち消し合う巨大な係数」を作ってしまい、ノイズに過敏になります。一方PLSは少数の潜在変数だけを使うため、係数が暴れません。

では、PLSはどうやってこの「安定した少数の方向」を見つけているのでしょうか。鍵は、PCAとの決定的な違いにあります。

PLSとPCAの違い — 「Yを見て圧縮する」

PLSは1970年代に計量経済学者 Herman Wold が開発し、息子の Svante Wold が化学計量学に持ち込んで一気に広まりました。名前の「部分的最小二乗」は、全変数を一度に解くのではなく、潜在変数を1つずつ抽出する各ステップで部分的に最小二乗を解くことに由来します。発想の核は「$y$ を予測するのに役立つ方向だけを残す」という、徹底して目的志向の次元圧縮にあります。これをPCAと対比すると違いがくっきりします。

PCAは、説明変数 $X$ の分散が最大になる方向を主成分として取り出します。これは $X$ だけを見た圧縮で、目的変数 $y$ は一切考慮しません。問題は、「$X$ の分散が大きい方向」が必ずしも「$y$ の予測に効く方向」とは限らないことです。ノイズや無関係な変動が大きい方向を主成分として拾ってしまうと、予測に役立たない圧縮になります。

PLSはここを変えます。$X$ を方向 $\bm{w}$ に射影した潜在変数 $t = X\bm{w}$ が、$y$ との共分散を最大化するように $\bm{w}$ を選ぶのです。つまり「分散最大」ではなく「$y$ との共分散最大」を圧縮の基準にします。

$$ \begin{equation} \max_{\bm{w}} \ \mathrm{Cov}(X\bm{w}, \bm{y}) \quad \text{subject to} \quad \|\bm{w}\| = 1 \end{equation} $$

ここで相関係数ではなく共分散を最大化するのがポイントです。相関は分散で割って正規化するため「方向の向き」しか見ませんが、共分散は分散の大きさも反映します。その結果PLSは、$y$ と関係が深く、かつ $X$ 側でも十分な変動を持つ——つまり情報量の多い方向を優先的に選びます。これが少数成分で安定した予測を生む理由の一つです。

この違いを図で見ると一目瞭然です。

PCAの方向(分散最大)とPLSの方向(yとの共分散最大)の違い

点の色は目的変数 $y$ の値を表します。灰色の線がPCA方向(分散が最大の縦長方向)、赤い線がPLS方向($y$ との共分散が最大の方向)です。点の色は左下から右上ではなく、$x_1$ の増加方向(おおむね横方向)に沿って変化しているので、$y$ を予測したいなら赤い方向に圧縮すべきです。ところがPCAは分散だけを見て縦方向(灰)を選んでしまい、$y$ の予測には的外れになります。PLSは色の勾配=$y$ との関係を捉えて、予測に効く方向を選ぶのです。

主成分回帰(PCR)との対比

PCAを使った回帰として 主成分回帰(PCR: Principal Component Regression) があります。PCRは「PCAで $X$ を主成分に圧縮 → その主成分で $y$ を回帰」という2段構えで、PLSと混同されがちです。しかし圧縮の段階で $y$ を一切見ていない点が決定的に違います。PCRでは、$y$ と無関係でも分散が大きい主成分が上位に来てしまい、逆に「分散は小さいが $y$ の予測に効く方向」を捨ててしまう危険があります。PLSは最初から $y$ との共分散で方向を選ぶため、同じ成分数ならPLSのほうが少ない成分で高い予測精度に達することが多いのです。「教師なしで圧縮してから回帰する(PCR)」のか、「教師あり情報を使いながら圧縮する(PLS)」のか——この一点が、現場でPCRよりPLSが好まれる理由です。

この「共分散最大化」を実際の計算手順に落とし込むと、有名な NIPALSアルゴリズム になります。次節でその重みベクトルを導出します。

共分散最大化からNIPALSを導く

第1の重みベクトル

中心化されたデータ(各列の平均が0)を仮定します。$t = X\bm{w}$ と $\bm{y}$ の共分散は、サンプル数の定数倍を除けば $(X\bm{w})^\top \bm{y} = \bm{w}^\top X^\top \bm{y}$ に比例します。したがって最大化問題は

$$ \begin{equation} \max_{\bm{w}} \ \bm{w}^\top (X^\top \bm{y}) \quad \text{subject to} \quad \|\bm{w}\|^2 = 1 \end{equation} $$

となります。これはラグランジュ未定乗数法で簡単に解けます。ラグランジアンを

$$ \mathcal{L}(\bm{w}, \lambda) = \bm{w}^\top (X^\top \bm{y}) – \lambda(\bm{w}^\top \bm{w} – 1) $$

と置き、$\bm{w}$ で微分して0とおくと、

$$ \frac{\partial \mathcal{L}}{\partial \bm{w}} = X^\top \bm{y} – 2\lambda \bm{w} = \bm{0} $$

が得られます。ここから $\bm{w} \propto X^\top \bm{y}$ がわかります。制約 $\|\bm{w}\| = 1$ を満たすように正規化すれば、第1の重みベクトルは

$$ \begin{equation} \bm{w}_1 = \frac{X^\top \bm{y}}{\|X^\top \bm{y}\|} \end{equation} $$

と、驚くほど単純な形になります。「各変数と $y$ の共分散($X^\top \bm{y}$ の各成分)に比例した重みを付ける」というのが、PLSの第1成分の正体です。$y$ と強く連動する変数ほど大きな重みを受け取ります。

スコア・ローディングとデフレーション

第1の重み $\bm{w}_1$ が決まったら、潜在変数(スコア)$\bm{t}_1 = X\bm{w}_1$ を計算します。次に、この $\bm{t}_1$ で $X$ と $\bm{y}$ を回帰したときの係数(ローディング)を求めます。

$$ \begin{equation} \bm{p}_1 = \frac{X^\top \bm{t}_1}{\bm{t}_1^\top \bm{t}_1}, \qquad q_1 = \frac{\bm{y}^\top \bm{t}_1}{\bm{t}_1^\top \bm{t}_1} \end{equation} $$

$\bm{p}_1$ は「$\bm{t}_1$ が各説明変数をどれだけ説明するか」、$q_1$ は「$\bm{t}_1$ が $y$ をどれだけ説明するか」を表します。第2成分以降は、第1成分が説明した分を差し引いた残差に対して、同じ手続きを繰り返します。この差し引きを デフレーション(deflation) と呼びます。

$$ \begin{equation} X \leftarrow X – \bm{t}_1 \bm{p}_1^\top, \qquad \bm{y} \leftarrow \bm{y} – q_1 \bm{t}_1 \end{equation} $$

デフレーション後の $X, \bm{y}$ に対して再び $\bm{w}_2 = X^\top \bm{y} / \|X^\top \bm{y}\|$ を求め……と繰り返すことで、互いに直交する潜在変数を順番に取り出していきます。これがNIPALS(Nonlinear Iterative Partial Least Squares)アルゴリズムです。

デフレーションが効くのは、$\bm{t}_1$ が説明できる成分を $X$ から完全に取り除くからです。残差 $X – \bm{t}_1\bm{p}_1^\top$ は構成上 $\bm{t}_1$ と直交するため、次に得られるスコア $\bm{t}_2$ は $\bm{t}_1$ と無相関になります。こうして各潜在変数が重複のない情報を担い、少数の成分で効率よく $y$ を説明できるわけです。逆に言えば、デフレーションを忘れると同じ方向を何度も拾ってしまい、成分を増やす意味がなくなります。

NIPALSアルゴリズムの流れ

図がNIPALSの1サイクルです。①$y$ との共分散で重み $\bm{w}$ を決め、②スコア $\bm{t}=X\bm{w}$ を計算し、③ローディング $\bm{p}, q$ を求め、④その寄与を $X, \bm{y}$ から差し引く(デフレーション)。これを指定した成分数まで繰り返します。各ステップが先ほど導いた式と一対一に対応していることを確認してください。

回帰係数の組み立て

最後に、抽出した重み $W = [\bm{w}_1, \dots, \bm{w}_A]$、ローディング $P = [\bm{p}_1, \dots, \bm{p}_A]$、$Q = [q_1, \dots, q_A]^\top$ から、元の説明変数 $X$ に対する回帰係数ベクトルを次の公式で組み立てます。

$$ \begin{equation} \bm{\beta}_{\text{PLS}} = W (P^\top W)^{-1} Q \end{equation} $$

これにより、予測は $\hat{\bm{y}} = X \bm{\beta}_{\text{PLS}} + \bar{y}$($\bar{y}$ は $y$ の平均)と、通常の線形回帰と同じ形で書けます。成分数 $A$ を変数の数より十分小さく選ぶことで、少数の安定した方向だけを使った回帰が実現します。

理論が出そろったので、これをそのままコードにしてみましょう。数式とコードが一対一で対応していることが、PLSの理解を確かなものにします。

Pythonでスクラッチ実装する

NIPALSの実装

上で導いた手順を、NumPyでそのまま実装します。単一の目的変数に対するPLS(PLS1)です。

import numpy as np

def pls1_nipals(X, y, n_comp):
    """単一出力PLS(PLS1)のNIPALS実装。中心化済みのX, yを渡す。"""
    X = X.copy().astype(float)
    y = y.copy().astype(float).ravel()
    n, p = X.shape
    W = np.zeros((p, n_comp)); P = np.zeros((p, n_comp))
    Q = np.zeros(n_comp); T = np.zeros((n, n_comp))
    for a in range(n_comp):
        w = X.T @ y
        w /= np.linalg.norm(w)        # ① 重み(||w||=1に正規化)
        t = X @ w                      # ② スコア(潜在変数)
        tt = t @ t
        p_load = X.T @ t / tt          # ③ Xローディング
        q = (y @ t) / tt               # ③ yローディング(スカラー)
        X = X - np.outer(t, p_load)    # ④ デフレーション
        y = y - q * t
        W[:, a] = w; P[:, a] = p_load; Q[a] = q; T[:, a] = t
    beta = W @ np.linalg.inv(P.T @ W) @ Q   # 回帰係数
    return beta, W, P, Q, T

各行が前節の数式と対応しています。w = X.T @ y が重みの導出式、t = X @ w がスコア、X - np.outer(t, p_load) がデフレーション、最後の W @ inv(P.T @ W) @ Q が回帰係数の公式です。たった十数行でPLSの本体が書けてしまうのは、共分散最大化の解が単純な形だったおかげです。

sklearnと一致するか確かめる

スクラッチ実装が正しいかどうかは、定評ある実装と突き合わせるのが一番です。scikit-learnPLSRegression と回帰係数を比べてみます。

from sklearn.cross_decomposition import PLSRegression

X, y = make_chem_data()
Xc = X - X.mean(0)
yc = y - y.mean()

beta, *_ = pls1_nipals(Xc, yc, n_comp=2)

model = PLSRegression(n_components=2, scale=False)
model.fit(Xc, yc)
beta_sklearn = model.coef_.ravel()

print("係数の最大差:", np.max(np.abs(beta - beta_sklearn)))

実行すると、係数の最大差は約 $1.4 \times 10^{-16}$ という、浮動小数点の丸め誤差レベルの値になります。つまりスクラッチ実装はsklearnと完全に一致しています。自分で導いた式がそのまま正しく動くことを確認できると、PLSが「ブラックボックスの関数」ではなく「自分で組み立てられる手法」になります。

では、実務で最も重要な「成分数をいくつにするか」という問題に進みましょう。

成分数を交差検証で選ぶ

PLSで唯一決めるべきハイパーパラメータが成分数(使う潜在変数の個数)です。少なすぎると $y$ の情報を取りこぼし(過小適合)、多すぎるとノイズまで拾って過学習します。最適な成分数は、交差検証(クロスバリデーション)で予測誤差が最小になる点として選びます。

def kfold_rmse(X, y, n_comp, k=5, seed=0):
    rng = np.random.default_rng(seed)
    idx = rng.permutation(len(y))
    folds = np.array_split(idx, k)
    errs = []
    for f in folds:
        te = f
        tr = np.setdiff1d(idx, te)
        mx, my = X[tr].mean(0), y[tr].mean()
        beta, *_ = pls1_nipals(X[tr] - mx, y[tr] - my, n_comp)
        pred = (X[te] - mx) @ beta + my
        errs.append(np.sqrt(np.mean((y[te] - pred) ** 2)))
    return np.mean(errs)

comps = np.arange(1, 11)
cv = [kfold_rmse(X, y, c) for c in comps]
best = comps[int(np.argmin(cv))]
print("最適成分数:", best, " CV-RMSE:", round(min(cv), 3))

成分数とRMSE:交差検証で最適成分数を選ぶ

この図は成分数に対する訓練RMSE(灰)と交差検証RMSE(赤)です。訓練RMSEは成分数を増やすほど単調に下がり続けますが、交差検証RMSEは成分数2で最小になり、その後はほぼ横ばい〜微増します。データを2因子から作ったので、本質的な情報は2成分で尽きているわけです。実行結果でも最適成分数は2、そのときのCV-RMSEは約0.378でした。訓練誤差だけを見て成分数を増やすと過学習する、という機械学習の基本がここにも現れています。

成分数が決まったら、その潜在変数空間でデータがどう並んでいるかを見てみましょう。

スコアプロットと予測精度

PLSの潜在変数(スコア)$t_1, t_2$ を2軸にとった散布図をスコアプロットと呼びます。サンプルの全体像や外れ値の把握に使う、ケモメトリクスの定番図です。

スコアプロット:潜在変数空間でのサンプル分布

この図は第1成分スコア $t_1$ を横軸、第2成分スコア $t_2$ を縦軸にとり、点の色で $y$ の値を示したものです。$t_1$ が大きいほど $y$ が大きい(色が変わる)方向に並んでおり、第1成分が $y$ の主要な変動を捉えていることがわかります。20次元のデータが、たった2次元の潜在空間で意味のある構造に整理されているのです。

実際の予測精度も確認します。

実測値と予測値の対応

横軸が実測値、縦軸がPLS(2成分)の予測値で、点が対角線(破線)に近いほど予測が正確です。点はほぼ対角線上に乗っており、決定係数 $R^2$ は約0.987と高い値になりました。20変数の生データを使いながら、わずか2成分で品質をほぼ完璧に再現できています。これがPLSの威力です。

汎化性能でもPLSは素朴なOLSに勝ります。同じデータで全20変数のOLSを5分割交差検証するとRMSEは約0.477でしたが、PLS(2成分)は約0.378でした。変数を全部使う回帰より、$y$ に効く2方向だけに絞ったPLSのほうが未知データをよく当てる——「次元を減らすことが精度向上につながる」という、多重共線性下での教訓がはっきり表れています。

最後に、PLSが各成分・各変数をどう評価しているかを2つの図で見ます。

累積説明率とVIP

各成分が $X$ と $y$ の分散をどれだけ説明するかを累積で見ると、PLSの「少数成分で $y$ を説明する」性質がはっきりします。

各成分の累積説明率(Xとy)

青が $X$ の累積説明率、オレンジが $y$ の累積説明率です。注目すべきは、2成分で $y$ の約98.7%を説明している点です。$X$ 側の説明率もすぐに飽和しており、3成分目以降を足しても $y$ の説明はほとんど増えません。これが先ほど交差検証で成分数2が選ばれた理由を、別の角度から裏づけています。

どの変数が予測に効いているかは、VIP(Variable Importance in Projection)スコアで評価できます。VIPは、各変数が潜在変数を通じて $y$ の説明にどれだけ寄与したかを表す指標です。

def vip(W, T, Q):
    p, A = W.shape
    ssy = np.array([Q[a]**2 * (T[:, a] @ T[:, a]) for a in range(A)])
    vips = np.zeros(p)
    for j in range(p):
        weight = np.array([(W[j, a] / np.linalg.norm(W[:, a]))**2 for a in range(A)])
        vips[j] = np.sqrt(p * np.sum(ssy * weight) / np.sum(ssy))
    return vips

beta, W, P, Q, T = pls1_nipals(Xc, yc, best)
v = vip(W, T, Q)
print("VIP>1の変数数:", int((v >= 1).sum()))

VIPスコア:予測に効く変数の重要度

この図は各変数のVIPスコアで、赤いバーが「VIP ≥ 1」の変数、灰色が1未満の変数です。VIP ≥ 1 を重要変数の目安とするのが慣例で、これを使えば「品質に効く波長/センサーはどれか」を絞り込めます。VIPの総和の二乗平均が1になるよう正規化されているため、1という閾値が「平均以上に効いている」という自然な基準になります。変数選択やプロセスの解釈に直結する、実務で重宝する指標です。

実務でPLSを使うときのポイント

最後に、PLSを現場で使う際の勘所をまとめておきます。

  • 必ず標準化を検討する: 変数のスケールが揃っていないと、単位の大きい変数が共分散を支配します。スペクトルのように同一単位ならそのままでもよいですが、温度・圧力・流量など異種のセンサーを混ぜるときは、各変数を平均0・分散1に標準化してから適用します。
  • スコアプロットで外れ値を見る: $t_1$-$t_2$ 平面で他から大きく離れたサンプルは、測定ミスや異常運転の可能性があります。Hotelling の $T^2$ 統計量で管理限界(楕円)を引き、限界を超えた点を外れ値として検出する運用が一般的です。
  • VIPと回帰係数で変数を解釈する: VIP ≥ 1 の変数に絞ると、モデルを軽くしつつ「どの波長・どのセンサーが効くか」を物理的に解釈できます。プロセスの理解や、次の実験計画にも直結します。
  • 多出力なら PLS2: 目的変数が複数あるときは、$\bm{y}$ を行列に拡張した PLS2 を使います。NIPALSの中で $y$ 側にも反復(スコア $\bm{u}$ の更新)が入りますが、「$X$ と $Y$ の共分散を最大化する方向を順に取る」という考え方は同じです。

これらを押さえれば、PLSは「とりあえず動く」だけでなく「解釈できて運用できる」回帰手法になります。

まとめ

PLS回帰(部分的最小二乗法)を、理論からスクラッチ実装まで通して見てきました。要点は次の通りです。

  • 多重共線性や $p > n$ の状況では、OLSの $(X^\top X)^{-1}$ が不安定になり回帰係数が暴れる。PLSは少数の潜在変数に圧縮することでこれを回避する。
  • PLSとPCAの決定的な違いは圧縮の基準にある。PCAは $X$ の分散最大、PLSは $y$ との共分散最大の方向を選ぶ。
  • 共分散最大化をラグランジュ法で解くと、第1の重みは $\bm{w}_1 \propto X^\top \bm{y}$ という単純な形になり、スコア・ローディング・デフレーションを繰り返す NIPALS アルゴリズムが導かれる。
  • 回帰係数は $\bm{\beta}_{\text{PLS}} = W(P^\top W)^{-1}Q$ で組み立てられ、スクラッチ実装はsklearnと丸め誤差レベルで一致する。
  • 成分数は交差検証で選ぶ。今回のデータでは2成分で $y$ の98.7%を説明し、$R^2 \approx 0.987$ を達成した。VIP ≥ 1 で重要変数を絞り込める。

PLSは、高次元・共線性・少サンプルという「現実のデータの三重苦」に強く、ケモメトリクスやプロセスのソフトセンサーで広く使われています。冒頭で触れた粉体プロセスのゼロショット回帰のように、転移学習やドメイン適応の枠組みの中でも、安定した予測器・特徴抽出器としてPLSが選ばれています。

次のステップとして、以下の記事もあわせて読むと理解が立体的になります。