2026年10月8日にscikit-learn 1.9.1のMDS本文を再確認した。MDSは非類似度を指定した次元の配置へ近似する方法で、metric/non-metric、距離の定義、初期値、反復、stress、ランダム性、欠損扱いで地図が変わる。2次元の近さをブランド需要、原因、客観的な空白市場と読み替えず、距離表・次元数・再実行の安定性・外れ値・元データの意味を併記する。
MDSは、対象どうしの非類似度から点の配置を作る方法です。商品AとBの違いを2、AとCの違いを5と決めたなら、その関係を地図上の点間距離で表します。ただし、元の情報を2次元に収められない場合もあります。地図の近さだけでなく、どの組の距離がどれだけ変わったかまで読む必要があります。
30秒で要点
- 入力は「何を違いとするか」を決めた非類似度。類似度の大きさを、そのまま距離として渡すものではありません。
- 古典MDS、計量MDS、非計量MDSは同じ計算ではありません。比較する誤差の定義と実装を明記します。
- 架空の長方形4点は2次元で正確に再現できますが、横軸だけにすると縦の距離3が0になります。
- 軸の向きや地図の空白から、需要・因果・市場機会までは判断できません。
まず、何を「近い」と呼ぶか決める
身長と体重のように単位の違う数値をそのまま使うと、大きな数値範囲の項目が距離に強く影響します。標準化をする場合も、「各項目をどの程度重く扱うか」を変えていることを記録します。
表が収まらない場合は、横にスクロールできます
| 入力・目的 | 選択肢の例 | 先に確かめること |
|---|---|---|
| 同じ単位や重みづけを定義できる数値 | ユークリッド距離 | 単位・外れ値・欠測処理 |
| ベクトルの大きさより向きを比べたい | コサイン非類似度など | ゼロベクトル、負値、使う式 |
| 項目の上下パターンを比べたい | 相関から作る非類似度 | 定数列、中心化、何を無視するか |
| 数値とカテゴリが混在する | Gower型の非類似度など | 各変数の重み、カテゴリ型、欠測の分母 |
これは自動選択表ではありません。たとえば、値の大きさが重要な売上規模を、向きだけの比較で消してよいかは目的次第です。また、対称・非負・対角0の表であっても、低次元のユークリッド距離として完全再現できるとは限りません。
古典・計量・非計量を分ける
表が収まらない場合は、横にスクロールできます
| 方法 | 主な考え方 | 読み違えやすい点 |
|---|---|---|
| 古典MDS | 距離の二乗を中心化した行列を固有分解する | 固有値による近似は、一般のstress最小化と同じ目的関数ではない |
| 計量MDSの代表的な方法 | 入力の非類似度と点間距離の差を小さくする | 次元や初期値、反復停止条件で結果が変わりうる |
| 非計量MDS | 非類似度を順位関係に沿って変換した値と点間距離を合わせる | 元の非類似度の絶対差を、そのまま保存する方法ではない |
古典MDSでは、距離行列をD、対象数をn、中心化行列をJ、全成分1の列ベクトルを1とすると、J = I - 11ᵀ/n、B = -J(Dを要素ごとに二乗した行列)J/2 を使います。正の固有値と固有ベクトルから座標を作ります。非ユークリッドな非類似度からは負の固有値が出ることがあり、その場合は再現できない成分を隠さないことが大切です。Rのcmdscale仕様
同じ配置を全体として回転・反転・平行移動しても点間距離は変わりません。地図の右側を自動的に「高級」、上側を「好感」と命名するのではなく、元の項目や別の観測と照合して説明します。
架空4点で、2次元から1次元への損失を見る
次はMDSの再現誤差を説明するための架空データです。実際のブランド調査ではありません。A=(0,0)、B=(4,0)、C=(0,3)、D=(4,3)という長方形から距離を作りました。
表が収まらない場合は、横にスクロールできます
| 組 | 入力の距離 | 2次元の再現距離 | 横軸だけを残した1次元の距離 | 1次元の残差平方 |
|---|---|---|---|---|
| A–B | 4 | 4 | 4 | 0 |
| A–C | 3 | 3 | 0 | 9 |
| A–D | 5 | 5 | 4 | 1 |
| B–C | 5 | 5 | 4 | 1 |
| B–D | 3 | 3 | 0 | 9 |
| C–D | 4 | 4 | 4 | 0 |
2次元では6組すべてを再現できます。横軸だけを残すとAとC、BとDは重なります。長い横幅を残せても、「上下に3離れている」という関係は失われます。
この例の中心化行列Bの固有値は16、9、0、0です。横方向の1成分を残した指定の配置では、距離の残差平方和は20、入力距離の平方和は100。ここで独自に sqrt(20/100) と定義した相対誤差は約0.4472です。これはこの投影と分母に対する値であり、最良の1次元stress解や、ライブラリが返すStress-1の値とは呼びません。
Python:旧3点の距離表を古典MDSで再現する
次の教材は、距離表を入力して座標を出す手順を示します。旧3点の距離2・5・4をそのまま使い、古典MDSの計算をNumPyで明示しています。生成された座標の符号や向きより、最後に表示する再現距離を確認してください。
import numpy as np
D = np.array([[0, 2, 5], [2, 0, 4], [5, 4, 0]], dtype=float)
J = np.eye(len(D)) - np.ones_like(D) / len(D)
B = -0.5 * J @ (D ** 2) @ J
eigenvalues, eigenvectors = np.linalg.eigh(B)
order = np.argsort(eigenvalues)[::-1]
eigenvalues = eigenvalues[order]
eigenvectors = eigenvectors[:, order]
if eigenvalues.min() < -1e-10:
raise ValueError("This example expects Euclidean distances")
Z = eigenvectors[:, :2] * np.sqrt(np.maximum(eigenvalues[:2], 0))
reproduced = np.linalg.norm(Z[:, None, :] - Z[None, :, :], axis=2)
print("coordinates:\n", np.round(Z, 6))
print("distances:\n", np.round(reproduced, 6))
assert np.allclose(reproduced, D)
同じ距離は A=(0,0)、B=(2,0)、C=(13/4, sqrt(231)/4)でも表せます。出力がこの向きにならないことは異常ではありません。
scikit-learnのMDSは別の計算経路です。次はscikit-learn 1.5.2の引数で計量MDSを指定する教材です。距離表から座標を出す役割は同じですが、上の固有分解と同じ座標・同じ目的関数とは限りません。
import numpy as np
import sklearn
from sklearn.manifold import MDS
assert sklearn.__version__ == "1.5.2", "This example specifies scikit-learn 1.5.2"
D = np.array([[0, 2, 5], [2, 0, 4], [5, 4, 0]], dtype=float)
mds = MDS(n_components=2, metric=True, dissimilarity="precomputed",
random_state=42, n_init=8, max_iter=1000, eps=1e-9,
normalized_stress=False)
Z = mds.fit_transform(D)
print("coordinates:\n", np.round(Z, 6))
print("reported raw stress:", mds.stress_)
使用版によってdissimilarity、metric、metric_mdsの引数や初期化の既定値が異なります。古いコードと最新ドキュメントの引数を混ぜず、版・初期値・反復条件・正規化の設定を記録してください。MDS API
stressと次元数は、同じ条件で比べる
計量MDSの誤差を説明するときは、たとえば 各i<jについて(入力非類似度 - 再現距離)²を合計する と、何を足しているかを先に明らかにします。非計量では比較相手が変換後の値となり、正規化した指標では分母も必要です。
次元を増やすと一般に配置の自由度は増えますが、低い誤差だけで測定や解釈が正しいと判断しません。同じ対象・非類似度・方法のもとで、全体の値と組ごとの残差を併記します。初期値を変えた複数の解、対象を少し変えたときの関係、別の調査でも同じ傾向が出るかを確かめます。再標本化を行う場合も、何を独立な標本とみなすかを決めます。
ブランド調査のケース:地図から言えることを限定する
架空のブランド調査で、回答者が付けた印象項目から非類似度を作るとします。近い2ブランドは、その回答者・質問・尺度・距離の定義では似た値だったと読めます。距離が大きいことだけで、利益が出る差別化や顧客に選ばれる理由を確認したことにはなりません。
- 比べる対象、回答者、質問項目、欠測処理、重みを記録する。
- 誤差の大きい組を確認し、2D図だけで言い切れない関係を示す。
- 空白領域は仮説の候補にとどめ、需要・購入意向・提供費用は別途調べる。
- 調査を繰り返すときは、質問や対象が変わった影響と実際の印象変化を分ける。
練習3問
1. stressが高ければ外れ値を削ってよい?
いいえ。入力誤りか、意味のある異質な対象かを先に調べます。次元数・計算法・初期値・距離の選択を点検し、除外するなら理由と除外前後を残します。
2. 毎回地図の向きが違う。関係も変わった?
点間距離が同じなら、回転・反転による可能性があります。向きを揃えるだけで済む違いと、距離・近傍関係そのものが変わった違いを分けます。
3. 数値とカテゴリが混在する場合は?
Gower型などが候補になります。ただし、カテゴリの扱い、変数の重み、欠測時の計算を定義し、その非類似度をMDSがどの程度再現できるか確認します。
5分診断:目的・データ・継続比較を確認する
表が収まらない場合は、横にスクロールできます
| 問い | 未確定なら先に行うこと |
|---|---|
| 何の違いを読み、どの判断に使うか決まっている? | 「似ている」の意味と、図だけでは決めない事項を書く |
| 対象・尺度・欠測処理が明確? | 距離表を作る前のデータ処理を記録する |
| 継続比較と検証の仕組みがある? | 定義の変更、残差、別調査の結果を分けて残す |
関連と次の一歩
- 度数表のプロフィールを扱うならコレスポンデンス分析
- 数値変数の分散を少数成分にまとめるならPCA
- 地図を描くことと群分けの目的を比較するならクラスター分析
参照したい一次資料
- R stats: cmdscale:古典MDS、固有値、補正と配置の仕様
- scikit-learn: MDS:計量・非計量、stress、版ごとのAPI
- scikit-learn 1.5.2: MDS:掲載コードの対象版
- R cluster: daisy:混合型の非類似度・重み・欠測