データ分析・GA4

判別分析とは?線形判別・マハラノビス距離・正準判別分析の違いとExcel・Pythonでの手順

判別分析とは?線形判別・マハラノビス距離・正準判別分析の違いとExcel・Pythonでの手順

判別分析は、すでにグループ分けが済んだデータから「どの変数がグループを分けているか」を式にし、その式で新しいデータの所属先を当てる手法です。与信審査の完済と延滞、検査データの陽性と陰性のように、答えが分かっている過去データが手元にある場面で使います。この記事では、線形判別関数・マハラノビス距離・二次判別の使い分け、2群2変数の計算例のExcelでの再現、正準判別分析で取れる軸の本数、そしてscikit-learnでの実装と精度の確かめ方までを、実際に計算した数値で説明します。

まとめ:判別分析の要点と手法の選び方

  • 判別分析は教師あり手法です。グループのラベルが付いた学習データが無ければ使えません。ラベルが無い場合はクラスター分析の領域になります。
  • 線形判別関数は各群の分散共分散行列が等しいことを前提にします。前提が崩れる場合は二次判別分析(QDA)に切り替えます。
  • 判別得点は 判別係数 × 各変数の合計 + 定数項 という1本の式で、符号だけで所属先が決まります。係数はExcelのMINVERSEとMMULTで計算できます。
  • 正準判別分析で取れる軸の本数は min(群の数 − 1, 変数の数) です。3群4変数のアヤメのデータでは2本になり、第1軸だけで群間の分散の99.12%を説明します。
  • 精度は再代入の正答率ではなく交差検証で見ます。再代入は必ず甘く出ます。

判別分析が答える問いと、隣接手法との線引き

判別分析の出発点は、R. A. Fisherが1936年に「Annals of Eugenics」誌 7巻2号 179〜188ページで発表した論文「The Use of Multiple Measurements in Taxonomic Problems」です。アヤメの花のがく片と花弁の長さ・幅から品種を分ける問題を扱い、群内のばらつきに対して群間の差が最も大きくなる方向へデータを射影する、という発想を示しました。この「分ける方向を1本の線形結合として求める」考え方が、現在の線形判別分析(LDA)の骨格です。

判別分析が答えるのは2つの問いです。1つは予測で、新しい観測値がどの群に属するかを判定します。もう1つは解釈で、判別係数の大きさから、どの変数が群を分ける力を持つのかを読みます。予測精度だけが目的なら勾配ブースティングなどの方が当たりますが、判別係数という解釈可能な形で「何が効いているか」を説明できる点が、判別分析が実務で残っている理由です。

クラスター分析との線引き

混同されやすいのがクラスター分析ですが、両者は前提が正反対です。判別分析は「AとBに分かれていることが既知のデータ」から分ける式を学習します。クラスター分析は分類が未知の状態から、似ているもの同士を機械的に束ねます。手元のデータにグループのラベル列があるかどうかで、どちらを使うかは自動的に決まります。データ分類の仕組みはクラスター分析の基本概念とデータ分類の仕組みで整理しています。

ロジスティック回帰との使い分け

2群の判別であれば、ロジスティック回帰でも同じ問題を解けます。分かれ目は前提の置き方です。判別分析は各群の説明変数が多変量正規分布に従い、群間で分散共分散行列が等しいと仮定します。この仮定が成り立つときは、判別分析の方が少ないサンプルで安定した係数を得られます。逆に説明変数にカテゴリ変数(性別、契約種別など)が混ざる場合、正規分布の仮定は明らかに崩れるので、ロジスティック回帰を選びます。所属確率そのものを出したい場合もロジスティック回帰が向きます。回帰系の手法との関係は重回帰分析の式の立て方と結果の見方と合わせて見ると整理しやすくなります。

線形判別関数・マハラノビス距離・二次判別の3方式

線形判別関数による判別

2群の場合、群の平均ベクトルを m1、m2、併合分散共分散行列を Sp とすると、判別係数ベクトルは Sp の逆行列 × (m1 − m2) で求まります。定数項は2群の平均の中点でちょうど0になるように置きます。結果は変数の重み付き和という1本の式になり、値が正なら一方の群、負ならもう一方の群と判定します。境界は直線(変数が3つなら平面)になるため、群の広がりが直線で切れる形をしているときに素直に当たります。

マハラノビス距離による判別

もう1つの解き方が、各群の重心までの距離を測り、近い方の群へ割り当てる方法です。ここで使うマハラノビス距離は、単純なユークリッド距離を分散共分散行列の逆行列で補正したもので、(x − m) の転置 × Sp の逆行列 × (x − m) の平方根として定義されます。ばらつきの大きい変数の影響を割り引き、変数同士の相関も考慮するため、単位の異なる変数を同じ土俵で比較できます。

両群で分散共分散行列が等しいと仮定して同じ Sp を使う限り、マハラノビス距離による判別と線形判別関数による判別は同じ境界を与えます。距離の差を展開すると線形の式に帰着するためで、別々の手法として覚える必要はありません。ただし一致するのは、2群の事前確率を等しく置いた場合に限ります。群ごとに別々の分散共分散行列を使うとき、または学習データの群比率をそのまま事前確率に使うときは、境界がずれて判定が食い違います。scikit-learnは既定で群比率を事前確率に使うため、群サイズが偏ったデータでは距離最近の判定と一致しません(priors=[0.5, 0.5] を渡せば一致します)。

二次判別分析へ切り替える判断基準

群ごとに分散共分散行列を分けて推定すると、境界は直線ではなく二次曲線になります。これが二次判別分析(QDA)です。切り替えの判断には、群間で分散共分散行列が等しいかを見るBox の M 検定を使います。ただしこの検定は正規性からのずれに敏感で、サンプルが多いと実務上問題にならない差でも有意になります。検定結果だけで機械的に決めるのは避けてください。

実際、アヤメのデータで両者を同じ5分割交差検証にかけると、線形判別が平均0.98、二次判別が平均0.9667で、線形判別の方が上回りました(scikit-learn 1.6.1、乱数シード0)。パラメータ数が群の数だけ増える二次判別は、群あたりのサンプルが少ないと過学習側に振れます。等分散の仮定が崩れていることが図示できるほど明らかで、かつ各群に十分なサンプルがある場合にだけ二次判別を選ぶ、という順序が現実的です。

2群2変数の計算例とExcelでの再現手順

与信審査を模した12件のデータで、判別係数が出るまでの計算を追います。完済群6件と延滞群6件について、年収(百万円)と勤続年数(年)の2変数を使います。

群 年収 勤続年数 群 年収 勤続年数
完済 6.2 4 延滞 3.9 5
完済 5.4 9 延滞 4.5 2
完済 7.1 6 延滞 3.2 7
完済 5.1 11 延滞 4.1 3
完済 6.6 7 延滞 3.6 1
完済 5.9 5 延滞 5.2 6

群ごとの平均は完済が (6.05, 7.00)、延滞が (4.0833, 4.00) です。次に各群の不偏分散共分散行列を求め、自由度で重み付けして併合します。完済群と延滞群のサンプル数がどちらも6なので、重みは (6−1) と (6−1) の等分になり、併合分散共分散行列 Sp は次のようになります。

行列 年収・年収 年収・勤続 勤続・勤続
併合分散共分散行列 Sp 0.5243 −0.6300 6.2000
Sp の逆行列 2.1724 0.2207 0.1837

この逆行列に平均の差ベクトル (6.05 − 4.0833, 7.00 − 4.00) を掛けると判別係数が出ます。定数項まで含めた判別得点の式は次のとおりです。

判別得点 = 4.9347 × 年収 + 0.9853 × 勤続年数 − 30.4214

12件に当てはめると、完済群6件はすべて正の値、延滞群は5件が負の値になりました。誤ったのは延滞群の (5.2, 6) の1件だけで、判別得点は +1.151 と完済側に落ちています。的中率は12件中11件で91.7%です。年収の係数が勤続年数の5倍あることから、この12件では年収の方が完済と延滞を分けていると読めます。ただし変数の単位が違うため、係数の大小をそのまま重要度として比べられるのは、標準化したデータで係数を求め直したときだけです。

Excelで再現する場合、必要な関数は6つです。行列を返す関数の入力方法はバージョンで違います。Microsoft 365 では出力範囲の左上のセルに式を入れてEnterを押すだけで結果が広がります。それ以外のバージョンでは、出力範囲(Sp の逆行列なら2行2列)を先に選択し、左上のセルに式を入力してから Ctrl+Shift+Enter で確定します。

工程 Excelの関数
群ごとの平均 AVERAGE
群ごとの分散・共分散 VAR.S、COVARIANCE.S
併合分散共分散行列 自由度で重み付けして加算
逆行列 MINVERSE
行列の積・転置 MMULT、TRANSPOSE

共分散は COVARIANCE.P(分母が n)ではなく COVARIANCE.S(分母が n−1)を使ってください。今回のように両群のサンプル数が等しい場合、COVARIANCE.P にしても係数は一律1.2倍(4.9347が5.9216、0.9853が1.1824)になるだけで判定は1件も変わりません。ただし群ごとの件数が違うと自由度の重み付けが噛み合わず、係数どうしの比まで変わるため、判定が入れ替わります。

新規データの判定とマハラノビス距離での確認

年収5.0・勤続8年の申込者を判定すると、判別得点は +2.134 で完済側です。同じ点のマハラノビス距離は完済群の重心まで1.4544、延滞群の重心まで2.5266で、こちらも完済群に近いという結論になります。年収4.6・勤続3年の場合は判別得点が −4.766、マハラノビス距離は完済群まで3.1730、延滞群まで0.7318で、いずれも延滞側です。前述のとおり同じ Sp を使う限り両者の結論は一致するので、距離の値は「どちらの群にどれだけ近いか」という余裕の確認に使うのが実用的です。判別得点が0に近い申込者は、判定を機械に任せず人が見る、という運用の線引きに使えます。

正準判別分析で取れる軸の本数と寄与率

群が3つ以上になると、判別の境界を1本の軸では表せなくなります。そこで群間の分散を群内の分散で割った比が最大になる軸を順に取り出すのが正準判別分析(CDA)です。取り出せる軸の本数は min(群の数 − 1, 変数の数) に決まっており、これは統計ソフトの仕様ではなく行列の階数から来る上限です。scikit-learnで上限を超える本数を指定すると、n_components cannot be larger than min(n_features, n_classes - 1). というエラーで止まります。

3群4変数のアヤメのデータ(150件)で確かめると、取れる軸は2本でした。第1軸の寄与率が0.9912、第2軸が0.0088で、群の違いはほぼ第1軸だけで説明できます。群間の分離度を示す正準相関は第1軸が0.9848、第2軸が0.4712、群間の差の有意性に使うWilks のラムダは0.0234でした。これらは群内平方和行列の逆行列と群間平方和行列の積の固有値(32.192と0.285)から導いた値で、正準相関は固有値をラムダとして sqrt(ラムダ÷(1+ラムダ))、Wilks のラムダは 1÷(1+ラムダ) の積として求まります。値は0に近いほど群がよく分かれていることを意味します。

ここで軸を取り出す操作は次元圧縮そのものですが、主成分分析の定義・仕組み・分析手順とは目的が違います。主成分分析は群のラベルを使わず全体の分散が大きい方向を探すのに対し、正準判別分析は群のラベルを使い、群を分ける方向を探します。可視化の見た目は似ていても、前者は教師なし、後者は教師ありです。散布図で群がきれいに分かれて見える図が欲しいだけなら主成分分析では不足で、正準判別分析の第1軸・第2軸で描く必要があります。

統計ソフトで同じ計算をする場合、SPSSでは[分析]→[分類]→[判別分析]が対応します。[統計量]ダイアログでBox の M を追加すると、IBMの説明にある「A test for the equality of the group covariance matrices」、つまり群間で分散共分散行列が等しいかの検定まで同じ画面で確認できます。Excelの標準機能にはこの検定が無いため、前提の検証まで含めるならSPSSかPythonを選ぶことになります。

scikit-learnでの実装と精度の確かめ方

Pythonでは sklearn.discriminant_analysis.LinearDiscriminantAnalysis を使います。以下はscikit-learn 1.6.1で実行したコードと、その出力です。

import numpy as np
from sklearn.datasets import load_iris
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.model_selection import StratifiedKFold, cross_val_score
from sklearn.metrics import confusion_matrix

X, y = load_iris(return_X_y=True)
lda = LinearDiscriminantAnalysis().fit(X, y)

print("判別関数の本数:", lda.transform(X).shape[1])
print("各軸の寄与率:", np.round(lda.explained_variance_ratio_, 4))
print("再代入の正答率:", round(lda.score(X, y), 4))
print(confusion_matrix(y, lda.predict(X)))

cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=0)
scores = cross_val_score(LinearDiscriminantAnalysis(), X, y, cv=cv)
print("交差検証の正答率:", np.round(scores, 4), "平均", round(scores.mean(), 4))
判別関数の本数: 2
各軸の寄与率: [0.9912 0.0088]
再代入の正答率: 0.98
[[50  0  0]
 [ 0 48  2]
 [ 0  1 49]]
交差検証の正答率: [1.     1.     0.9667 0.9667 0.9667] 平均 0.98

混同行列は行が正解、列が予測です。1つ目の群は50件すべて正解、2つ目の群は2件が3つ目の群へ、3つ目の群は1件が2つ目の群へ流れており、誤分類は合計3件です。この3件が交差検証でも同程度に残り、再代入0.98と交差検証0.98がほぼ一致しました。両者が大きく開くときは過学習を疑います。

正答率を評価するときは、当てずっぽうの水準と比べてください。3群が均等なアヤメのデータなら、何も学習しなくても33.3%は当たります。0.98という値は、この33.3%と比べて初めて意味を持ちます。群の比率が9対1に偏ったデータでは、多数派に全部倒すだけで90%になるため、正答率ではなく群ごとの再現率や混同行列を見ないと判断を誤ります。solver は既定が svd で、変数が多く共線性が強い場面では lsqr か eigen に切り替えて shrinkage を併用します。shrinkage は svd では使えず、指定すると shrinkage not supported with 'svd' solver. で止まります。scikit-learn全体の使い方はScikit-learnの読み方・できること・使い方にまとめています。

covariance_ の分母と教科書の併合分散共分散行列のずれ・その補正

実装で見落とされやすいのが covariance_ 属性です。公式ドキュメントは「Weighted within-class covariance matrix」と説明し、各群の共分散を「the (potentially shrunk) biased estimator of covariance」で推定すると明記しています。biased、つまり分母が n の推定量です。手計算やExcelで使う併合分散共分散行列は分母が n−g(g は群の数)なので、両者は一致しません。

n, g = X.shape[0], len(np.unique(y))
pooled = sum((np.sum(y == k) - 1) * np.cov(X[y == k], rowvar=False, ddof=1)
             for k in range(g)) / (n - g)
lda = LinearDiscriminantAnalysis(store_covariance=True).fit(X, y)

print("比:", round(float(lda.covariance_[0, 0] / pooled[0, 0]), 4))
print("(n - g) / n:", round((n - g) / n, 4))
比: 0.98
(n - g) / n: 0.98

150件3群なので、比はちょうど (150−3)÷150 = 0.98 になります。ずれが全成分で同じ定数倍に収まるのは、既定の事前確率(学習データの群比率)を使う場合です。priors に群比率と違う値を明示すると成分ごとに比が変わり、定数倍では戻せません。covariance_ をそのまま論文や報告書の「併合分散共分散行列」として転記すると数値が合わなくなるので、この補正を忘れないでください。

判別係数 coef_ の方は、既定の svd ソルバーであれば n−g 側で計算されるため、Excelでの手計算と一致します。ただし lsqr と eigen は covariance_ をそのまま解くので、係数も定数項も手計算の n÷(n−g) 倍になります。先ほどの12件の例では svd が (4.9347, 0.9853) だったのに対し、lsqr と eigen は (5.9216, 1.1824) で、ちょうど12÷10の1.2倍でした。倍率が係数と定数項で共通なので判定は変わりませんが、係数の値を報告書に載せるならソルバーを揃えてください。なお2群では coef_ が1行だけ返り、符号は手計算と逆向きになります。scikit-learnが2つ目の群を正に取る規約によるもので、判定そのものは同じです。

前提条件の検証と、判別分析を選ばない方がよい場面

判別分析の結果が信用できるかは、係数を見る前に前提を確かめたかで決まります。確認すべきは3点です。各群の説明変数が正規分布から大きく外れていないか、群間で分散共分散行列が近いか、説明変数同士が強く相関していないかです。1点目と2点目が崩れると判定の境界そのものがずれ、3点目が崩れると係数の値が不安定になります。

3点目は特に見落とされます。相関の強い変数を同時に入れると、判別係数の符号が実務感覚と逆になったり、データを少し入れ替えただけで係数が大きく振れたりします。上の12件の例は、併合分散共分散行列から求めた年収と勤続年数の相関が −0.3494 と弱かったため、係数が両方とも正で安定しました。同じ2変数でも相関が0.9を超えるデータでは、この符号は簡単に反転します。分散拡大係数(VIF)で確認し、片方を落とすか、主成分分析で次元を落としてから判別する方が安定します。

判別分析を選ばない方がよい場面もはっきりしています。説明変数の大半がカテゴリ変数のときは正規分布の仮定が成立しないので、ロジスティック回帰か決定木系の手法を使ってください。群の境界が曲線や入れ子構造になっているときも、線形判別では原理的に届きません。この場合は二次判別か、非線形の写像を挟むカーネル法の仕組みとカーネル関数の種類の適用が候補になります。そして、最小の群のサンプル数が説明変数の数を下回る場合は、分散共分散行列の逆行列が求まらず計算自体が成立しません。変数を減らすか、データを集め直すのが先です。

よくある質問

判別分析とクラスター分析の違いは何ですか?

グループのラベルが既知かどうかが違いです。判別分析はラベル付きの学習データから分ける式を作る教師あり手法、クラスター分析はラベルの無いデータを似たもの同士で束ねる教師なし手法です。両者を続けて使うこともでき、クラスター分析で作った群をラベルにして判別分析にかければ、どの変数がその群を分けているかを係数で説明できます。ただしこの手順で出る正答率は分類性能の証拠になりません。同じデータからラベルを作っているためで、精度を語るには別に用意したデータで確かめる必要があります。

判別分析とロジスティック回帰分析の違いは何ですか?

置いている前提が違います。判別分析は説明変数が多変量正規分布に従い、群間で分散共分散行列が等しいと仮定します。ロジスティック回帰はこの仮定を置かず、所属確率を直接モデル化します。運用面では境界の動かし方も違います。ロジスティック回帰は出力された確率の閾値を0.5から動かすだけで見逃しと誤検知の比率を調整できますが、判別分析で同じことをするには事前確率か誤分類コストを指定して境界そのものを動かします。

Excelで判別分析をするにはどうすればよいですか?

分析ツールに判別分析のメニューは無いため、行列関数で組みます。AVERAGEで群ごとの平均、VAR.SとCOVARIANCE.Sで群ごとの分散共分散行列を出し、自由度で重み付けして併合します。MINVERSEでその逆行列を求め、MMULTで平均の差ベクトルを掛けたものが判別係数です。定数項は判別係数と2群の平均の中点の積に負号を付けた値になります。

正準判別分析と線形判別分析は何が違いますか?

正準判別分析は、群を最もよく分ける軸を min(群の数 − 1, 変数の数) 本まで順に取り出す枠組みで、群が3つ以上あるときの分離軸の抽出と可視化に使います。線形判別分析は、その軸を使って所属先を判定する分類の側面を指します。実装上は同じクラスで、scikit-learnでは transform が正準判別分析の軸への射影、predict が分類に対応します。2群のときは軸が1本しか取れないため、両者を区別する必要はほとんどありません。

判別分析の正答率はどのくらいあれば十分ですか?

絶対的な基準値はなく、当てずっぽうの水準と比べて判断します。2群なら50%、3群が均等なら33.3%が出発点で、そこからどれだけ上回ったかを見ます。あわせて、学習データをそのまま当てはめた再代入の正答率ではなく、交差検証の値で評価してください。再代入は必ず甘く出るため、両者が大きく開いていれば過学習を疑います。

関連記事

お気に入りに入れた記事の一覧

資料請求

RELATED POSTS 関連記事

目次