我们通常采用计算“距离”的方法来度量不同样本之间的相似性,进而判断该样本的大致类别。距离首先是一个几何概念,用 dist(⋅,⋅) d i s t ( ⋅ , ⋅ ) 表示,其中最为任熟悉的是二维和三维几何空间的欧几里德距离,随着数据维度的增大,距离在维数、幂次数等方面被推广了,距离被抽象为满足一些基本性质:
非负性:
graph TD;
连续属性-->有序属性;
离散属性-->有序属性;
离散属性-->无序属性;
有序属性-->闵科夫斯基;
无序属性-->VDM;
def eucldist_forloop(coords1, coords2):
""" Calculates the euclidean distance between 2 lists of coordinates. """
dist = 0
for (x, y) in zip(coords1, coords2):
dist += (x - y)**2
return dist**0.5
或者
# 生成器表达式
def eucldist_generator(coords1, coords2):
""" Calculates the euclidean distance between 2 lists of coordinates. """
return sum((x - y)**2 for x, y in zip(coords1, coords2))**0.5
或者
# NumPy版本
def eucldist_vectorized(coords1, coords2):
""" Calculates the euclidean distance between 2 lists of coordinates. """
return np.sqrt(np.sum((coords1 - coords2)**2))
或者
# NumPy 内建函数
np.linalg.norm(np_c1 - np_c2)
或者
# 根据scipy库求解
from scipy.spatial.distance import pdist
X=np.vstack([np_c1,np_c2])
d2=pdist(X)
当 p→∞ p → ∞ 时,闵科夫斯基距离即切比雪夫距离(Chebyshev Distance)
python实现:
# NumPy 内建函数
np.linalg.norm(np_c1 - np_c2,ord=np.inf)
或者
# 根据scipy库求解
from scipy.spatial.distance import pdist
X=np.vstack([np_c1,np_c2])
d2=pdist(X,'chebyshev')
当 p=1 p = 1 时,闵科夫斯基距离即曼哈顿距离(Manhattan distance)
python实现:
# NumPy 内建函数
np.linalg.norm(np_c1 - np_c2,ord=1)
#根据scipy库求解
from scipy.spatial.distance import pdist
X=np.vstack([np_c1,np_c2])
d2=pdist(X,'cityblock')
令 mu,a m u , a 表示属性 u u 上取值为 a a 的样本数, mu,a,i m u , a , i 表示在第 i i 个样本簇中在属性 u u 上取值为 a a 的样本数, k k 为样本簇数,则属性 u u 上两个离散值 a a 与 b b 之间的VDM距离为
利用闵可夫斯基度量对高维数据进行聚类通常是无效的,因为样本之间的距离随着维数的增加而增加。余弦距离测量两个矢量之间的夹角,而不是两个矢量之间的幅值差。它适用于高维数据聚类时相似度测量。
# NumPy 内建函数
np.dot(vector1,vector2)/(np.linalg.norm(vector1)*(np.linalg.norm(vector2)))
马氏距离,即数据的协方差距离,于欧式距离不同的是它考虑到各属性之间的联系,如考虑性别信息时会带来一条关于身高的信息,因为二者有一定的关联度,而且独立于测量尺度。
import numpy as np
x=np.random.random(10)
y=np.random.random(10)
#马氏距离要求样本数要大于维数,否则无法求协方差矩阵
#此处进行转置,表示10个样本,每个样本2维
X=np.vstack([x,y])
XT=X.T
#方法一:根据公式求解
S=np.cov(X) #两个维度之间协方差矩阵
SI = np.linalg.inv(S) #协方差矩阵的逆矩阵
#马氏距离计算两个样本之间的距离,此处共有10个样本,两两组合,共有45个距离。
n=XT.shape[0]
d1=[]
for i in range(0,n):
for j in range(i+1,n):
delta=XT[i]-XT[j]
d=np.sqrt(np.dot(np.dot(delta,SI),delta.T))
d1.append(d)
#方法二:根据scipy库求解
from scipy.spatial.distance import pdist
d2=pdist(XT,'mahalanobis')
KL散度又称为相对熵,它是描述对随机变量X的两个概率分布 P P 和 Q Q 差别的非对称性度量,它不满足距离基本性质中的对称性和直递性。特别的,在信息论中, DKL(P(x)||Q(x)) D K L ( P ( x ) | | Q ( x ) ) 表示当概率分布 Q(x) Q ( x ) 来拟合真实分布 P(x) P ( x ) 时,产生的信息损耗。
DKL(P(x)||Q(x))=∑x∈Xln(p(x)q(x))(2.9) (2.9) D K L ( P ( x ) | | Q ( x ) ) = ∑ x ∈ X l n ( p ( x ) q ( x ) )
连续形式如下:
DKL(P(x)||Q(x))=∫∞−∞ln(p(x)q(x))(2.10) (2.10) D K L ( P ( x ) | | Q ( x ) ) = ∫ − ∞ ∞ l n ( p ( x ) q ( x ) )
python实现:
import numpy as np
import scipy.stats
# 随机生成两个离散型分布
x = [np.random.randint(1, 11) for i in range(10)]
print(x)
print(np.sum(x))
px = x / np.sum(x)
print(px)
y = [np.random.randint(1, 11) for i in range(10)]
print(y)
print(np.sum(y))
py = y / np.sum(y)
print(py)
# 利用scipy API进行计算
# scipy计算函数可以处理非归一化情况,因此这里使用
# scipy.stats.entropy(x, y)或scipy.stats.entropy(px, py)均可
KL = scipy.stats.entropy(x, y)
print(KL)
# 编程实现
KL = 0.0
for i in range(10):
KL += px[i] * np.log(px[i] / py[i])
# print(str(px[i]) + ' ' + str(py[i]) + ' ' + str(px[i] * np.log(px[i] / py[i])))
print(KL)
[1]. 周志华,机器学习,清华大学出版社,2016
[2]. 距离度量以及python实现(一)
[3]. python 3计算KL散度(KL Divergence)
<个人网页blog已经上线,一大波干货即将来袭:https://faiculty.com/>
/* 版权声明:公开学习资源,只供线上学习,不可转载,如需转载请联系本人 .*/
QQ交流群:451429116