マハラノビス距離とユークリッド距離の違い
DESCRIPTION
相関のある多変量データで距離を測る場合、我々が通常「距離」と呼ぶユークリッド距離よりも、マハラノビス距離の方が都合がよい。多変量データを変数ごとに標準化してユークリッド距離をとる場合は標準化により変数間の関係性が変わる上に相関関係は考慮されないが、マハラノビス距離を使えば変数間の相関関係も考慮した多変量標準化尺度として使用できる。Rでのデモつき。 このメモでは、説明のために、比較的きれいなデータを用いて、距離の大きさで便宜上外れ値を判定してはいるが、ロバスト性のない平均値ベクトルや共分散行列から計算されるマハラノビス距離はやはり全くロバスト性をもたないため、外れ値検出の目的で使用してはいけない。逆に言えば、マハラノビス距離を用いて外れ値検出を行うためには、平均値ベクトルと共分散行列の代わりに、ロバスト推計した位置と尺度指標を用いれば良い。TRANSCRIPT
5 10 15 20 25
020
40
60
80
100120
speed
dist
-2 -1 0 1
-10
12
3
speed
dist
Histogram of d1
d1
Frequency
0 40 80 120
05
10
15
-2 -1 0 1
-10
12
3
speed
dist
2011.02 作成
マハラノビス距離とユークリッド距離の違い
車のスピードと停車するまでに必要な距離を測定した2変数の cars データセットを用いて、データ中心からの各データポイントの距離を測定する。 我々が通常距離と呼んでいるものはユークリッド距離だが、相関のある多変量データを取り扱う際にはマハラノビス距離の方が便利。
方法 1 標準化してユークリッド距離を測定
変数 dist と speed はそれぞれ尺度が違うのでそのままで距離計算をすると第 1 変数の影響が第 2 変数よりも大きくなる。
これを避けるために、まず2変数をそれぞれ標準化し(図 2)、それから二乗和の平方根をとって距離を計算する。
図 1
図 2
図 3
図 4
距離 d1 が 120 を越える外れ値は 49 番のデータポイント。次に他のデータから外れ気味なのは緑で示すデータポイントで、距離が遠い順に 48, 47, 509, 35, 23 番が分布の外側にあるということになる。
Histogram of d2
d2
Frequency
0 2 4 6 8 10
010
20
30
5 10 15 20 25
040
80
120
speed
dist
方法 2 マハラノビス距離による測定
方法 1 のユークリッド距離のかわりに、平均値ベクトルと共分散行列から算出するマハラノビス距離を使用してみる。
方法 1 と同様、ヒストグラム(図 5)を作成し、で大きな距離とる柱二つ分の色を変えてデータポイントを表示したのが図 6。緑表示されているのは、データ番号 23 番のみ。
○ マハラノビス距離
平均値ベクトルが 、共分散行列が Σ である多変量データ は、以下により算出される。
図 5
「標準化+ユークリッド距離」と「マハラノビス距離」の違いは、マハラノビス距離がデータ分散だけでなく相関も考慮しているということ。つまり、データを多変量標準化して距離尺度を作成していることになる。
-3 -2 -1 0 1 2 3
-3-2
-10
12
3
無相関ユークリッド
NmA[,1]
NmA[,2]
-3 -2 -1 0 1 2 3
-3-2
-10
12
3
無相関マハラノビス
NmA[,1]
NmA[,2]
-3 -2 -1 0 1 2 3
-3-2
-10
12
3
0.8相関 ユークリッド
NmB[,1]
NmB[,2]
-3 -2 -1 0 1 2 3
-3-2
-10
12
3
0.8相関 マハラノビス
NmB[,1]
NmB[,2]
おまけ:マハラノビス距離とユークリッド距離の違い
データ NmA は、独立なデータ数 1000 の正規乱数を二つ組み合わせたもので、NmB もデータ数 1000 の正規乱数だが変数間に 0.8 の相関がある。
この二種類のデータについて、それぞれユークリッド距離とマハラノビス距離を計算し、データ中心から距離 2 以内の部分を緑、さらに距離 1 以内の部分を赤に塗ってみた。
データが正規分布に従う場合、各データポイントのデータ中心(平均値ベクトル)からのマハラノビス距離は F 分布に従う。
Rコード
data(cars) # carsデータ呼び出しdat <- as.matrix(cars) # リスト属性の cars データを行列属性に変換してdatに格納d <- ncol(dat) # d: 変数の数n <- nrow(dat) # n: データ数plot(dat) # 図 1が表示される
##### ユークリッド距離による試算
dat.s <- scale(dat) # 標準化plot(dat.s) # 図 2が表示される
d1 <- sqrt(dat[,1]^2 + dat[,2]^2) # 第一変数と第二変数の二乗和の平方根で距離計算hist(d1) # 計算された距離をヒストグラムに。図 3。
flg <- rep(1, n) # 色表示用のデータフラグ作成。初期値は 1(黒)flg[which(d1>80)] <- 3 # 距離 d1が 80を越えるデータを 3(緑)にflg[which(d1>120)] <- 2 # 距離 d1 が 120 を越えるデータを 2(赤)にplot(dat.s, pch=20, col=flg) # 図 4表示which(flg==2) # 赤表示されるデータの番号がわかる。No.49which(flg==3) # 緑表示されるデータの番号がわかる。No. 23, 35, 47, 48, 509
##### マハラノビス距離による試算cv <- cov(dat) # 共分散行列計算mn <- colMeans(dat) # 平均値ベクトル算出d2 <- mahalanobis(dat, mn, cv) # マハラノビス距離算出hist(d2) # 図 5の表示
flg2 <- rep(1, n) # 色表示用のデータフラグ作成。初期値は 1(黒)flg2[which(d2>6)] <- 3 # 距離 d1 が 6 を越えるデータだけ 3(緑)にflg2[which(d2>8)] <- 2 # 距離 d1 が 8 を越えるデータだけ 2(赤)にplot(dat, pch=20, col=flg2) # 図 4表示which(flg2==2) # 赤表示されるデータの番号がわかる。No.49
#################### おまけ ####################rm(list=ls(all=TRUE)) # 作業領域のクリアlibrary(mvtnorm) # rmvnorm(多変量正規乱数)関数用set.seed(25) # 乱数の再現性確保のため
# 共分散行列作成c08 <- matrix(0.8, ncol=2, nrow=2)
# # 対角成分を 1 に(diag(c08) <- 1) # 算式を括弧で囲むと内容表示n1 <- 1000 # 作成するデータ数
# 正規分布データ NmA <- cbind(rnorm(n1), rnorm(n1))
# 単変量の独立な正規分布データを組み合わせただけ NmB <- rmvnorm(n=n1, mean=c(0, 0), sigma=c08)
# 相関 0.8の多変量正規分布データ
cor(NmA); cor(NmB) # 実相関
# ユークリッド距離の計算#eucA <- sqrt(diag(scale(NmA) %*% t(scale(NmA))))
#eucB <- sqrt(diag(scale(NmB) %*% t(scale(NmB))))
eucA <- sqrt(diag(NmA %*% t(NmA)))
eucB <- sqrt(diag(NmB %*% t(NmB)))
#マハラノビス距離の計算mahA <- mahalanobis(NmA, apply(NmA, 2, mean), cov(NmA))
mahB <- mahalanobis(NmB, apply(NmB, 2, mean), cov(NmB))
# パラメータはデータ・平均値ベクトル・共分散行列# ユークリッド距離と比較可能にする# F検定統計量の計算eucA.s <- eucA * (n1 - 2)* n1 /((n1^2 - 1)* 2)
eucB.s <- eucB * (n1 - 2)* n1 /((n1^2 - 1)* 2)
mahA.s <- mahA * (n1 - 2)* n1 /((n1^2 - 1)* 2)
mahB.s <- mahB * (n1 - 2)* n1 /((n1^2 - 1)* 2)
# 正規分布の 1σ(約 68.27%)、2 σ(約 95.45%)にあたるF分布の%値を算出cf1 <- qf(0.6827, 2, n1 - 2)
cf2 <- qf(0.9545, 2, n1 - 2)
# 色設定 距離 1より内側を赤にeucA.cl <- rep(1, 1000);
eucA.cl[which(eucA < 2)] <- 3
eucA.cl[which(eucA < 1)] <- 2
eucB.cl <- rep(1, 1000);
eucB.cl[which(eucB < 2)] <- 3
eucB.cl[which(eucB < 1)] <- 2
mahA.cl <- rep(1, 1000);
mahA.cl[which(mahA.s < cf2)] <- 3
mahA.cl[which(mahA.s < cf1)] <- 2
mahB.cl <- rep(1, 1000);
mahB.cl[which(mahB.s < cf2)] <- 3
mahB.cl[which(mahB.s < cf1)] <- 2
par(mfrow=c(2,2)) # 2行 2列にグラフィック画面分割 plot(NmA, pch=20, col=eucA.cl, main="無相関ユークリッド")
plot(NmA, pch=20, col=mahA.cl, main="無相関マハラノビス")
plot(NmB, pch=20, col=eucB.cl, main="相関 0.8ユークリッド")
plot(NmB, pch=20, col=mahB.cl, main="相関 0.8マハラノビス")