浅谈马氏距离【Mahalonobis Distance】

article/2025/8/30 19:19:02

浅谈马氏距离【Mahalonobis Distance】

    • 1. Introduction
    • 2. 欧式距离对于多元数据会存在一些什么问题?
    • 3 .什么是马氏距离
    • 4.马氏距离背后的数学和intuition
    • 5. 利用python来计算马氏距离
    • 6. Case1: 使用马氏距离进行多元异常值检测
    • 7. Case 2: 对分类问题应用马氏距离
    • 8. Case 3: one-class classification
    • 结论

1. Introduction

马氏距离是度量某个点和某个分布间距离的一个指标。在异常值检测高度不平衡数据的分类以及 one-class 分类上都有着广泛的应用。本文将解释马氏距离背后的intuition以及用一些实例帮助大家更好地理解这个指标。

2. 欧式距离对于多元数据会存在一些什么问题?

在介绍马氏距离之前,我想有必要对欧式距离进行一些简单的阐述。欧式距离是我们衡量两个点之间距离的最常用的指标。
如果两个点在一个二维平面中,那么对于这两个点 (p1,q1) 和 (p2,q2) 之间的欧式距离可以表示为:
在这里插入图片描述
对于多维空间,上述式子可以拓展为:
在这里插入图片描述
当然,只要维数(列)equally weighted并且相互独立,欧式距离仍是不错的选择。
这句话是什么意思呢,接下来举个例子。
在这里插入图片描述
这两个表显示了相同对象的“Area”和“Price”,仅仅是变量的单位发生了改变。理论上,任意两行(可以理解为A点和B点)之间的距离都是相同的,但是欧式距离计算的话就会产生不同的值。当然,这个问题可以从技术上加以克服,比如对它进行标准化处理((x – mean) / std),使其范围在0到1之间。

但是,欧式距离还有一个缺点。如果维度(数据集中的列)相互关联(这在实际数据集中通常是这种情况),那么点和分布间的欧式距离对于这个点到底离分布多近就会给出一些误导信息。

在这里插入图片描述
右上图给出了两个正相关变量的散点图。当一个变量增加时,另一个变量也会增加。图中蓝点和红点与中心的(欧式)距离相等,但实际上只有蓝色才是更接近cluster的。

这是因为,欧式距离刻画的仅仅是两个点之间的距离,它并不考虑数据集中的其余点是如何变化的。因此,欧式距离是不能用来真正的判断一个点与点的分布到底有多接近的。

这就引入了马氏距离。

3 .什么是马氏距离

马氏距离是点和分布间点距离,并不是两个点之间的距离,它其实是欧式距离的多元等效项。

那么在计算上,马氏距离到底与欧式距离有何不同呢?

(1) 它将“列”转化成不相关的向量。
(2) 缩放列使其方差等于1。
(3) 最后计算欧式距离

这三个步骤很好地解决了刚才所谈的关于欧式距离的一些缺点。接下来我们来详细了解一下马氏距离。

4.马氏距离背后的数学和intuition

首先,奉上马氏距离的公式:
在这里插入图片描述
这里,D^2 即为马氏距离;x表示观察到的向量(数据集的row);m表示独立变量(列)的均值向量;C^(-1)表示的是独立变量协方差矩阵的逆。

scale
(x-m)实际上是向量与均值的距离,然后除以协方差矩阵。这个形式有没有很眼熟?这实际上是标准化的多元等价形式。z = (x vector) - (mean vector) / (covariance matrix)

correlation
那除以协方差有什么作用呢?

如果数据集中的变量是高度相关的,那么会导致协方差很大,除以较大的协方差就可以有效地减小距离。那如果X并不相关,那么协方差也不大,因此距离也不会减小很多。

综上所述,马氏距离可以有效地解决欧式距离的量纲和相关性的问题。

5. 利用python来计算马氏距离

import pandas as pd
import scipy as sp
import numpy as npfilepath = 'https://raw.githubusercontent.com/selva86/datasets/master/diamonds.csv'
df = pd.read_csv(filepath).iloc[:, [0,4,6]]
df.head()

在这里插入图片描述
接下来写计算马氏距离的公式。

def mahalanobis(x=None, data=None, cov=None):"""Compute the Mahalanobis Distance between each row of x and the data  x    : vector or matrix of data with, say, p columns.data : ndarray of the distribution from which Mahalanobis distance of each observation of x is to be computed.cov  : covariance matrix (p x p) of the distribution. If None, will be computed from data."""x_minus_mu = x - np.mean(data)if not cov:cov = np.cov(data.values.T)inv_covmat = sp.linalg.inv(cov)left_term = np.dot(x_minus_mu, inv_covmat)mahal = np.dot(left_term, x_minus_mu.T)return mahal.diagonal()df_x = df[['carat', 'depth', 'price']].head(500)
df_x['mahala'] = mahalanobis(x=df_x, data=df[['carat', 'depth', 'price']])
df_x.head()

在这里插入图片描述

6. Case1: 使用马氏距离进行多元异常值检测

假设检验统计量遵循自由度为n的卡方分布,则在0.01显著性水平和2自由度下的临界值计算如下:

# Critical values for two degrees of freedom
from scipy.stats import chi2
chi2.ppf((1-0.01), df=2)
#> 9.21

这意味着,如果观测值的马氏距离超过9.21,则可以认为是极端。

当然也可以用p值来确定观察值是否极端:

# Compute the P-Values
df_x['p_value'] = 1 - chi2.cdf(df_x['mahala'], 2)# Extreme values with a significance level of 0.01
df_x.loc[df_x.p_value < 0.01].head(10)

在这里插入图片描述
这些值和数据集中的其余部分进行比较,那很显然是极端的。

7. Case 2: 对分类问题应用马氏距离

利用马氏距离进行分类的intuition是将观察值归类为与它最接近的类别。

让我们看一下BreastCancer数据集上的示例实现,其目的是确定肿瘤是良性还是恶性的。

df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/BreastCancer.csv', usecols=['Cl.thickness', 'Cell.size', 'Marg.adhesion', 'Epith.c.size', 'Bare.nuclei', 'Bl.cromatin', 'Normal.nucleoli', 'Mitoses', 'Class'])df.dropna(inplace=True)  # drop missing values.
df.head()

在这里插入图片描述
让我们以70:30的比例将数据集拆分为训练和测试。然后将训练数据集分为“ pos”(1)和“ neg”(0)类的同类组。为了预测测试数据集的类别,我们测量给定观测值(行)与正值(xtrain_pos)和负值数据集(xtrain_neg)之间的马氏距离。然后,根据观察到的最接近的组为其分配类别。

from sklearn.model_selection import train_test_split
xtrain, xtest, ytrain, ytest = train_test_split(df.drop('Class', axis=1), df['Class'], test_size=.3, random_state=100)# Split the training data as pos and neg
xtrain_pos = xtrain.loc[ytrain == 1, :]
xtrain_neg = xtrain.loc[ytrain == 0, :]

接下来构建Mahalanobis Binary Classifier。

class MahalanobisBinaryClassifier():def __init__(self, xtrain, ytrain):self.xtrain_pos = xtrain.loc[ytrain == 1, :]self.xtrain_neg = xtrain.loc[ytrain == 0, :]def predict_proba(self, xtest):pos_neg_dists = [(p,n) for p, n in zip(mahalanobis(xtest, self.xtrain_pos), mahalanobis(xtest, self.xtrain_neg))]return np.array([(1-n/(p+n), 1-p/(p+n)) for p,n in pos_neg_dists])def predict(self, xtest):return np.array([np.argmax(row) for row in self.predict_proba(xtest)])clf = MahalanobisBinaryClassifier(xtrain, ytrain)        
pred_probs = clf.predict_proba(xtest)
pred_class = clf.predict(xtest)# Pred and Truth
pred_actuals = pd.DataFrame([(pred, act) for pred, act in zip(pred_class, ytest)], columns=['pred', 'true'])
print(pred_actuals[:5])     

输出:
在这里插入图片描述
让我们看看分类器如何在测试数据集上执行。

from sklearn.metrics import classification_report, accuracy_score, roc_auc_score, confusion_matrix
truth = pred_actuals.loc[:, 'true']
pred = pred_actuals.loc[:, 'pred']
scores = np.array(pred_probs)[:, 1]
print('AUROC: ', roc_auc_score(truth, scores))
print('\nConfusion Matrix: \n', confusion_matrix(truth, pred))
print('\nAccuracy Score: ', accuracy_score(truth, pred))
print('\nClassification Report: \n', classification_report(truth, pred))

输出:

AUROC:  0.9909743589743589Confusion Matrix: [[113  17][  0  75]]Accuracy Score:  0.9170731707317074Classification Report: precision    recall  f1-score   support0       1.00      0.87      0.93       1301       0.82      1.00      0.90        75avg / total       0.93      0.92      0.92       205

8. Case 3: one-class classification

One-class是一种算法,其中训练数据集包含仅属于一个类的观察值。在仅知道该信息的情况下,目标是确定新(或测试)数据集中的给定观察是否属于该类。

让我们在BreastCancer数据集上尝试一下,我们将仅考虑训练数据中的恶性观察(类别column = 1)。

df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/BreastCancer.csv', usecols=['Cl.thickness', 'Cell.size', 'Marg.adhesion', 'Epith.c.size', 'Bare.nuclei', 'Bl.cromatin', 'Normal.nucleoli', 'Mitoses', 'Class'])df.dropna(inplace=True)  # drop missing values.

将数据集的50%分成训练和测试。训练数据中仅保留1。

from sklearn.model_selection import train_test_split
xtrain, xtest, ytrain, ytest = train_test_split(df.drop('Class', axis=1), df['Class'], test_size=.5, random_state=100)# Split the training data as pos and neg
xtrain_pos = xtrain.loc[ytrain == 1, :]

让我们构建一个,MahalanobisOneClassClassifier并从训练集(xtrain_pos)中获得x中每个数据点的马氏距离。

class MahalanobisOneclassClassifier():def __init__(self, xtrain, significance_level=0.01):self.xtrain = xtrainself.critical_value = chi2.ppf((1-significance_level), df=xtrain.shape[1]-1)print('Critical value is: ', self.critical_value)def predict_proba(self, xtest):mahalanobis_dist = mahalanobis(xtest, self.xtrain)self.pvalues = 1 - chi2.cdf(mahalanobis_dist, 2)return mahalanobis_distdef predict(self, xtest):return np.array([int(i) for i in self.predict_proba(xtest) > self.critical_value])clf = MahalanobisOneclassClassifier(xtrain_pos, significance_level=0.05)
mahalanobis_dist = clf.predict_proba(xtest)# Pred and Truth
mdist_actuals = pd.DataFrame([(m, act) for m, act in zip(mahalanobis_dist, ytest)], columns=['mahal', 'true_class'])
print(mdist_actuals[:5])            
Critical value is:  14.067140449340169mahal  true_class
0  13.104716           0
1  14.408570           1
2  14.932236           0
3  14.588622           0
4  15.471064           0

我们有马氏距离和每个观测的实际类别。我希望那些具有低马氏距离的观测值是1。因此,我mdist_actuals按Mahalanobis距离进行排序,并按分位数将行分成10个相等大小的组。顶部分位数中的观察数应比底部分位数中的观察数多。让我们来看一下。

# quantile cut in 10 pieces
mdist_actuals['quantile'] = pd.qcut(mdist_actuals['mahal'], q=[0, .10, .20, .3, .4, .5, .6, .7, .8, .9, 1], labels=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10])# sort by mahalanobis distance
mdist_actuals.sort_values('mahal', inplace=True)
perc_truths = mdist_actuals.groupby('quantile').agg({'mahal': np.mean, 'true_class': np.sum}).rename(columns={'mahal':'avg_mahaldist', 'true_class':'sum_of_trueclass'})
print(perc_truths)
avg_mahaldist  sum_of_trueclass
quantile                                 
1              3.765496                33
2              6.511026                32
3              9.272944                30
4             12.209504                20
5             14.455050                 4
6             15.684493                 4
7             17.368633                 3
8             18.840714                 1
9             21.533159                 2
10            23.524055                 1

1(恶性病例)中将近90%落在马氏距离的前40%范围内。顺便提及,所有这些都低于临界值pf 14.05。因此,让我们将临界值作为临界值,并将那些马氏距离小于临界值的观测值标记为正值。

from sklearn.metrics import classification_report, accuracy_score, roc_auc_score, confusion_matrix# Positive if mahalanobis 
pred_actuals = pd.DataFrame([(int(p), y) for y, p in zip(ytest, clf.predict_proba(xtest) < clf.critical_value)], columns=['pred', 'true'])# Accuracy Metrics
truth = pred_actuals.loc[:, 'true']
pred = pred_actuals.loc[:, 'pred']
print('\nConfusion Matrix: \n', confusion_matrix(truth, pred))
print('\nAccuracy Score: ', accuracy_score(truth, pred))
print('\nClassification Report: \n', classification_report(truth, pred))
Confusion Matrix: [[183  29][ 15 115]]Accuracy Score:  0.8713450292397661Classification Report: precision    recall  f1-score   support0       0.92      0.86      0.89       2121       0.80      0.88      0.84       130avg / total       0.88      0.87      0.87       342

因此,在不了解良性分类的情况下,我们能够准确预测87%的观察结果的分类。

结论

在这篇文章中,几乎涵盖了有关马氏距离的所有内容:公式背后的intuition,python中的实际计算以及如何将其用于多元异常检测,二进制分类和一类分类。


http://chatgpt.dhexx.cn/article/fUtSvrOA.shtml

相关文章

距离度量之马氏距离

马氏距离 用来度量一个样本点&#xff30;与数据分布为&#xff24;的集合的距离。 假设样本点为&#xff1a; 数据集分布的均值为&#xff1a; 协方差矩阵为&#xff33;。 则这个样本点&#xff30;与数据集合的马氏距离为&#xff1a; 马氏距离也可以衡量两个来自同一…

马氏距离(Mahalanobis Distance)介绍与实例

本文介绍马氏距离&#xff08;Mahalanobis Distance&#xff09;&#xff0c;通过本文&#xff0c;你将了解到马氏距离的含义、马氏距离与欧式距离的比较以及一个通过马氏距离进行异常检测的例子&#xff08;基于Python的sklearn包&#xff09;。 目的 计算两个样本间的距离时…

马氏距离-Mahalanobis Distance

一、学习目的 在训练one-shoting learning 的神经网路的时候&#xff0c;由于采用的是欧式距离&#xff0c;欧氏距离虽然很有用&#xff0c;但也有明显的缺点。它将样品的不同属性&#xff08;即各指标或各变量&#xff09;之间的差别等同看待&#xff0c;这一点有时不能满足实…

欧氏距离与马氏距离

Preface 之前在写《Multi-view CNNs for 3D Objects Recognition》的阅读笔记的时候&#xff0c;文章中的一个创新点便是将MVCNN网络提取到的3D Objects的形状特征描述符&#xff0c;投影到马氏距离&#xff08;Mahalanobis Distance&#xff09;上&#xff0c;“这样的话&…

马氏距离 Mahalanobis Distance

马氏距离 Mahalanobis Distance 1. 马氏距离定义2. 马氏距离实际意义2.1 欧氏距离近就一定相似&#xff1f;2.2 归一化后欧氏距离就一定相似&#xff1f;2.3 算上维度的方差就够了&#xff1f; 3. 马氏距离的几何意义4. 马氏距离的推导5. 马氏距离限制 Reference: 马氏距离(Mah…

马氏距离概念

马氏距离 一、基本概念&#xff1a; 方差&#xff1a;方差是标准差的平方&#xff0c;而标准差的意义是数据集中各个点到均值点距离的平均值。反应的是数据的离散程度。 协方差&#xff1a;标准差与方差是描述一维数据的&#xff0c;当存在多维数据时&#xff0c;我们通常需要知…

马氏距离通俗理解

基础知识&#xff1a; 假设空间中两点x&#xff0c;y&#xff0c;定义&#xff1a; 欧几里得距离&#xff0c; Mahalanobis距离&#xff0c; 不难发现&#xff0c;如果去掉马氏距离中的协方差矩阵&#xff0c;就退化为欧氏距离。那么我们就需要探究这个多出来的因子究竟有什么含…

马氏距离Mahalanobis Distance实例

简介 如果按照欧氏距离去理解马氏距离&#xff0c;一定会迷惑一段时间。因为欧氏距离可以计算两个点之间的距离&#xff0c;而马氏距离是计算一个点距离一个聚类的距离。如果想通过马氏距离去计算某两个点之间的距离是行不通的。下面按照一般的套路介绍一下欧氏距离与马氏距离…

马氏距离详解

马氏距离详解 一、理性认知二、感性认知第一个例子第二个例子 三、实例认知四、公式推导推导过程 致谢 一、理性认知 马氏距离(Mahalanobis distance)是由印度统计学家马哈拉诺比斯(P. C. Mahalanobis)提出的&#xff0c;表示点与一个分布之间的距离。它是一种有效的计算两个未…

马氏距离(Mahalanobis Distance)

马氏距离(Mahalanobis Distance)是度量学习中一种常用的距离指标,同欧氏距离、曼哈顿距离、汉明距离等一样被用作评定数据之间的相似度指标。但却可以应对高维线性分布的数据中各维度间非独立同分布的问题。 什么是马氏距离 马氏距离(Mahalanobis Distance)是一种距离的度量,…

马氏距离详解(数学原理、适用场景、应用示例代码)

看了很多关于马氏距离&#xff08;Mahalanobis Distance&#xff09;的介绍&#xff0c;但是总感觉有一些地方不太清晰&#xff0c;所以结合数学公式、机器学习中的应用案例&#xff0c;从头梳理一下。 马氏距离实际上是欧氏距离在多变量下的“加强版”&#xff0c;用于测量点…

linux 配置swoole环境

linux 配置swoole环境 安装PHP wget http://mirrors.linuxeye.com/oneinstack-full.tar.gz && tar xzf oneinstack-full.tar.gz && ./oneinstack/install.sh --php_option 6 --phpcache_option 1 --reboot vim /usr/local/php/etc/php.ini 删除对exec函数…

ppp开启pap/chap认证

什么是pap&#xff1f; PAP 是 PPP 协议集中的一种链路控制协议&#xff0c;通过2次握手建立认证&#xff0c;对等结点持续重复发送 ID/ 密码&#xff08;明文&#xff09;给验证者。 什么是chap&#xff1f; CHAP通过三次握手验证被认证方的身份&#xff0c;在初始链路建立…

Ensp配置PPP CHAP认证

如图配置IP地址 启用 CHAP 认证&#xff0c;用户名/密码为&#xff1a;HuaWei/123456 确保RAR20-A和RAR20-B之间可以互通 按照如下步骤进行。 1&#xff09;配置IP地址&#xff0c;确保设备互通 <Huawei>system-view [Huawei]sysname RAR20-A [RAR20-A]in…

思科模拟器启用CHAP协议

chap使用密文格式发送chap认证信息&#xff0c;相比较pap的明文格式&#xff0c;更具有安全性。 添加s端口&#xff1a;先将路由器关闭&#xff0c;将HWIC-2T模块拖入卡槽&#xff0c;再将路由器开启 单向CHAP&#xff1a;R2为认证方 R1&#xff1a; hostname R1 …

H3C(27)——PAP与CHAP

1.PAP的单向认证 【R1】 <RouterA> system-view[RouterA] local-user userb class network [RouterA-luser-network-userb] password simple passb [RouterA-luser-network-userb] service-type ppp [RouterA-luser-network-userb] quit[RouterA] interface serial 1/0 …

ppp的chap认证报文原理以及细节

ppp的chap认证报文原理 chap认证&#xff1a; 1.验证方&#xff08;存有本地数据库的一方&#xff09;主动向被验证方发送一个挑战报文&#xff0c;里面包含报文id&#xff0c;随机数&#xff0c;本端用户名&#xff08;默认单向认证不带&#xff09;。 2.被验证方收到挑战请求…

Cisco(56)——PAP和CHAP

说明:R1,R3,R5,R7,R9的S1/1的地址为1.1.1.1/24,R2,R4,R6,R8,R10的S1/1的地址为1.1.1.2/24,实验步骤省略配置hostname和IP地址的过程! 一:PAP的单向认证,R1为认证方 R1(config)#username R2 password 0 123R1(config)#interface serial 1/1 R1(config-if)#encapsulation …

ppp协议(pap和chap验证模式)拓扑(eNSP)

一&#xff0e;基本配置 新建拓扑 ①添加路由&#xff1a;添加两个Axaioxia_2220路由到拓扑图上 ②改标签名&#xff1a;其标签名称默认为Axiaoxia_1与Axaioxia_2&#xff0c;双击“Axiaoxia_1与Axaioxia_2”手动改为自己需要的名, 我改为“xiaoxia_1与xiaoxia_2” ③添加…

PAP与CHAP认证

一、PPP介绍 PPP&#xff08;point-to-point protocol&#xff09;是一种点到点链路层协议&#xff0c;主要用于在全双工的同异步链路上进行点到点的数据传输。##在PPP中主要由三类协议簇组成 1、链路控制协议簇&#xff08;Link Control protocol&#xff09;&#xff1a;主要…