参考大神连接1: https://www.jianshu.com/p/c30bb865429e
参考大神连接2: https://zhuanlan.zhihu.com/p/46626607
因为需要对数据距离进行判定,记录一下自己的学习。
在大数据的年代,我们难免要对数据进行处理,我们可能需要从一堆数据中找到一些相似的数据,然后归成一类,或者需要对比两堆数据的相似度等等,用此来找到我们需要的数据。
衡量的方式一般有通过数据距离的远近进行判断的,还有通过数据分布的相似度进行判断的,下面将就这两种方式进行学习。
距离的判定
欧式距离
欧式距离就是我们大家较为熟悉的距离度量,也就是我们常说的
L
2
L2
L2距离,通过衡量两个数据点各个维度绝对距离的远近,来衡量数据的相似度。
公式如下:
d
i
s
t
a
n
c
e
=
∑
i
=
0
n
(
x
i
−
y
i
)
2
distance= \sqrt{\sum_{i=0}^n(x_i - y_i)^2}
distance=i=0∑n(xi−yi)2
代码编写如下:
from math import sqrt
def Euclidean_distance(x,y):
distance = 0
# 使用zip函数将同一个序号对应的x,y绑定起来
for i,j in zip(x,y):
distance += pow(i-j,2)
distance = sqrt(distance)
return distance
distance = Euclidean_distance([1,1,1],[1,0,0])
print(distance)
# 结果:1.4142135623730951
曼哈顿距离
曼哈顿距离可能名称我们稍微陌生一点,但是要是提起来
L
1
L1
L1距离,那么大家可能就更加熟悉,曼哈顿距离描述的是:在多个维度上的绝对距离进行求和后的结果。
公式如下:
d
i
s
t
a
n
c
e
=
∑
i
=
0
n
∣
x
i
−
y
i
∣
distance= \sum_{i=0}^n \lvert{x_i - y_i}\rvert
distance=i=0∑n∣xi−yi∣
代码编写如下:
def manhatton_distance(x,y):
distance = 0
for i,j in zip(x,y):
# 使用求和函数sum同理
distance += abs(i-j)
return distance
distance = manhatton_distance([1,1,1],[1,0,2])
print(distance)
# 结果:2
切比雪夫距离
切比雪夫距离(Chebyshev distance)或是
L
∞
L∞
L∞度量,是向量空间中的一种度量,二个点之间的距离定义是其各坐标数值差绝对值的最大值。
公式如下:
d
i
s
t
a
n
c
e
=
lim
p
→
∞
(
∑
i
=
0
n
∣
x
i
−
y
i
∣
p
)
1
/
p
distance= {\lim_{p \to \infty}} \left(\sum_{i=0}^n {\lvert{x_i - y_i}\rvert }^p \right)^{1/p}
distance=p→∞lim(i=0∑n∣xi−yi∣p)1/p
当
p
→
∞
p\to \infty
p→∞的时候,我们会发现,两者之前的距离就等于所有维度上的绝对距离中最大的,(从公式当中提出那个最大的绝对值,会发现剩余的趋向于零)
代码编写如下:
import numpy as np
def chebyshev_distance(x,y):
return abs(x-y).max()
distance = chebyshev_distance(np.array([1,2,3]),np.array([2,4,6]))
print(distance)
# 结果:3
明可夫斯基距离
看完上面三个距离公式,是否可以发现他们有种相似性,如果用一个通用公式来表示上面三个公式的话,就形成了明可夫斯基距离。明可夫斯基距离又称明氏距离,是欧氏空间中的一种测度,被看做是欧氏距离和曼哈顿距离的一种推广。
公式如下:
d
i
s
t
a
n
c
e
=
(
∑
i
=
0
n
∣
x
i
−
y
i
∣
k
)
1
/
k
distance= \left(\sum_{i=0}^n {\lvert{x_i - y_i}\rvert }^k \right)^{1/k}
distance=(i=0∑n∣xi−yi∣k)1/k
1、当
k
=
1
k = 1
k=1的时候,退化为曼哈顿距离。
2、当
k
=
2
k = 2
k=2 的时候,退化为欧式距离。
3、当
k
→
∞
{k \to \infty}
k→∞的时候,变成了切比雪夫距离。
代码编写如下:
import numpy as np
from scipy.spatial.distance import pdist
def minkowski_distance(x, y, p):
# pdist函数是对一个矩阵的每一行进行距离运算
# 所以我们需要先使用np.vstack函数按垂直方向(行顺序)堆叠数组构成一个新的数组
return pdist(np.vstack((x, y)), 'minkowski', p=p)
print(minkowski_distance([1,1,1],[1,0,2],1))
# 结果:2.
pdis是一个很强大的计算距离的函数。通过改变参数p我们能够变成上述曼哈顿距离、欧式距离以及切比雪夫距离,还有很多其他的标准距离函数等。
马氏距离
当考虑各个维度的尺度不一样的时候,我们上述单纯的考虑各个维度的距离问题就容易造成衡量的结果不理想的情况,假设身高的单位是毫米,体重的单位为
k
g
kg
kg,这样的情况下,身高稍微变化一点都会造成距离变化很大,而体重虽然在现实里面变化很大,但在计算差值的时候,却显得不那么明显(因为单位大),
为了解决上述问题,提出了马氏距离,可以看作是欧氏距离的一种修正,修正了欧式距离中各个维度尺度不一致且相关的问题。关于马氏距离为什么会比欧式距离好很多,可以浏览大神连接。
公式如下:
单个数据点的马氏距离
M
D
(
x
,
y
)
=
(
x
−
μ
)
T
∑
−
1
(
x
−
μ
)
M_D(x,y)= \sqrt{(x-\mu)^T \textstyle{\sum ^{-1}}(x - \mu)}
MD(x,y)=(x−μ)T∑−1(x−μ)
数据点x, y之间的马氏距离
M
D
(
x
,
y
)
=
(
x
−
y
)
T
∑
−
1
(
x
−
y
)
M_D(x,y)= \sqrt{(x-y)^T \textstyle{\sum ^{-1}}(x - y)}
MD(x,y)=(x−y)T∑−1(x−y)
协方差为:
c
o
v
(
x
i
,
y
j
)
=
∑
i
=
1
n
(
x
i
−
x
‾
)
(
y
i
−
y
‾
)
n
−
1
cov(x_i,y_j) = \frac{\sum_{i=1}^n{(x_i-\overline{x})(y_i-\overline{y})}}{n-1}
cov(xi,yj)=n−1∑i=1n(xi−x)(yi−y)
协方差矩阵为:(在维度较多的情况下,有多个协方差矩阵)
∑
=
∑
i
=
1
n
∑
j
=
1
n
c
o
v
(
x
i
,
y
j
)
\sum = \sum_{i=1}^n\sum_{j=1}^ncov(x_i,y_j)
∑=i=1∑nj=1∑ncov(xi,yj)
其中Σ是多维随机变量的协方差矩阵,μ为样本均值,如果协方差矩阵是单位向量,也就是各维度独立同分布,马氏距离就变成了欧氏距离。
代码编写如下:
import numpy as np
from scipy.spatial.distance import pdist
def Mahalanobis_distance(x,y):
X=np.vstack([x,y])
XT=X.T
d2=pdist(XT,'mahalanobis')
return d2
汉明距离
两个等长字符串s1与s2之间的汉明距离定义为将其中一个变为另外一个所需要作的最小替换次数。例如字符串“1111”与“1001”之间的汉明距离为2。
from scipy.spatial.distance import pdist
def hamming_distance(x, y):
# 点与点的汉明距离
return pdist(np.vstack((x, y)), 'hamming')
相似度的判定
相似度判断更加注重两个向量在方向上的差异,而非距离或长度上。
余弦相似度
主要判断两个向量在方向上的差异性,通过判断向量之间的余弦值俩判断数据的相似度。
公式如下:
c
o
s
(
θ
)
=
(
A
B
)
∣
A
∣
∣
B
∣
=
∑
i
=
1
n
A
i
B
i
∑
i
=
1
n
(
A
i
)
2
×
∑
i
=
1
n
(
B
i
)
2
cos(\theta) = \frac{(AB)}{\vert{A}\vert\vert{B}\vert} = \frac{\textstyle{\sum_{i=1}^n}{A_i}{B_i}}{\sqrt{\textstyle{\sum_{i=1}^n{(A_i)}^2}}\times {\sqrt{\textstyle{\sum_{i=1}^n{(B_i)}^2}}}}
cos(θ)=∣A∣∣B∣(AB)=∑i=1n(Ai)2×∑i=1n(Bi)2∑i=1nAiBi
代码编写如下:
import numpy as np
from scipy.spatial.distance import pdist
def Cosine_distance(x, y):
# 点与点的夹角余弦距离
return pdist(np.vstack((x, y)), 'cosine')
皮尔森相关系数
皮尔逊相关系数,又称皮尔逊积矩相关系数,是用于度量两个变量X和Y之间的相关(线性相关),其值介于-1与1之间。
公式如下:
β
x
,
y
=
c
o
v
(
X
,
Y
)
σ
X
σ
Y
=
∑
i
=
1
n
(
X
i
−
X
‾
)
(
Y
i
−
Y
‾
)
∑
i
=
1
n
(
X
i
−
X
‾
)
2
×
∑
i
=
1
n
(
Y
i
−
Y
‾
)
2
\beta_{x,y} = \frac{cov(X,Y)}{\sigma_X\sigma_Y} = \frac{\textstyle{\sum_{i=1}^n}{(X_i-\overline{X})(Y_i-\overline{Y})}}{\sqrt{\textstyle{\sum_{i=1}^n{(X_i-\overline{X})}^2}}\times {\sqrt{\textstyle{\sum_{i=1}^n{(Y_i-\overline{Y})}^2}}}}
βx,y=σXσYcov(X,Y)=∑i=1n(Xi−X)2×∑i=1n(Yi−Y)2∑i=1n(Xi−X)(Yi−Y)
代码编写如下:
from scipy.stats import pearsonr
print(pearsonr([1,2,3,4],[5,6,7,8]))
# 输出 r p
r: 相关系数 [-1,1]之间,p-value: p值。 p值越小,表示相关系数越显著。
#结果 1 , 0
Jaccard相似系数
Jaccard系数主要用于计算符号度量或布尔值度量的个体间的相似度,因为个体的特征属性都是由符号度量或者布尔值标识,因此无法衡量差异具体值的大小,只能获得“是否相同”这个结果,所以Jaccard系数只关心个体间共同具有的特征是否一致这个问题。如果比较X与Y的Jaccard相似系数,只比较xn和yn中相同的个数。
公式如下:
相似系数:
J
(
A
,
B
)
=
∣
A
∩
B
∣
∣
A
∪
B
∣
J(A,B) = \frac{\vert{A\cap B}\vert}{\vert{A\cup B}\vert}
J(A,B)=∣A∪B∣∣A∩B∣
杰卡德距离:
J
δ
(
A
,
B
)
=
1
−
J
(
A
,
B
)
=
∣
A
∪
B
∣
−
∣
A
∩
B
∣
∣
A
∪
B
∣
J_\delta(A,B) =1-J(A,B)= \frac{{\vert{A\cup B}\vert}-{\vert{A\cap B}\vert}}{\vert{A\cup B}\vert}
Jδ(A,B)=1−J(A,B)=∣A∪B∣∣A∪B∣−∣A∩B∣
代码编写如下:
from scipy.spatial.distance import pdist
def jaccard_similarity_coefficient(x, y):
# 点与点的杰卡德距离
return pdist(np.array([x, y]), 'jaccard')