確率・統計

(24) 主成分回帰 ( PCR ) と部分最小二乗法 ( PLS )

最小二乗法を原理とする重回帰モデルは、標本数が推定したい係数 ( 独立変数の種類 ) に対して十分に大きいことを前提としています。しかし、場合によっては十分な標本が得られなかったり、波形データなど、変数の種類が非常に多い場合があり、しかも独立変数どうしで相関があるような場合、通常の重回帰モデルでは処理ができなかったり、処理できたとしても正しい結果が得られないような場合があります。これは、独立変数の種類を少なくして相関を減らすことで回避することができるため、今回はそのための手法である「主成分回帰 ( Principal Component Regression ; PCR )」と「部分最小二乗法 ( Partial Least Squares ; PLS )」を紹介したいと思います。

(注) 数式などの記法について (ドキュメントの中で使用している数式の表現方法に関する注意点です)

1) 一般逆行列 ( Generalized Inverse )

以前、連立方程式の解法についていくつかのアルゴリズムを紹介しました。この中で、連立方程式を解くことができない場合として、解を求めることができない「不能」と解が定まらない「不定」について説明をしました。まずは、この内容をもう一度整理しておきます。

連立方程式が少なくとも一つ解を持つ場合を「無矛盾 ( Consistent )」といいます。"普通に" 解が得られる場合の他に、解が「不定」の場合も無矛盾となります。解を一つも持たなければ「矛盾 (Inconsistent)」といいます。よって「不能」ということは「矛盾している」ということになります。例として、

3x + 2y = 6
6x + 4y = 8

は解を持たないため「矛盾」となります。また、

2x + 4y = 10
x + 2y = 5

は、( x, y ) = ( 1, 2 ), ( 3, 1 ) など無数にあるため「不定」になりますが「無矛盾」です。

3x + 2y = 12
6x + 5y = 27

は唯一の解 ( x, y ) = ( 2, 3 ) を持つのでこれも「無矛盾」となります。

連立方程式が「無矛盾」となるのはどのような場合でしょうか。矛盾な方程式の例を以下のように書きなおしてみます。

x|3|+y|2|=|6|
|6||4||8|

この式が成り立つためには、ベクトル ( 6, 8 )T が ( 3, 6 )T と ( 2, 4 )T の線形結合で表すことが可能でなければなりません。それが可能な時、x, y は線形和の係数を意味します。しかし、この例では x, y をどのようにしても両辺を等しくすることができません。一般的に、係数行列 A の連立方程式 Ax = b が無矛盾であるためには、bA の列ベクトルの線形結合で表せることが必要十分条件となります。

また連立方程式が「無矛盾」なとき、解が一意に決まるためには、A の列ベクトルが全て線形独立でなければなりません (*1-1)。このとき、A は逆行列 A-1 を持ち、連立方程式 Ax = b の解は

x = A-1b

によって求められます。

式の数に対して未知数の数が多ければ、未知数の決め方は複数考えることができるので必ず「不定」になります。逆に未知数の数が少ない時、通常は「不能」となりますが、式に適当な数を乗除することで同じ式になるものが混在していれば、解が一意に決まったり、逆に「不定」となる場合もあります。

係数行列 A が逆行列を持たず解が一意に決まらなかったり、矛盾しているために解が得られないような場合も「意味のある解」を得たい場合があります。「最小二乗法 ( Least Squares )」はその代表的な例であり、左辺の式によって得られる値と右辺の解との差を全ての式について二乗して和を計算した時、その値が最小になるような未知数を解とするのが最小二乗法の考え方でした。また、不定であれば解は無数にあるので、その中から「代表」となるような解を決める方法が考えられます。

逆行列を持つ行列は「正則行列 (Regular Matrix)」と呼ばれます。正則ではない正方行列である「特異行列 (Singular Matrix)」や、もっと一般に正方ではない行列に対しても逆行列の概念を導入するため、m 行 n 列の行列 A に対して次のような定義の n 行 m 列の行列 A- を考えます。

AA-A = A

もし A が正則行列なら、逆行列 A-1 は上式を満たすので、A- は逆行列の一般化と考えることができます。これを「一般逆行列 (Generalized Inverse )」または「擬似逆行列 (Pseudo Inverse)」といいます。連立方程式 Ax = b の両辺に AA- を左側から掛けると

AA-Ax = AA-b

となり、左辺は Ax と等しいので、A-b は連立方程式の解と考えることができます。

全ての行列は必ず一般逆行列を持ちます。また、無矛盾な連立方程式で解が無数に存在する場合があることからも明らかなように、一般逆行列は一つだけとは限りません (補足 1)。例えば、

|2,4|
|1,2|

の一般逆行列を

|a,c|
|b,d|

としたとき、2a + 4b + c + 2d = 1 を満たす任意の ( a, b, c, d ) を持つ行列は全て対象になるので、例えば

|0,1||1,-1|
|0,0|,|1,-2|

などが一般逆行列となります。


先述の通り、正則行列を除いて一般逆行列は無尽蔵に作成することができますが、この中でも有用なものが存在します。まず、

(A-A)T = A-A

を満たす ( すなわち A-A が対称行列となる ) 一般逆行列 A-A の「最小ノルム形一般逆行列 (Minimum Norm Generalized Inverse)」といいます。これも一般逆行列の一つなので、

Ax = AA-b

が成り立ちますが、この式から得られる解 x = A-b のノルム ||x|| が最小となるという特徴を持つためこの名が付けられています (補足 2)。先ほど示した、解が不定な連立方程式

2x + 4y = 10
x + 2y = 5

は、x = 5 - 2y が成り立つので、x2 + y2

x2 + y2=( 5 - 2y )2 + y2
=5( y - 2 )2 + 5

より ( x, y ) = ( 1, 2 ) のとき最小値をとります。

A- =|a,c|
|b,d|

としたとき、

|a,c||10|=|1|
|b,d||5||2|

より

10a + 5c = 1
10b + 5d = 2

を満たす ( a, b, c, d ) であれば何でもよく、例えば

A- =|0,1/5|
|1/10,1/5|

は上式を満たし、

A-A =|0,1/5||2,4|=|1/5,2/5|
|1/10,1/5||1,2||2/54/5|

なので確かに A-A は対称行列となっています。


A の一般逆行列 A-

(AA-)T = AA-

を満たす ( すなわち AA- が対称行列となる ) とき、A-A の「最小二乗形一般逆行列 (Least Squares Generalized Inverse)」といいます。最小二乗法の正規方程式 XTXa = XTy の解を Gy としたとき、

XTXGy = XTy

より ( y が任意であれば ) XTXG = XT が成り立ちます (補足 3)。両辺に右側から X を掛けて

XTXGX = XTX

より XGX = X が成り立つので (補足 3) GX の一般逆行列であり、XTXG = XT の両辺を転置した

(XG)TX = X

の両辺に右側から G を掛けて

(XG)T(XG) = XG

となります。任意の行列とその転置行列の積は対称行列なので、XG は対称行列となり、G は最小二乗形一般逆行列であることになります。


「最小ノルム形一般逆行列」と「最小二乗形一般逆行列」の条件を満たし、さらに

A-AA- = A- (反射形)

の条件を満たす一般逆行列を「ムーア-ペンローズ形逆行列 ( Moore-Penrose Inverse )」といい A+ で表します。一般逆行列が複数あり得るのに対してムーア-ペンローズ形は一意に決まり (補足 4)、A = LR とし、LTART = (LTL)(RRT) が逆行列を持つとき、

A+ = RT(RRT)-1(LTL)-1LT

とすれば、

AA+A = LRRT(RRT)-1(LTL)-1LTLR = LR = A

A+AA+ = RT(RRT)-1(LTL)-1LTLRRT(RRT)-1(LTL)-1LT = RT(RRT)-1(LTL)-1LT = A+

となるので、反射形の一般逆行列となります。また、

AA+ = LRRT(RRT)-1(LTL)-1LT = L(LTL)-1LT

より

(AA+)T = L[ (LTL)-1 ]TLT

であり、LTL は対称行列でその逆行列も対称であることから [ (LTL)-1 ]T = (LTL)-1 なので、

(AA+)T = AA+

が成り立ちます。さらに

A+A = RT(RRT)-1(LTL)-1LTLR = RT(RRT)-1R

なので同様に

(A+A)T = A+A

となり、A+ は「最小ノルム形一般逆行列」「最小二乗形一般逆行列」の条件も満たすことになります。


最小二乗法によって得られる線形重回帰モデルの正規方程式は以下の式となるのでした。

XTXa = XTy

もし、XTX が逆行列を持つならば、(XTX)-1XTy が求める最小二乗解となり、(XTX)-1XT

X[ (XTX)-1XT ]X = X(XTX)-1(XTX) = X

より X の一般逆行列であり、

[ (XTX)-1XT ]X[ (XTX)-1XT ] = (XTX)-1(XTX)(XTX)-1XT = (XTX)-1XT

より反射形であり、

[ X(XTX)-1XT ]T = X[ (XTX)-1 ]TXT = X(XTX)-1XT

より最小二乗形であり、

[ (XTX)-1XTX ]T = ET = E

より最小ノルム形なので、ムーア-ペンローズ形逆行列の条件を満たします。しかし、XTX が逆行列を持たなければ、正規方程式の解は一意にはならず、XTX の一般逆行列を G としたとき、正規方程式の両辺に左側から XTXG を掛けて

XTXGXTXa = XTXGXTy より

XTXa = XTXGXTy

なので、GXTy がその解の一つとなります。このとき、GXTX の一般逆行列であることから

(XTX)G(XTX) = XTX

が成り立ち、XT(XGXTX) = XTX とすることで

XGXTX = X

が成り立つことがわかるので (補足 3) GXTX の一般逆行列となります。

G は複数存在しますが、その中で XTX の最小ノルム形一般逆行列 H を選択したとします。このとき、

(HXTX)T = HXTX

が成り立つので HXTX の最小ノルム形一般逆行列であり、

XTXHXTX = XTX

より

XTX(HXT) = XT

が成り立つので (補足 3)、

(HXT)TXTX = X

より両辺に右側から HXT を掛けると

(HXT)TXTX(HXT) = X(HXT) より

(XHXT)T(XHXT) = XHXT

となり、XHXT は対称行列であることから HXTX の最小二乗形一般逆行列です。最後に

XTXHXTX = XTXXHXTX = XHXTXHXTX = HXTXHXTXHXT = HXT

なので HXT は反射形であり、HXT はムーア-ペンローズ形逆行列であることになります。


線形重回帰モデルでは、各独立変数ベクトルを行とした行列 X ( これを「デザイン行列 (Design Matrix)」といいます ) は通常 "縦長" の形となります。つまり、独立変数の種類 ( 例えば身長や体重などの連続値や性別などのカテゴリなど ) と比較してサンプルの数 ( 例えば被験者数など ) が十分に多いことが一般的であり、この場合は XTX の行列数が独立変数の種類と等しく、たいていは逆行列を持つので最小二乗解も一意に決まります。しかし、サンプル数が極端に少なかったり、独立変数の要素数が非常に多い場合はこの前提が成り立ちません。その場合、解は一意に決めることができませんが、一つの決め方として XTX の最小ノルム形一般逆行列 H を選択して HXTy を解とすれば、HXT はムーア-ペンローズ形逆行列なので一意に解が決まり、その解は最小二乗解であると同時に最小ノルム解にもなります。特に、HXTX のムーア-ペンローズ形逆行列であったとき、L = XT, R = X とすれば、

H = XT(XXT)-1(XXT)-1X

と表されるので、

HXT = XT(XXT)-1(XXT)-1XXT = XT(XXT)-1

という結果が得られます。これは XXT が逆行列を持つ場合に相当し、比較的簡単に解を得ることができることを意味します。


最後に、対称行列の「固有値分解 (Eigendecomposition)」や「特異値分解 (Singular Value Decomposition)」とムーア-ペンローズ形逆行列の関係について紹介します (*1-2)。まず、二つの直交行列 P, Q に挟まれた任意の行列 PAQT のムーア-ペンローズ形逆行列を考えます。このとき、

(PAQT)+ = QA+PT

とすると、

PAQTQA+PTPAQT = PAA+AQT = PAQT (一般逆行列)

QA+PTPAQTQA+PT = QA+AA+PT = QA+PT (反射形)

(PAQTQA+PT)T = P(AA+)TPT = PAA+PT = PAQTQA+PT (最小二乗形)

(QA+PTPAQT)T = Q(A+A)TQT = QA+AQT = QA+PTPAQT (最小ノルム形)

となり、四つの条件を全て満たしていることがわかります。特に、A が ( 対角成分にゼロを含むことも許容した ) 対角行列 D であったとき、D の i 行 i 列目の要素を λi として、D+ の対角成分 λ+i

λ+i=1 / λi( λi ≠ 0 )
=0( λi = 0 )

とすれば ( DD+ の積は対角行列なので、対角成分のみを計算して )、

DD+D = { δ, δ, ... δ }D = { λ1, λ2, ... } = D (一般逆行列)

D+DD+ = { δ, δ, ... δ }D+ = { λ+1, λ+2, ... } = D+ (反射形)

であり ( 但し δ は λi ≠ 0 のとき 1、λi = 0 のとき 0 を表すとします )、DD+, D+D は明らかに対称行列なのでムーア-ペンローズ形逆行列となります。

任意の非特異な対称行列 A は、固有値からなる対角行列 D と固有ベクトルを列とする直交行列 Q を使って以下の式で表すことができます。

A = QDQT

これを「固有値分解 (Eigendecomposition)」というのでした。さらに、A が任意の行列になっても、AATATA のゼロでない固有値が全て等しく なることから、ゼロでない固有値を対角成分とした対角行列を DAAT の固有ベクトルを列ベクトルとする行列を UATA の固有ベクトルを列ベクトルとする行列を V としたとき、

A = U|D,0|VT
|0,0|

で表されます。A が m 行 n 列の行列ならば、U はサイズ m、V はサイズ n の正方行列となります。これを「特異値分解 (Singular Value Decomposition)」というのでした。従って、今までの議論から

A+ = V|D+,0|UT
|0,0|

という結果が得られ、任意の行列は特異値分解の結果から簡単にムーア-ペンローズ形逆行列が得られることを意味しています。


*1-1) あるベクトル群が線形独立なとき、任意のベクトル ( 但しベクトル群に対して線形従属でなければなりません ) はそのベクトル群を使って一意の線形結合で表すことができます。詳細は「数値演算法 (8) 連立方程式を解く -2-」の「5) 固有値と固有ベクトル」で紹介しています。

*1-2) 「固有値 (Eigenvalue)」と「固有ベクトル (Eigenvector)」及びそれらを使った「行列の対角化」については「数値演算法 (8) 連立方程式を解く -2-」の中の「5) 固有値と固有ベクトル」で紹介しています。また、対称行列の「固有値分解 (Eigendecomposition)」は「固有値問題 (1) 対称行列の固有値」の中の「3) 直交行列 (Orthogonal Matrix)」で、「特異値分解 (Singular Value Decomposition)」は「固有値問題 (3) 画像の固有空間」の中の「3) 特異値分解 (Singular Value Decomposition)」でそれぞれ説明しています。


2) 主成分回帰 ( Principal Component Regression ; PCR )

線形重回帰モデルでは通常、標本数が回帰係数よりも多いので XTX は逆行列を持ち、最小二乗解として (XTX)-1XTy が得られます。この時、前節で説明した連立方程式の解の状態は「不能」です。ところが、標本の内容によっては逆に回帰係数の方が標本数より多いような場合もあり、この時に得られる解は最小ノルム解になるので本来得ようとしていたデータとはたいていかけ離れたものになります。また、各独立変数間で高い相関があったりするような場合を「多重共線性 (Multicollinearity)」といい、XTX の逆行列を計算しようとしても ( 係数の数よりランクが小さくなって ) 失敗したり、計算できたとしても実際とはかけ離れた結果になることもあります。
「計量化学 (Chemometrics)」と呼ばれる、実験データをコンピュータを利用して解析する化学の一分野では、大量の測定値を使って解析をする反面、その標本数は少なく、測定値間の相関が複雑に絡まって誤った解釈をしてしまう場合が多々あります。このようなときに利用できる手法の一つに「主成分回帰 ( Principal Component Regression ; PCR )」があります。

名前の通り、独立変数から共分散行列を求め、その固有値分解から主成分を抽出する「主成分分析 ( Principal Component Analysis ; PCA )」を利用した回帰分析で、独立変数の各要素間が無相関になるよう「主軸変換」され、その固有値は変換後の主軸で新たに表現される値 ( これを主成分と言います ) の分散値を意味します。固有値の大きな主軸のみを利用することで精度の高い近似値が得られるので次元を少なくすることも可能になり、先に述べたような多重共線性の問題を回避することができるようになります。

実際のデータで主成分回帰を試してみます。下記データは、統計計算用ツール R のパッケージ "pls" に付属しているサンプル・データの一つで、5 種類の物理化学的品質パラメータと官能検査から得られた 6 種類の特性値を 16 種類のオリーブオイルから得た結果です。最初の G1 〜 G5 がギリシャ産、次の I1 〜 I5 がイタリア産、最後の S1 〜 S6 がスペイン産です。

表 2-1. オリーブオイルの特性値
オリーブオイル物理化学的品質パラメータ官能特性値
酸性過酸化物K232K270DK黄色味緑色味茶色味光沢透明度甘み
G10.7312.71.9000.1390.00321.473.410.179.775.250.3
G20.1912.31.6780.116-0.00423.466.39.877.868.751.7
G30.2610.31.6290.116-0.00532.753.58.782.383.245.4
G40.6713.71.7010.168-0.00230.258.312.281.177.147.8
G50.5211.21.5390.119-0.00151.832.58.072.465.346.5
I10.2618.72.1170.1420.00140.742.920.167.763.552.2
I20.2415.31.8910.116053.830.411.577.877.345.2
I30.3018.51.9080.1250.00126.466.514.278.774.651.8
I40.3515.61.8240.104065.712.110.381.679.648.3
I50.1919.42.2220.158-0.00345.031.928.475.772.952.8
S10.1510.51.5220.116-0.00470.912.210.887.788.144.5
S20.168.141.5270.106-0.00273.59.78.389.989.742.3
S30.2712.51.5550.093-0.00268.112.010.878.475.146.4
S40.1611.01.5730.094-0.00367.613.911.984.683.848.5
S50.2410.81.3310.085-0.00371.410.610.888.188.546.7
S60.3011.41.4150.093-0.00471.410.011.489.588.547.2

まずは、このデータに対して重回帰分析を行なってみます。独立変数は、5 つの物理化学的品質パラメータに産地 ( ギリシャ産 = 0, イタリア産 = 1, スペイン産 = 2 ) を追加して、「黄色味」から「甘み」まで個々に従属変数として処理します。処理結果を ANOVA 表で以下に示します。

表 2-2. ANOVA 表
従属変数変動要因平方和自由度不偏分散分散比 ( F 値 )p 値
黄色味予測値(回帰による)4551.76758.66.050.0087
残差(回帰との)1127.99125.3
観測値(全体)5679.615
緑色味予測値(回帰による)6194.961032.54.470.023
残差(回帰との)2079.79231.1
観測値(全体)8274.615
茶色味予測値(回帰による)354.5659.113.290.00051
残差(回帰との)40.094.45
観測値(全体)394.615
光沢予測値(回帰による)386.4664.43.080.063
残差(回帰との)187.9920.9
観測値(全体)574.415
透明度予測値(回帰による)680.56113.42.880.075
残差(回帰との)354.7939.4
観測値(全体)1035.215
甘み予測値(回帰による)89.9615.02.640.092
残差(回帰との)51.195.67
観測値(全体)141.015

p 値 < 0.01 は「黄色味」と「茶色味」だけで、全体として当てはめはあまりよくなさそうです。重相関係数と決定係数は次のようになります。

表 2-3. 重相関係数と決定係数
従属変数重相関係数決定係数自由度調整済み決定係数
黄色味0.8950.8010.669
緑色味0.8650.7490.581
茶色味0.9480.8990.831
光沢0.8200.6730.455
透明度0.8110.6570.429
甘み0.7990.6380.396

「自由度調整済み決定係数 (Adjusted R2)」とは、通常の決定係数が独立変数の種類を多くとるほど 1 に近づくので (「過剰適合 (Overfitting)」にも関係する現象で、要するに統計的な ( コントロールできない ) 誤差分がゼロに近づくためにそのようになります )、調整のために以下のような計算をした値です。

R~2 = 1 - ( 1 - R2 )[ ( n - 1 ) / ( n - p - 1 ) ]

p = 0 のときは R~2 = R2 となり、p → n - 1 で R~2 → -∞ となります。調整の結果、茶色味以外はかなり低い値となっています。

図 2-1. 独立変数間の相関
各独立変数どうしの相関図

上図は、独立変数間の相関を表したグラフです。いくつかの変数について、互いに相関関係にあるものが見つかります。このことから、多重共線性によって回帰モデルが正しく生成されなかったことが考えられます。そこで、独立変数を主成分分析により主成分へ変換してみます。

表 2-4. 主成分分析結果
固有値寄与率固有ベクトル
10.60.938( 0.00295189, 0.996187, 0.0650423, 0.00397745, 0.000325868, -0.0579344 )
0.6650.0590( 0.134083, -0.0616059, 0.0571816, 0.0144666, 0.000420742, -0.987293 )
0.01841.64E-03( -0.932987, -0.0257005, 0.342861, -0.0125361, -0.00688786, -0.105433 )
0.01039.13E-04( 0.331543, -0.0561684, 0.932844, 0.0768262, 0.00855904, 0.103689 )
0.0001591.41E-05( 0.0385293, -0.000922421, 0.0681348, -0.994623, 0.0675893, -0.00530878 )
1.10E-069.74E-08( -0.0119536, 6.75257e-05, -0.0102973, 0.066631, 0.997653, -0.000822524 )

ほとんど第一主成分で近似ができることがこの結果からわかります。第一主成分の大部分は「過酸化物」で構成され、次の第二主成分は「産地」がほとんどを占めます。データをこの二つの主成分の固有ベクトルで変換し、再度重回帰モデルで検証してみます。

表 2-5. ANOVA 表 (主成分を利用した重回帰分析)
従属変数変動要因平方和自由度不偏分散分散比 ( F 値 )p 値
黄色味予測値(回帰による)4448.022224.023.484.84E-05
残差(回帰との)1231.61394.7
観測値(全体)5679.615
緑色味予測値(回帰による)5909.922955.016.22.91E-04
残差(回帰との)2364.713181.9
観測値(全体)8274.615
茶色味予測値(回帰による)257.02128.512.11.06E-03
残差(回帰との)137.61310.6
観測値(全体)394.615
光沢予測値(回帰による)359.92179.910.91.66E-03
残差(回帰との)214.51316.5
観測値(全体)574.415
透明度予測値(回帰による)631.42315.710.22.20E-03
残差(回帰との)403.81331.1
観測値(全体)1035.215
甘み予測値(回帰による)86.8243.410.41.99E-03
残差(回帰との)54.2134.17
観測値(全体)141.015

重相関係数と決定係数は次のようになります。

表 2-6. 重相関係数と決定係数 (主成分を利用した重回帰分析)
従属変数重相関係数決定係数自由度調整済み決定係数
黄色味0.8850.7830.750
緑色味0.8450.7140.670
茶色味0.8070.6510.598
光沢0.7920.6270.569
透明度0.7810.6100.550
甘み0.7850.6160.557

独立変数の要素が減った分、F 値や p 値は改善されています。自由度調整済み決定係数も多少よくなっていますが、大幅に改善されたかというとそういうわけでもありません。

わざわざ主成分分析を使って独立変数の直交化を行ったわけですが、結果としては、「過酸化物」と「産地」の二つだけを選んで重回帰分析を行ったのと変わりはありません。他の独立変数が従属変数に関与しているかどうかは、結局わからないわけです。このように、主成分回帰は独立変数間の相関だけを考慮するため従属変数との相関は無視して変換され、結果として、従属変数と相関の強い状態で本当に独立変数が変換されたかはわかりません。最悪、全く無相関な主成分が選択され、正しい結果が得られない可能性もあります。


3) PLS 回帰 ( Partial Least Squares Regression ; PLS Regression )

主成分回帰では、従属変数が主成分の決定になにも関与していないのが問題となるのでした。寄与率が大きな主成分を見つけても、それが従属変数と強い相関を持っているとは限りません。そこで、独立変数ベクトル X の転置と、従属変数からなる行列 Y ( 今までの重回帰モデルと違い、従属変数はベクトルではなく行列として扱います。もちろん、その特別な場合としてベクトルでも適用は可能です。なお、重回帰モデルでも従属変数を行列に拡張することは簡単にできます ) の積 XTY についての特異値分解をまずは行います。但し、前もって、XY の列ベクトルが、平均ゼロ、標準偏差 1 となるように正規化しておきます。

XTY = UrDrVrT

X は N 行 p 列 ( すなわち p 個の独立変数の要素を持った N 個の標本からなる行列 )、Y は N 行 q 列 とし、Ur は p 行 r 列、Dr はサイズ r の対角行列 ( 対角成分は全てゼロでないとします )、Vr は q 行 r 列 とします。このとき、r は XTY の階数 ( Rank ) を意味します。

Dr の対角成分は XTY の固有値です。i 番目の固有値を λi として λ1 ≥ λ2 ≥ ... λr の順に並べられてあるとします。また、対応する固有ベクトル ( Ur, Vr の列ベクトル ) をそれぞれ ui, vi とします。このとき、uiTXTYvi = λi が最大になるのは i = 1 のときであり、

( Xu1 )TYv1 = λ1

より Xu1X の各独立変数ベクトルを主軸 u1 で直交変換したもの、Yv1 は同じく Y の各従属変数ベクトルを主軸 v1 で直交変換したものです。これにより、両者の変換後の値 ( 主成分分析における主成分 ) の内積、すなわち分散値が最大になるように変換されたことになります。そこで、主成分を

t1 = Xu1 / ||Xu1||

w1 = Yv1 / ||Yv1||

として、t1w1 の間に回帰式

w1 = b1t1

を仮定し、b1 を推定します。t1Tt1 = 1 なので、

t1Tw1 = t1Tb1t1 = b1

であり、w1 はこの b1 を使って

w^1 = b1t1

と近似できることになります。この操作はちょうど、X, Y それぞれの主成分どうしで回帰係数を推定したことに相当します。次に、

p1 = XTt1

q1 = YTw1

を求め、

X = X - t1p1T

Y = Y - w1q1T

として、再度特異値分解のところから反復処理します。その結果、X, Y がどちらも 0 に十分近い状態になったとすれば、最初の処理の X, YX0, Y0 とし、以下、処理を重ねるごとに添字を一つずつ更新すると、

X0 = X1 + t1p1T = X2 + t2p2T + t1p1T = ... ≅ Σi( tipiT ) = TPT

Y0 ≅ Σi( wiqiT ) = WQT

となります。ここで T, P, W, Q はそれぞれ ti, pi, wi, qi を列ベクトルとする行列になります。このとき、bi を i 番目の対角成分とする対角行列 B を使って WTB と表すことができるので、この値を W~ とすれば

Y~W~QT = TBQT

と定義することができて、X = TPT より XT = PTT なので、

XTY~ = PTTTBQT

という結果が得られます。T は「潜在ベクトル (Latent Vector)」と呼ばれていますが、その実体は主軸変換された独立変数の成分 ( 一般に「スコア行列 ( Score Matrix )」と呼ばれます ) です。YTBQT の積で近似され、T は主成分なので、前述の通り Y~ = TBQT は主成分を使った回帰モデルであると考えることができます。また、XTY は、PTTTBQT の二つの積に分解され、その分解の中で T が生成された形になっています。

XTPT

より、両辺を転置して

PTTXT

となるので、両辺に左側から PT を掛けて

PTPTTPTXT

という形になりますが、これは P を係数行列とし、TT を未知数、XT を右辺の値とした最小二乗法の正規方程式と同じ形となっています。但し、未知数と右辺の値はベクトルではなく行列です。これは、複数の連立方程式が係数行列は共通で横に並んだ様子を思い浮かべれば理解しやすいかと思います。この解を T~ = GXT としたとき ( 最小二乗法なので T は推定値 T~ です )、G は最小二乗形一般逆行列となるのでした。よって、これを Y の式に代入すると

YXGTBQTXBPLS

と表現できて、XY の間の回帰モデルとすることができます。特に、P の行が標本数なのに対して列数は抽出した主成分の数であり、通常は主成分の数が少なくなるようにするのが目的となるので、PTP は逆行列を持つと考えてたいていは問題ありません。したがって、

G = ( PTP )-1PT

とすれば、

PGP = P( PTP )-1PTP = P( P の一般逆行列 )
GPG = ( PTP )-1PTP( PTP )-1PT = ( PTP )-1PT = G( 反射形 )
( PG )T = [ P( PTP )-1PT ]T = P( PTP )-1PT = PG( 最小二乗形 )
( GP )T = [ ( PTP )-1PTP ]T = E( 最小ノルム形 )

であり、GP のムーア-ペンローズ形逆行列になります。


特異値分解は、係数を一つ計算する度に行われるので、毎回全ての特異値を導き出すのは効率的に問題があります。そのため、PLS 回帰では「べき乗法 (Power Iteration)」に似た方法が一般的に採用されています。このアルゴリズムは「Nonlinear Iterative Partial Least Squares ( NIPALS )」と呼ばれています。

べき乗法は、固有値の中で絶対値が最大のものを求める手法です。ある正方行列 A の固有値を λi とします。ここで、固有値は絶対値の大きい順に並べ替えられているとします ( よって λ1 が絶対値最大の固有値となります )。各固有値に対応する固有ベクトルを ui としたとき、

Aui = λiui

となります。ui は基底であり、任意のベクトル x はその線形結合

x = Σi( ciui )

で表されるので、

Anx = Σi( ciAnui ) = Σi( ciλinui )

より c1 ≠ 0 ならば

Anx = c1λ1nΣi( ( ci / c1 )( λi / λ1 )nui )

となり、λi / λ1 < 1 ( i > 1 ) より Anx は c1λ1nu1 へ収束していきます。x の初期値を x0 として、

x(n) = Anx0
( x(n) = Ax(n-1) )

とすると、

x(n-1) = c1λ1n-1Σi( ( ci / c1 )( λi / λ1 )n-1ui )

であり、n が十分大きければ c1λ1n-1u1 へ収束します。但し、|| Ax || は A の要素によって変化していくので、計算の度にノルムで割って正規化する必要があります。

|| x(n) ||2 ≅ || c1λ1nu1 ||2 = c12λ12n

( x(n-1), x(n) ) ≅ ( c1λ1n-1u1, c1λ1nu1 ) = c12λ12n-1

より

λ1 = || x(n) ||2 / ( x(n-1), x(n) )

で最初の固有値を求めることができます。


べき情報を使った固有値・固有ベクトル算出用のプログラムを以下に示します。

/*
  Normalize : 配列 [ s, e ) に対して正規化を行う

  中心化は行わず、ノルムで割るのみである。
*/
template< class In >
void Normalize( In s, In e )
{
  typedef typename std::iterator_traits< In >::value_type value_type;

  // ノルムの計算
  value_type norm = 0;
  for ( In i = s ; i != e ; ++i )
    norm += std::pow( *i, 2.0 );
  norm = std::sqrt( norm );

  if ( norm != 0 )
    for ( ; s != e ; ++s )
      *s /= norm;
}

/*
  PowerIter : べき乗法による一番目の固有値・固有ベクトルの抽出

  Test 型の引数 test は前回の解からの収束を判定するための関数オブジェクトで、初期化するための init、判定対象の値を収集
  するための operator()、収束判定を行うための isConvergent をメンバ関数として持つことを前提とする。

  固有ベクトル x は初期値としても利用されるため、要素数が行列のサイズと等しいことを前提としている。
  また、処理終了時には第一固有値(絶対値最大の固有値)に対する固有ベクトルが返されるが、このときユークリッド・ノルムの値は 1 に正規化されている。

  a : 対象の行列への参照
  x : 第一固有ベクトルへのポインタ(渡される要素は初期値として利用される)
  test : 収束判定用関数オブジェクト
  maxCnt : 反復処理の最大回数
  戻り値 : 第一固有値
*/
template< class T, template< class T > class MATRIX, class Test >
  T PowerIter( const MATRIX< T >& a, std::vector< T >* x, Test test, unsigned int maxCnt )
{
  // 更新後の固有ベクトルを x で初期化して正規化
  std::vector< T > newX( *x );
  if ( ! Normalize( newX.begin(), newX.end() ) )
    return( std::numeric_limits< T >::quiet_NaN() );

  unsigned int cnt = 0; // 処理回数
  for ( ; cnt < maxCnt ; ++cnt ) {
    *x = newX;
    // 新たな x を Ax で更新
    MatrixLib::mult( a, x->begin(), x->end(), newX.begin(), newX.end() );
    if ( ! MathLib::Normalize( newX.begin(), newX.end() ) )
      return( std::numeric_limits< T >::quiet_NaN() );
    // 収束判定
    test.init();
    for ( typename std::vector< T >::size_type i = 0 ; i < x->size() ; ++i )
      test( (*x)[i], newX[i] );
    if ( test.isConvergent() )
      break;
  }

  if ( cnt >= maxCnt )
    throw ExceptionExcessLimit( maxCnt );

  MatrixLib::mult( a, x->begin(), x->end(), newX.begin(), newX.end() );
  return( std::inner_product( newX.begin(), newX.end(), newX.begin(), T() ) /
          std::inner_product( x->begin(), x->end(), newX.begin(), T() ) );
}

テンプレート引数の MATRIX は行列の型を表し、この型を持つ引数は a です。MATRIX 自体もテンプレート・クラスであり、テンプレート引数として T を持つので、"template< class T > class MATRIX" というように、テンプレート引数の中でさらにテンプレートを使っています。MatrixLib::mult は行列とベクトルの積を計算するための関数で、第一引数に行列、第二・第三引数はベクトルの開始と末尾の次の位置をそれぞれ表します。また、最後の二つの引数は計算結果を返すベクトルの先頭と末尾の次の位置になります。具体的な実装はここでは示していませんが、行列の各行に対してベクトルとの内積を計算するだけの簡単な処理で実現できます ( ベクトルどうしの内積の計算には、STL ( Standard Template Library ) にある inner_product 関数が利用できます。この関数は、べき乗法の実装の中でも使用しています )。
収束したかどうかは、ベクトルの各要素が変化しないことで判定するのが通常ですが、この判定はいくつかの方法が考えられるので、これも具体的な実装は示さず抽象化しています。テンプレート引数 Test がその判定用関数オブジェクトの型を表し、三番めの引数 test がその型を持ちます。test オブジェクトは init 関数で初期化を行い、operator() で前の値と現在の値を引数として各要素をチェック ( 例えば差分の最大値で判定するなら各要素の差分の大きさを比較して最大値を取得 ) し、isConvergent で ( 例えばあるしきい値以下になっているかなどによって ) 収束判定を行います。収束しない場合を想定して、チェック回数は maxCnt までとし、それを超えた場合は例外を投げる仕様となっています。

処理の内容は前に説明した通りであり、ベクトル x に行列 a を掛けて正規化することを収束するまで繰り返し、最後に固有値を求めて戻り値として返します。また、固有ベクトルは引数 x にて返されます。


べき乗法を応用して、以下のような処理を考えます。なお、式の中で "∝" は左辺のベクトルをノルムが 1 になるよう正規化することを意味します。

  1. tXu
  2. vYTt
  3. wYv
  4. uXTw

最初、u は適当な値で初期化しておきます。この処理を t が収束するまで繰り返し、収束したら b = tTw で回帰係数を推定し、p = XTt, q = YTw を求めて X = X - tpT, Y = Y - wqT としてから再度反復処理を繰り返します。

この反復処理によって、左辺の各々のベクトルは以下のような式で表すことができます。

  1. tXuXXTYYTt
  2. vYTtYTXuYTXXTYv
  3. wYvYYTXuYYTXXTw
  4. uXTwXTYvXTYYTtXTYYTXu

従って、ある定数 λ について XTYYTXu = λu が成り立つことから uXTYYTX の固有ベクトルであり、同様に vYTXXTY の固有ベクトルです。これらはちょうど、先に示した特異値分解の UrVr に相当し、tw もそれぞれ明らかに先述のベクトル t, w と同種のものです。


NIPALS を使って PLS 回帰を行うためのサンプル・プログラムを以下に示します。

/**
   PLS 回帰 ( NIPALS アルゴリズム )
**/
class PLS_Regression_NIPALS
{
  Matrix< double > x_; // 独立変数 X
  Matrix< double > y_; // 従属変数 Y

  std::vector< double > b_; // 主成分 t, w での回帰係数
  Matrix< double > pT_;     // p = Xt・t を列ベクトルとする行列の転置
  Matrix< double > qT_;     // Q = Yt・w を列ベクトルとする行列の転置

  // 反復処理により u, t, v, w を求める関数
  void iterProc( Matrix< double >* x, Matrix< double >* y,
                 size_t latentVecIdx, double e, unsigned int maxCnt );

 public:

  /// 独立変数 X と従属変数 Y を指定して構築
  ///
  /// x : 独立変数 X
  /// y : 従属変数 Y
  template< class T, class U >
    PLS_Regression_NIPALS( const Matrix< T >& x, const Matrix< U >& y );

  /// PLS回帰を行い、回帰係数を a に返す
  ///
  /// a : 回帰係数を得るための行列へのポインタ
  /// latentVecs : 回帰係数(計算する潜在ベクトル)の個数
  /// e : 反復処理でベクトルが収束したかを判定するためのしきい値
  /// maxCnt : 反復処理の最大処理回数(反復処理は各回帰係数の算出で繰り返されるため、それぞれの処理での最大回数を意味する)
  void operator()( Matrix< double >* a, size_t latentVecs, double e, unsigned int maxCnt );
};

/*
  Centralize : データ [ s, e ) を中心化・正規化する

  テンプレート引数の In はコンテナの iterator の型であることが前提となる。
  標準偏差がゼロである場合は正規化できないため何も処理せず false を返す。
*/
template< class In >
  bool Centralize( In s, In e )
{
  typedef typename std::iterator_traits< In >::value_type value_type;

  value_type sz = std::distance( s, e );
  if ( sz <= 0 ) return( false );

  value_type mu = std::accumulate( s, e, value_type() ) / sz; // 平均値
  value_type sigma = 0; // 標準偏差
  for ( In i = s ; i != e ; ++i )
    sigma += std::pow( *i - mu, 2.0 );
  sigma = std::sqrt( sigma );

  if ( sigma == 0 )
    return( false );

  for ( ; s != e ; ++s )
    *s = ( *s - mu ) / sigma;

  return( true );
}

/*
  PLS_Regression_NIPALS コンストラクタ : 独立変数 X と従属変数 y を指定して構築
*/
template< class T, class U >
  PLS_Regression_NIPALS::PLS_Regression_NIPALS( const Matrix< T >& x, const Matrix< U >& y )
{
  assert( &x != 0 && &y != 0 );

  if ( x.rows() != y.rows() )
    throw ExceptionNotEqualLength< typename Matrix< T >::size_type >( x.rows(), y.rows() );
  if ( x.rows() == 0 )
    throw ExceptionNotPositiveLength< typename Matrix< T >::size_type >( x.rows() );

  x_.assign( x.begin(), x.end(), x.rows(), true );
  y_.assign( y.begin(), y.end(), y.rows(), true );

  for ( Matrix< double >::size_type c = 0 ; c < x_.cols() ; ++c ) {
    Matrix< double >::iterator col = x_.column( c );
    Centralize( col, col.end() );
  }
  for ( Matrix< double >::size_type c = 0 ; c < y_.cols() ; ++c ) {
    Matrix< double >::iterator col = y_.column( c );
    Centralize( col, col.end() );
  }
}

/*
  MultMatByVec : 行列 m と ベクトル [ is, ie ) の積を計算し、[ os, oe ) に返す

  結果は必ず Normalize される。
*/
template< class In, class Out >
void MultMatByVec( const Matrix< double >& m, In is, In ie, Out os, Out oe )
{
  MatrixLib::mult( m, is, ie, os, oe );
  Normalize( os, oe );
}

/*
  MultMatByVec : 行列 m の転置と ベクトル [ is, ie ) の積を計算し、[ os, oe ) に返す

  needToNorm が true なら結果は Normalize される。
*/
template< class In, class Out >
void MultTransByVec( const Matrix< double >& m, In is, In ie, Out os, Out oe, bool needToNorm )
{
  Out o = os;
  for ( Matrix< double >::size_type c = 0 ; c < m.cols() ; ++c ) {
    Matrix< double >::const_iterator col = m.column( c );
    *o++ = std::inner_product( is, ie, col, double() );
  }
  if ( needToNorm )
    Normalize( os, oe );
}

/*
  SubMat : 列ベクトル [ rs, re ) と行ベクトル [ cs, ce ) の積を計算し(結果は行列になる)、m から減算する
*/
template< class Row, class Column >
void SubMat( Row rs, Row re, Column cs, Column ce, Matrix< double >* m )
{
  Matrix< double >::iterator i = m->begin();
  for ( ; cs != ce ; ++cs )
    for ( Row r = rs ; r != re ; ++r )
      *i++ -= *r * *cs;
}

/*
  MultMatByTrans : src とその転置行列の積を計算し、dest に返す
*/
void MultMatByTrans( const Matrix< double >& src, SymmetricMatrix< double >* dest )
{
  for ( Matrix< double >::size_type r = 0 ; r < src.rows() ; ++r ) {
    for ( Matrix< double >::size_type c = r ; c < src.rows() ; ++c ) {
      Matrix< double >::const_iterator row = src.row( r );
      Matrix< double >::const_iterator column = src.row( c );
      (*dest)[r][c] = std::inner_product( row, row.end(), column, double() );
    }
  }
}

/*
  PLS_Regression_NIPALS::operator() : PLS 回帰メインルーチン
*/
void PLS_Regression_NIPALS::operator()( Matrix< double >* a, size_t latentVecs, double e, unsigned int maxCnt )
{
  assert( a != 0 );

  // 潜在ベクトルの個数は X のサイズより小さいことを前提とする
  if ( latentVecs > x_.cols() )
    throw ExceptionTooGreatNumber< size_t >( latentVecs, x_.cols() );
  if ( latentVecs > x_.rows() )
    throw ExceptionTooGreatNumber< size_t >( latentVecs, x_.rows() );

  pT_.assign( latentVecs, x_.cols() );
  qT_.assign( latentVecs, y_.cols() );

  // x_, y_ は更新されるためコピーして使う
  Matrix< double > x( x_ );
  Matrix< double > y( y_ );
  for ( size_t cnt = 0 ; cnt < latentVecs ; ++cnt )
    iterProc( &x, &y, cnt, e, maxCnt );

  SymmetricMatrix< double > pTp( pT_.rows() ); // Pt・P
  MultMatByTrans( pT_, &pTp );

  SquareMatrix< double > pTpM;                 // ( Pt・P )^-1
  InverseMatrix( pTp, &pTpM );

  Matrix< double > gT;                         // Gt ( G = ( Pt・P )^-1・Pt )
  MatrixLib::mult( pTpM, pT_, &gT );
  gT.transpose();
  for ( vector< double >::size_type c = 0 ; c < gT.cols() ; ++c )
    for ( vector< double >::size_type r = 0 ; r < gT.rows() ; ++r )
      gT[r][c] *= b_[c];

  MatrixLib::mult( gT, qT_, a );               // A = Gt・Qt
}

/*
  PLS_Regression_NIPALS::iterProc : 反復処理により u, t, v, w を求める関数

  t = X・u
  v = Yt・t
  w = Y・v
  u = Xt・w

  を繰り返す
*/
void PLS_Regression_NIPALS::iterProc( Matrix< double >* x, Matrix< double >* y,
                                      size_t latentVecIdx, double e, unsigned int maxCnt )
{
  typedef vector< double > Vec;

  Vec u( x->cols(), 1.0 / std::sqrt( static_cast< double >( x->cols() ) ) ); // u ベクトル
  vector< Vec > t( 2, Vec( x->rows() ) ); // t ベクトル(収束判定のため前の値を保持できるよう二つ分確保)
  Vec v( y->cols() ); // v ベクトル
  Vec w( y->rows() ); // w ベクトル

  Vec::size_type tIdx = 0; // t ベクトルの現在の計算対象インデックス (0/1)
  unsigned int cnt; // 反復処理回数
  for ( cnt = 0 ; cnt < maxCnt ; ++cnt ) {
    Vec& ct = t[tIdx]; // t ベクトルの現在の計算対象
    MultMatByVec( *x, u.begin(), u.end(), ct.begin(), ct.end() );         // t = X・u
    MultTransByVec( *y, ct.begin(), ct.end(), v.begin(), v.end(), true ); // v = Yt・t
    MultMatByVec( *y, v.begin(), v.end(), w.begin(), w.end() );           // w = Y・v
    MultTransByVec( *x, w.begin(), w.end(), u.begin(), u.end(), true );   // u = Xt・w

    // 収束チェック
    ConvergenceTest_ByMax< double > test( e );
    for ( Vec::size_type i = 0 ; i < t[tIdx ^ 1].size() ; ++i )
      test( t[tIdx ^ 1][i], ct[i] );
    if ( test.isConvergent() ) break;
    tIdx ^= 1; // t ベクトルの現在の計算対象を反転
  }
  if ( cnt >= maxCnt )
    throw ExceptionExcessLimit( maxCnt );

  Vec& ct = t[tIdx]; // t ベクトルの現在の計算対象

  // 回帰係数の登録
  b_.push_back( std::inner_product( ct.begin(), ct.end(), w.begin(), double() ) );
  // w は回帰係数を元に予測値にする
  for ( Vec::size_type i = 0 ; i < w.size() ; ++i )
    w[i] = b_.back() * ct[i];
  Matrix< double >::iterator pTRow = pT_.row( latentVecIdx );
  MultTransByVec( *x, ct.begin(), ct.end(), pTRow, pTRow.end(), false ); // p = Xt・t
  Matrix< double >::iterator qTRow = qT_.row( latentVecIdx );
  MultTransByVec( *y, w.begin(), w.end(), qTRow, qTRow.end(), false );   // q = Yt・w

  SubMat( ct.begin(), ct.end(), pTRow, pTRow.end(), x ); // X = X - t・pt
  SubMat( w.begin(), w.end(), qTRow, qTRow.end(), y );   // Y = Y - w・qt
}

コンストラクタでは、受け取った独立変数と従属変数を中心化・正規化してコピーするだけの処理を行っています。実際の処理は operator() を呼び出して行いますが、このとき回帰係数を得るための行列へのポインタと回帰係数の個数、反復処理で使用するしきい値と最大処理回数をそれぞれ渡します。回帰係数の個数は明示する必要があることに注意してください。また、その個数は独立変数の行列数よりも小さいことを前提とします。反復処理を行う iterProc が主要な処理を行うところになります。4 つのベクトル t, v, w, u を収束するまで反復処理し、tw の内積から回帰係数を求めます。最後に行列 x, y からそれぞれ tpTwqT を減算し ( この処理があるので行列 x, y はコピーして使います )、処理を完了します。必要な係数をすべて求めたら、G = ( PTP )-1PT を計算し、QT との積から X に対応した回帰係数を計算します。

べき乗法のサンプル・プログラムではテンプレート引数としていた Matrix クラスはここでも行列を提供するために利用し、内部で行・列方向の反復子が使えるようになっています。begin, end 関数は通常の配列と同じような扱いをした反復子で、行方向に要素をたどって行末に達したら次の列の先頭行に移るような進み方をします。また、row は指定した行番号の行の反復子を、column は指定した列番号の列の反復子をそれぞれ返します。反復子の末尾は、反復子自身が end 関数を持っているため、通常のコンテナ・クラスのようにコンテナの end 関数を呼び出すのではないことに注意してください。なお、正方行列用に SquareMatrix、対称行列用に SymmetricMatrix もそれぞれ用意されています。べき乗法で登場した MatrixLib::mult は多重定義 ( オーバーロード ) されていて、二つの行列の積を計算するための関数も登場します。また、transpose は対象の行列を転置するメンバ関数です。

InverseMatrix は逆行列を計算するための関数で、第一引数の行列の逆行列を第二引数の行列にコピーします。具体的な実装方法は、「数値演算法 (7) 連立方程式を解く -1-」にて紹介しています。ConvergenceTest_ByMax は収束を判定するための関数オブジェクトで、前の値との差分と値自身との比率を求め、その最大値がしきい値以内なら処理が完了するようになっています。これは、べき乗法で登場したテンプレートによる抽象クラス Test の具体的な実装の一つになります。最後に、いくつかの例外用クラスが定義されていますが、これもその名前や判定内容からどんなものか判別できると思います。


サンプル・プログラムを使って主成分回帰のときに使ったデータを処理してみたところ、回帰係数は下表のような結果になりました。但し、潜在ベクトルは 6 個分 ( すなわち全て ) 算出しています。

表 3-1. 回帰係数 BPLS の値 ( 潜在ベクトル数 6 )
黄色味緑色味茶色味光沢透明度甘み
酸性-0.0580.056-0.0420.0620.0370.009
過酸化物-0.0810.0490.291-0.237-0.2150.321
K232-0.0540.0100.312-0.118-0.0610.185
K270-0.1250.1260.206-0.039-0.0390.019
DK-0.1110.141-0.134-0.147-0.1560.008
産地0.370-0.3780.2510.2600.306-0.095

上表において、係数が 0.2 以上のところを色付けしてあります。主成分回帰のときと同様に、どの従属変数も過酸化物と産地の影響が大きいことがこの結果からわかります。

表 3-2. 予測値の算出結果 ( 潜在ベクトル数 6 )
黄色味緑色味茶色味光沢透明度甘み
G1-1.0031.047-0.336-0.595-0.6930.271
G2-0.2770.271-0.297-0.137-0.184-0.011
G3-0.1890.197-0.4950.1270.049-0.246
G4-0.8650.8660.082-0.301-0.4100.221
G5-0.5010.569-0.817-0.079-0.224-0.196
I1-0.5070.4211.056-0.864-0.7400.887
I2-0.1730.1460.292-0.400-0.3440.351
I3-0.3770.3290.605-0.704-0.6360.695
I4-0.1380.1180.097-0.330-0.3030.325
I5-0.4060.2401.663-0.746-0.5671.033
S10.711-0.689-0.0430.6860.709-0.542
S20.718-0.646-0.4640.7400.739-0.772
S30.636-0.614-0.1800.4690.488-0.325
S40.752-0.732-0.1930.5970.630-0.467
S50.833-0.768-0.6250.7730.737-0.677
S60.787-0.757-0.3440.7650.748-0.546
分散0.3770.3520.3910.3330.3130.297

上表は、独立変数 XBPLS の積から従属変数 Y の予測値を計算した結果です。スペイン産は黄色味が強く、光沢や透明度も高いこと、イタリア産は甘みが強いことなど、産地ごとの特性がはっきりとこの結果からわかるようになります。

表 3-3. 残渣の算出結果 ( 潜在ベクトル数 6 )
黄色味緑色味茶色味光沢透明度甘み
G1-0.5610.707-0.1140.4100.3210.513
G2-1.1811.171-0.213-0.366-0.9961.266
G3-0.7760.682-0.2360.1210.573-0.621
G4-0.2320.224-0.1080.3490.274-0.280
G50.550-0.614-0.056-1.325-1.379-0.301
I1-0.033-0.0090.508-1.325-1.0870.536
I20.328-0.283-0.459-0.1030.233-1.286
I3-0.9221.122-0.2290.3520.1890.594
I40.925-1.060-0.5060.4610.478-0.215
I50.094-0.3111.573-0.107-0.0910.593
S10.352-0.248-0.2660.4640.523-0.629
S20.483-0.401-0.3470.7770.691-1.140
S30.278-0.332-0.128-0.872-0.873-0.206
S40.135-0.1310.1070.0350.0670.644
S50.256-0.2400.3170.4430.5440.247
S60.302-0.2770.1560.6850.5330.285
分散0.3190.3630.2330.4100.4380.463

残渣 ( 実測値 - 予測値 ) をみると、予測値と同程度のバラツキ ( 分散値 ) を持っていることがわかります。PLS 回帰は、残渣をできるだけ小さくする最小二乗法の考え方とは異なるため、分散比で判断することはあまり意味がないようです。実際、実測値は正規化されていたので分散値は 1 であり、通常の回帰分析での決定係数は予測値の分散と等しくなります。しかし、予測値と残渣の分散値の和は 1 にはならず、すべてそれより小さくなっています。

下表は、潜在ベクトルを 2 個までとして、回帰係数 BPLS と、従属変数の予測値及び残渣を求めた結果です。

表 3-4. 回帰係数 BPLS の値 ( 潜在ベクトル数 2 )
黄色味緑色味茶色味光沢透明度甘み
酸性-0.1920.209-0.190-0.048-0.088-0.029
過酸化物-0.0570.0310.293-0.167-0.1290.206
K232-0.0930.0690.260-0.177-0.1460.202
K270-0.1560.1470.089-0.145-0.1430.126
DK-0.1200.1150.056-0.106-0.1070.089
産地0.196-0.2040.1070.0860.115-0.023
 
表 3-5. 予測値の算出結果 ( 潜在ベクトル数 2 )
黄色味緑色味茶色味光沢透明度甘み
G1-1.1921.209-0.240-0.704-0.8230.394
G20.054-0.037-0.1880.1190.096-0.140
G30.085-0.037-0.5250.2870.218-0.361
G4-0.9841.009-0.315-0.530-0.6460.254
G5-0.4320.494-0.7140.019-0.114-0.243
I1-0.5250.4201.148-0.858-0.7320.944
I2-0.1230.0790.492-0.299-0.2370.358
I3-0.3710.2980.794-0.598-0.5120.656
I4-0.1450.1200.277-0.220-0.1910.236
I5-0.3860.2621.362-0.857-0.6901.012
S10.664-0.642-0.2160.5450.562-0.434
S20.649-0.609-0.4220.6250.611-0.554
S30.526-0.508-0.1700.4310.444-0.343
S40.718-0.698-0.1860.5680.593-0.441
S50.786-0.730-0.5900.7910.763-0.719
S60.677-0.628-0.5060.6800.657-0.618
分散0.3700.3460.3750.3200.2990.292
 
表 3-6. 残渣の算出結果 ( 潜在ベクトル数 2 )
黄色味緑色味茶色味光沢透明度甘み
G1-0.3730.545-0.2090.5180.4510.389
G2-1.5121.478-0.322-0.621-1.2761.395
G3-1.0500.916-0.206-0.0390.404-0.506
G4-0.1130.0810.2880.5780.510-0.313
G50.481-0.539-0.158-1.423-1.489-0.254
I1-0.015-0.0070.416-1.330-1.0950.479
I20.279-0.216-0.659-0.2040.126-1.293
I3-0.9281.153-0.4170.2460.0650.633
I40.932-1.061-0.6860.3510.365-0.127
I50.074-0.3321.8740.0030.0320.614
S10.399-0.295-0.0930.6050.670-0.737
S20.552-0.438-0.3900.8920.819-1.358
S30.388-0.438-0.138-0.834-0.829-0.187
S40.170-0.1640.0990.0640.1040.617
S50.303-0.2780.2820.4250.5180.290
S60.413-0.4050.3190.7700.6250.357
分散0.4060.4360.3400.4780.5190.514

潜在ベクトルを減らしても、予測値を見ると産地ごとの特性ははっきりと読み取ることができます。

表 3-7. 産地ごとの潜在ベクトル数別予測値平均
産地潜在ベクトル数黄色味緑色味茶色味光沢透明度甘み
Greece1-0.2640.2460.183-0.259-0.2520.232
2-0.4940.527-0.396-0.162-0.254-0.019
4-0.5670.590-0.371-0.198-0.2940.012
6-0.5670.590-0.373-0.197-0.2920.008
Italy1-0.4970.4640.344-0.488-0.4740.437
2-0.3100.2360.815-0.566-0.4720.641
4-0.3200.2510.741-0.606-0.5140.651
6-0.3200.2510.742-0.609-0.5180.658
Spain10.634-0.592-0.4390.6220.605-0.558
20.670-0.636-0.3480.6070.605-0.518
40.739-0.701-0.3080.6700.674-0.553
60.740-0.701-0.3080.6720.675-0.555
 
図 3-1. 産地ごとの潜在ベクトル数別予測値平均グラフ ( 緑:Greece 黄:Italy 赤:Spain )
産地ごとの潜在ベクトル数別予測値平均グラフ(NIPALS)

潜在ベクトル数に対する産地ごとの予測値平均を見ると、二つほどあれば十分であることがこの結果から読み取れます。


NIPALS の場合、主成分 tiwi の間に回帰式 wi = biti が成り立つと仮定して、

pi = Xti

qi = Ywi

を求めていましたが、wi は使わずに

pi = XTti

qi = YTti

を求め、

X = X - tipiT

Y = Y - tiqiT

として反復処理をする方法もあります。YX ではなくスコア行列の T による線形回帰で表せたとしたとき、その係数を B とすれば

TB = Y^

となります ( Y^Y の推定値を意味します )。両辺に左側から TT を掛けて

TTTB = TTY^

なので、T の列数が行数より少ない ( すなわち、独立変数の要素数より少ない主成分で X が表せる ) とすれば、TTT は非特異で逆行列が存在すると仮定して、

B = (TTT)-1TTY^

B を表すことができます。また、X = TPT より

XU(PTU)-1 = TPTU(PTU)-1 = T

なので、

Y^ = TB = T(TTT)-1TTY = XU(PTU)-1(TTT)-1TTY

より

BPLSU(PTU)-1(TTT)-1TTY = U(PTU)-1(TTT)-1TTTQT = U(PTU)-1QT

となります。ここで、

R = U(PTU)-1

とすれば、

T = XR

BPLS = RQT

が成り立ちます。この場合、XTY

XTY = PTTTQT

となって、NIPALS と比較して係数行列 B が取り除かれたような形で表されます。この手法は「SIMPLS」と呼ばれています。


SIMPLS を使った PLS 回帰処理用のサンプル・プログラムを以下に示します。

/**
   PLS 回帰 ( SIMPLS アルゴリズム )
**/
class PLS_Regression_SIMPLS
{
  Matrix< double > x_; // 独立変数 X
  Matrix< double > y_; // 従属変数 Y

  Matrix< double > u_;  // S = Xt・Y の左特異ベクトルを列ベクトルとする行列
  Matrix< double > pT_; // p = X・t を列ベクトルとする行列の転置
  Matrix< double > qT_; // Q = Y・t を列ベクトルとする行列の転置

  // u, t, v, w を求める関数
  void calcVector( Matrix< double >* x, Matrix< double >* y,
                   size_t latentVecIdx, double e, unsigned int maxCnt );

 public:

  /// 独立変数 X と従属変数 Y を指定して構築
  ///
  /// x : 独立変数 X
  /// y : 従属変数 Y
  template< class T, class U >
    PLS_Regression_SIMPLS( const Matrix< T >& x, const Matrix< U >& y );

  /// PLS回帰を行い、回帰係数を a に返す
  ///
  /// a : 回帰係数を得るための配列へのポインタ
  /// latentVecs : 回帰係数(計算する潜在ベクトル)の個数
  /// e : 反復処理でベクトルが収束したかを判定するためのしきい値
  /// maxCnt : 反復処理の最大処理回数(反復処理は各回帰係数の算出で繰り返されるため、それぞれの処理での最大回数を意味する)
  void operator()( Matrix< double >* a, size_t latentVecs, double e, unsigned int maxCnt );
};

/*
  MultTransByMat : mat1 の転置行列と mat2 の積を計算し、dest に返す
*/
void MultTransByMat( const Matrix< double >& mat1, const Matrix< double >& mat2, Matrix< double >* dest )
{
  for ( Matrix< double >::size_type r = 0 ; r < mat1.cols() ; ++r ) {
    Matrix< double >::const_iterator row = mat1.column( r );
    for ( Matrix< double >::size_type c = 0 ; c < mat2.cols() ; ++c ) {
      Matrix< double >::const_iterator column = mat2.column( c );
      (*dest)[r][c] = std::inner_product( row, row.end(), column, double() );
    }
  }
}

/*
  PLS_Regression_SIMPLS::operator() : PLS 回帰メインルーチン
*/
void PLS_Regression_SIMPLS::operator()( Matrix< double >* a, size_t latentVecs, double e, unsigned int maxCnt )
{
  assert( a != 0 );

  // 潜在ベクトルの個数は X のサイズより小さいことを前提とする
  if ( latentVecs > x_.cols() )
    throw ExceptionTooGreatNumber< size_t >( latentVecs, x_.cols() );
  if ( latentVecs > x_.rows() )
    throw ExceptionTooGreatNumber< size_t >( latentVecs, x_.rows() );

  u_.assign( x_.cols(), latentVecs );
  pT_.assign( latentVecs, x_.cols() );
  qT_.assign( latentVecs, y_.cols() );

  // x_, y_ は更新されるためコピーして使う
  Matrix< double > x( x_ );
  Matrix< double > y( y_ );
  for ( size_t cnt = 0 ; cnt < latentVecs ; ++cnt )
    calcVector( &x, &y, cnt, e, maxCnt );

  // Pt・U
  SquareMatrix< double > pTu( pT_.rows(), u_.cols() );
  MatrixLib::mult( pT_, u_, &pTu );

  // ( Pt・U )^-1
  SquareMatrix< double > pTuM;
  MathLib::InverseMatrix( pTu, &pTuM );

  // U・( Pt・U )^-1
  Matrix< double > upTuM;
  MatrixLib::mult( u_, pTuM, &upTuM );

  // A = U・( Pt・U )^-1・Qt
  MatrixLib::mult( upTuM, qT_, a );
}

/*
  PLS_Regression_SIMPLS::calcVector : u, t, p, q を求める関数

  u は Xt・Y の第一左特異ベクトル
  t = X・u / ||X・u||
  p = X・t
  q = Y・t
*/
void PLS_Regression_SIMPLS::calcVector( Matrix< double >* x, Matrix< double >* y,
                                        size_t latentVecIdx, double e, unsigned int maxCnt )
{
  typedef vector< double > Vec;

  // S = Xt・Y
  Matrix< double > s( x->cols(), y->cols() );
  MultTransByMat( *x, *y, &s );

  // S・St = ( Xt・Y )・( Xt・Y )t
  SymmetricMatrix< double > ssT( s.rows() );
  MultMatByTrans( s, &ssT );

  // S = Xt・Y の第一左特異ベクトル ( S・St の第一固有ベクトル ) を u に求める
  Vec u( x->cols(), 1.0 / std::sqrt( static_cast< double >( x->cols() ) ) );
  ConvergenceTest_ByMax< double > test( e );
  EigenLib::PowerIter( ssT, &u, test, maxCnt );
  for ( typename Vec::size_type i = 0 ; i < u.size() ; ++i )
    u_[i][latentVecIdx] = u[i];

  // t = Xu
  Vec t( x->rows() );
  MultMatByVec( *x, u.begin(), u.end(), t.begin(), t.end() );

  // p = Xt・t
  Matrix< double >::iterator row = pT_.row( latentVecIdx );
  MultTransByVec( *x, t.begin(), t.end(), row, row.end(), false );
  SubMat( t.begin(), t.end(), row, row.end(), x ); // X = X - t・pt

  // q = Yt・t
  row = qT_.row( latentVecIdx );
  MultTransByVec( *y, t.begin(), t.end(), row, row.end(), false );
  SubMat( t.begin(), t.end(), row, row.end(), y );   // Y = Y - t・qt
}

基本的な構成は NIPALS の場合とよく似ています。各ベクトルを求める関数は calcVector で、これを潜在ベクトルの数分だけ処理することで行列 U, T, P, Q が得られます。これらの行列を使い、BPLS を引数 a に求めて処理が完了します。calcVector の中で特異ベクトルを求める処理が必要になりますが、これは前に紹介したべき乗法のサンプル・プログラムをそのまま利用しています。求めたいのは特異値分解

XTY = UDVT

の左特異ベクトルからなる行列 U なので、

XTY(XTY)T = UDVT(UDVT)T = UDVTVDUT = UD2UT

より XTY(XTY)T の固有ベクトルを求めれば目的を達成することができます。

なお、コンストラクタの内容は NIPALS と全く同じなので実装は省略しています。


SIMPLSを使って NIPALS と同じデータを処理した結果を以下に示します。潜在ベクトルは 6 個分 ( すなわち全て ) 算出しています。

表 3-8. 回帰係数 BPLS の値 ( 潜在ベクトル数 6 )
黄色味緑色味茶色味光沢透明度甘み
酸性0.243-0.3320.2480.3460.3720.229
過酸化物-0.1800.1400.393-0.503-0.5600.765
K2320.198-0.3860.7470.1470.3850.252
K270-0.2740.3660.199-0.034-0.093-0.274
DK-0.1870.349-0.560-0.330-0.380-0.261
産地0.824-0.8370.5510.6150.727-0.193

上表において、係数が 0.5 以上のところを色付けしてあります。NIPALS と比較して係数の絶対値は大きくなる傾向にありますが、ここでも過酸化物と産地の影響が大きいという結果が得られました。

表 3-9. 予測値の算出結果 ( 潜在ベクトル数 6 )
黄色味緑色味茶色味光沢透明度甘み
G1-0.9351.033-0.624-0.498-0.5400.058
G2-0.9840.921-0.531-0.561-0.6790.124
G3-0.7270.616-0.5650.014-0.084-0.186
G4-1.1541.1670.338-0.177-0.4010.261
G5-0.8630.989-1.368-0.270-0.532-0.236
I1-0.6250.5701.306-1.204-1.0351.044
I2-0.2540.2470.198-0.663-0.5710.408
I3-0.5260.5470.545-1.194-1.1791.035
I4-0.026-0.0370.082-0.509-0.4430.700
I5-0.5220.1772.789-0.804-0.5031.516
S10.924-0.8530.0431.0311.053-0.985
S21.020-0.819-0.8171.1311.181-1.645
S31.112-1.095-0.1550.7120.763-0.283
S41.128-1.121-0.1720.8850.984-0.658
S51.161-1.041-0.9090.9440.841-0.744
S61.273-1.300-0.1611.1641.146-0.408
分散0.8010.7490.8990.6730.6570.638
 
表 3-10. 残渣の算出結果 ( 潜在ベクトル数 6 )
黄色味緑色味茶色味光沢透明度甘み
G1-0.6290.7210.1740.3130.1670.726
G2-0.4740.5200.0210.059-0.5011.131
G3-0.2380.263-0.1660.2350.707-0.681
G40.056-0.077-0.3640.2250.265-0.320
G50.912-1.0330.495-1.134-1.071-0.261
I10.085-0.1570.258-0.984-0.7920.379
I20.409-0.384-0.3660.1600.460-1.343
I3-0.7730.903-0.1690.8410.7320.254
I40.813-0.904-0.4910.6410.618-0.590
I50.211-0.2480.447-0.049-0.1550.109
S10.139-0.085-0.3510.1190.178-0.186
S20.181-0.2280.0050.3860.249-0.267
S3-0.1970.149-0.154-1.115-1.148-0.248
S4-0.2400.2590.086-0.253-0.2870.834
S5-0.0720.0340.6010.2730.4400.314
S6-0.1840.266-0.0260.2860.1360.147
分散0.1990.2510.1010.3270.3430.362

従属変数 Y の予測値と、実測値との残渣を計算した結果です。ここでも NIPALS と同様の結果が得られました。

表 3-11. 産地ごとの潜在ベクトル数別予測値平均
産地潜在ベクトル数黄色味緑色味茶色味光沢透明度甘み
Greece1-0.3510.3280.244-0.345-0.3350.309
2-0.7240.776-0.611-0.224-0.363-0.047
4-0.9330.944-0.546-0.303-0.4560.022
6-0.9330.945-0.550-0.298-0.4470.004
Italy1-0.6740.6290.467-0.661-0.6430.593
2-0.3820.2781.137-0.756-0.6210.872
4-0.3880.2980.981-0.865-0.7290.914
6-0.3910.3010.984-0.875-0.7460.941
Spain10.854-0.797-0.5920.8380.815-0.752
20.922-0.879-0.4380.8170.820-0.688
41.101-1.035-0.3630.9730.988-0.780
61.103-1.038-0.3620.9780.995-0.787
 
図 3-2. 産地ごとの潜在ベクトル数別予測値平均グラフ ( 緑:Greece 黄:Italy 赤:Spain )
産地ごとの潜在ベクトル数別予測値平均グラフ(SIMPLS)

潜在ベクトル数に対する産地ごとの予測値平均も NIPALS とほぼ同等の結果であり、潜在ベクトルが二つほどあれば識別には十分な精度が得られる結果となりました。今回は、潜在ベクトルの数を変化させて最適値を調べてみましたが、本来であれば処理前に前もって決めておく必要があります。この方法としては、例えば標本を K 個に分割してそのうちの一つを検証用、残り全てを係数の計算用に利用する操作を、検証用の標本を K 個全てに対して切り替えて行う手法があります。これは一般に「交差検証 ( Cross-Validation )」として知られる手法です。


NIPALSSIMPLS に対して今回紹介したものとは異なる式を採用したバージョンがあり、さらに「カーネル法」を採用したものなど全く別のアルゴリズムなども多く存在します。XY を近似するやり方が複数あるだけでなく正規化を行う位置も様々なので、各アルゴリズムにおいて結果を直接比較することを困難とする要因となっています。比較的新しい手法であり、書籍としては参考になるものがなく論文などで情報を入手するしかないので、まだうまくまとめられていない部分もありますが、理解できた部分が増えてきたら都度更新をしていきたいと思います。


補足 1) 一般逆行列の存在証明

任意の m 行 n 列行列 A の階数(ランク)が r であるとき、A = LR となるような m 行 r 列の行列 L と r 行 n 列の行列 R が必ず存在します。m 行 m 列の単位行列 Em のランクは m なので、

Em = LR

を満たす m 行の行列 L と m 列の行列 R が存在し、LR の「左逆行列 (Left Inverse)」、RL の「右逆行列 (Right Inverse)」といいます。これらについては「確率・統計 (12) 二標本の解析 -2-」の「補足 2) べき等行列の階数」にて証明法を紹介していますので、そちらをご覧ください。

m 行 n 列の行列 A のランクが r で、m 行 r 列の行列 B と r 行 n 列の行列 C を使って A = BC と表されるとき、B の左逆行列が LC の右逆行列が R ならば、

BC(RL)BC = B(CR)(LB)C = BErErC = BC = A

なので、RLA の一般逆行列となります。これは、任意の行列に対して一般逆行列が存在することを意味します。

GA の一般逆行列のとき、Z を任意の ( 但し行列数が G と等しい ) 行列として

G* = G + Z - GAZAG

とすると、

AG*A=A( G + Z - GAZAG )A
=AGA + AZA - AGAZAGA
=A + AZA - AZA = A

となります。また、S, T を (しかるべき行列数の) 任意の行列として

G* = G + ( E - GA )T - S( E - AG )

とすると、

AG*A=A[ G + ( E - GA )T - S( E - AG ) ]A
=AGA + A( E - GA )TA - AS( E - AG )A
=AGA + AETA - AGATA - ASEA + ASAGA
=A + ATA - ATA - ASA + ASA = A

となります。このことから、一般逆行列が一つ決まれば、それからいくらでも異なる一般逆行列を作ることができます。但し、G が通常の逆行列であれば、どちらの式も G* = G なので異なる逆行列を作ることはできません。


補足 2) 最小ノルム形一般逆行列 (Minimum Norm Generalized Inverse)

(A-A)T = A-A

を満たす一般逆行列に対し、連立方程式 Ax = b の解 A-b が最小のノルムを持つことを証明するにはいくつかの段階を踏む必要があります。

まず、Ax = 0 の形の連立方程式を「同次線形系 (Homogeneous Linear System)」といいます。x* がその解のとき、Ax* = 0 なので

x* = x* - A-(Ax*) = ( E - A-A )x*

と表すことができます。ここで任意のベクトル y を使って

x* = ( E - A-A )y

としたとき、

Ax* = A( E - A-A )y = ( A - AA-A )y = 0

なので、任意のベクトル y について ( E - A-A )yAx = 0 になり、全ての解はこの形で表せることになります。

次に、右辺を b0 として Ax = b の形の連立方程式「非同次線形系 (Nonhomogeneous Linear System)」について、解の一つを x* とし、右辺を 0 にした Ax = 0 の解の一つを z* とすると、

A( x* + z* ) = Ax* + Az* = b

なので x* + z*Ax = b の解になります。特に、A の任意の一般逆行列 A- に対し、A-b は解の一つであり、( E - A-A )yAx = 0 の解の一つなので、

A-b + ( E - A-A )y

Ax = b の解の一つになり、全ての解がこの形で表せることになります。このノルムの二乗を計算すると、

|| A-b + ( E - A-A )y ||2 = ||A-b||2 + 2( A-b, ( E - A-A )y ) + || ( E - A-A )y ||2

より ( A-b, ( E - A-A )y ) を計算すると

( A-b, ( E - A-A )y )=( A-b )T( E - A-A )y
=( A-Ax )T( E - A-A )y
=xT( A-A )T( E - A-A )y

となります。ここで (A-A)T = A-A が成り立つとすると

( A-b, ( E - A-A )y )=xTA-A( E - A-A )y
=xT( A-A - A-AA-A )y
=xT( A-A - A-A )y = 0

なので、

|| A-b + ( E - A-A )y ||2 = ||A-b||2 + || ( E - A-A )y ||2 ≥ ||A-b||2

となり、|| ( E - A-A )y || = 0 となるような y を選べばノルムが最小となります。

補足 3) 「ATAB = ATAC ならば AB = AC」の証明

一般に、行列 A と二つのベクトル x, y の間で Ax = Ay のとき x = y が成り立つとは限りません。例として、

A = |1,1|
|1,1|
x = ( 0, 0 )T, y = ( 1, -1 )T

に対して xy ですが、Ax = Ay = 0 になります。Ax = Ay のとき x = y が成り立つためには、A が逆行列を持つ必要があります。これは、連立方程式の解が一意になるか、不定になるかについての議論と同じ内容です。ベクトルについて成り立たないので、行列 B, C について AB = AC のときも B = C が成り立つとは限りません。

特定の条件下では、上記の関係が成り立つ場合があります。もし、

ATAB = ATAC

が成り立てば、必ず AB = AC が成り立ちます。これを証明するために、行列の「トレース (Trace)」を利用します。トレースとは対角成分の和であり、正方行列に対してのみ定義されます。正方行列 A のトレースを tr( A ) で表します。

AAT のトレース tr( AAT ) は、A の i 番目の列ベクトルを ai としたとき

tr( AAT ) = Σi( ||ai||2 ) ≥ 0

となり、tr( AAT ) = 0 ならば ai = 0 なので A = 0 です。AAT = 0 のとき、そのトレースはゼロになるので、AAT = 0 ならば A = 0 ということになります。

ATAB = ATAC が成り立つとき、

( AB - AC )T( AB - AC )=( BTAT - CTAT )( AB - AC )
=BTATAB - BTATAC - CTATAB + CTATAC
=( BT - CT )ATAB - ( BT - CT )ATAC
=( BT - CT )( ATAB - ATAC ) = 0

なので、AB - AC = 0、すなわち AB = AC が成り立つことになります。

また、「ATAB = ATAC ならば AB = AC」両辺の転置をとって

BTATA = CTATA ならば BTAT = CTAT

なので、ATABTBCTC と置き直せば

BAAT = CAAT ならば BA = CA

も成り立つことになります。

なお、任意のベクトル yに対して Ay = By が成り立てば A = B となることの証明については、任意のベクトル yに対して成り立つなら i 番目のみが 1 で他はすべてゼロであるベクトルでも成り立ち、そのとき AyBy はそれぞれ i 番目の列ベクトルと等しくなることから証明できます。

補足 4) ムーア-ペンローズ形逆行列の一意性証明

かなり技巧的なやり方ですが、参考文献では以下のように証明されています。

A+ に対して異なるムーア-ペンローズ形逆行列 G があると仮定します。このとき、ムーア-ペンローズ形逆行列の性質を利用すると

A+=A+AA+ = A+(AA+)T = A+(A+)TAT = A+(A+)T(AGA)T = A+(A+)TATGTAT
=A+(AA+)T(AG)T = A+AA+AG = A+AG
=A+A(GAG) = (A+A)T(GA)TG = AT(A+)TATGTG = (AA+A)TGTG
=ATGTG = (GA)TG = GAG = G

よって G = A+ すなわち A+ は一意であることが証明されました。


<参考文献>
1. 「統計のための行列代数(上)(下)」 D.A.ハーヴィル 著 (シュプリンガー・ジャパン社)
2. Kuroda Lab 様 - システム生物学と多変量解析
3. The University of Texas at Dallas - Herve Abdi, Ph.D. - Partial Least Squares (PLS) Regression
4. Eigenvector Research Incorporated - Properties of Partial Least Squares (PLS) Regression, and differences between Algorithms
5. Wikipedia

[Go Back]前に戻る [Back to HOME]タイトルに戻る
inserted by FC2 system