matlab 距离度量,notes/常见距离度量方式.md at master · fly2/notes · GitHub

常见距离度量方式

数值属性的距离度量

闵可夫斯基距离(MInkowski distance)

$\Large dist_{mk}(x_i,x_j)=(\sum_{u=1}^{n}|x_{iu}-x_{ju}|^p)^{\frac{1}{p}}$

欧式距离

当p=2时,闵可夫斯基距离即为欧式距离(Euclidean distance),欧氏距离是最易于理解的一种距离计算方法,源自欧氏空间中两点间的距离公式。

$\Large dist_{ed}(x_i,x_j)=||x_i-x_j||2=\sqrt{\sum{u=1}^{n}|x_{iu}-x_{ju}|^2}$

曼哈顿距离

当p=1时,闵可夫斯基距离即为曼哈顿距离(Manhattan distance),又名城市街区距离,计算两个地点的驾驶距离。

$\Large dist_{man}(x_i,x_j)=||x_i-x_j||1=\sum{u=1}^{n}|x_{iu}-x_{ju}|$

切比雪夫距离

当$p=\infty $时,闵可夫斯基距离即为切比雪夫距离( Chebyshev Distance)。 国际象棋玩过么?国王走一步能够移动到相邻的8个方格中的任意一个。那么国王从格子(x1,y1)走到格子(x2,y2)最少需要多少步?自己走走试试。你会发现最少步数总是max(| x2-x1 | , | y2-y1 | ) 步。有一种类似的一种距离度量方法叫切比雪夫距离。

$\Large dist_{cd}(x_i,x_j)=\lim_{p \to \infty}(\sum_{u=1}^{n}|x_{iu}-x_{ju}|^p)^{\frac{1}{p}}=\max\limits_{1\le u\le n}(|x_{iu}-x_{ju}|)$

马氏距离

有M个样本向量X1~Xm,协方差矩阵记为S,均值记为向量μ,则其中样本向量X到u的马氏距离表示为:

$\Large dist_{md}(X)=\sqrt{(X-\mu)^TS^{-1}(X-\mu)}$

而其中向量$X_i$与$X_j$之间的马氏距离定义为:

$\Large dist_{md}(X_i,X_j)=\sqrt{(X_i-X_j)^TS^{-1}(X_i-X_j)}$

马氏距离的优点:

马氏距离不受量纲的影响,两点之间的马氏距离与原始数据的测量单位无关;由标准化数据和中心化数据(即原始数据与均值之差)计算出的二点之间的马氏距离相同。马氏距离还可以排除变量之间的相关性的干扰。

马氏距离的缺点:

马氏距离夸大了变化微小的变量的作用。

余弦距离

在sklearn中有余弦距离和余弦相似度,余弦相似度即为下面的公式,余弦距离定义为1-余弦相似度。

$$\Large Cos_\theta=\frac{\sum_1^n(x_i y_i)}{\sqrt{\sum_1^n x_i^2}\sqrt{\sum_1^n y_i^2}}$$

余弦值的范围在[-1,1]之间,值越趋近于1,代表两个向量的方向越接近;越趋近于-1,他们的方向越相反;接近于0,表示两个向量近乎于正交。

当在做客户评分相似度比较时,不能直接比较两者的评分,需要比较两者对于均值的偏移值。如下例子:

虽然余弦相似度对个体间存在的偏见可以进行一定的修正,但是因为只能分辨个体在维之间的差异,没法衡量每个维数值的差异,会导致这样一个情况:比如用户对内容评分,5分制,X和Y两个用户对两个内容的评分分别为(1,2)和(4,5),使用余弦相似度得出的结果是0.98,两者极为相似,但从评分上看X似乎不喜欢这2个内容,而Y比较喜欢,余弦相似度对数值的不敏感导致了结果的误差,需要修正这种不合理性,就出现了调整余弦相似度,即所有维度上的数值都减去一个均值,比如X和Y的评分均值都是3,那么调整后为(-2,-1)和(1,2),再用余弦相似度计算,得到-0.8,相似度为负值并且差异不小,但显然更加符合现实。

文本属性的距离度量

编辑距离

编辑距离(Edit Distance),又称Levenshtein距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。一般来说,编辑距离越小,两个串的相似度越大。

import numpy as np

def Levenshtein_distance(str1,str2):

'''

计算编辑距离,用于学习算法,如果大规模计算建议改进或换c/matlab

参数

-----------------------

str1 字符串列表

str2 字符串列表

'''

if str1==None:

return len(str2)

elif str2==None:

return len(str1)

else:

l1=len(str1)

l2=len(str2)

dis =np.zeros([l1+1,l2+1])

dis[0,:]=range(l2+1)

dis[:,0]=range(l1+1)

for i in range(1,l1+1):

for j in range(1,l2+1):

if str1[i-1]==str2[j-1]:

dis[i,j]=dis[i-1,j-1]

else:

dis[i,j]=min(dis[i - 1,j] + 1, dis[i,j - 1] + 1, dis[i - 1,j - 1] + 1)

return dis[l1,l2]

Hamming 距离

汉明距离是使用在数据传输差错控制编码里面的,汉明距离是一个概念,它表示两个(相同长度)字对应位不同的数量,我们以d(x,y)表示两个字x,y之间的汉明距离。对两个字符串进行异或运算,并统计结果为1的个数,那么这个数就是汉明距离。

def hamming(s1, s2):

"""

返回两个等长的字符串的Hamming相似度

参数

--------------------------------

s1 字符串1

s2 字符串2

"""

if len(s1) != len(s2):

raise ValueError("Undefined for sequences of unequal length")

return sum(el1 != el2 for el1, el2 in zip(s1, s2))

Jaro-Winkler距离

在计算机科学和统计学中,Jaro-Winkler距离是测量两个序列之间编辑距离的字符串度量。它是由威廉E.温克勒于1990年提出的Jaro距离度量(1989,Matthew A.Jaro)的一个变体。非正式地说,两个单词之间的Jaro距离是将一个单词换成另一个单词所需的单个字符换位的最小数量。

$$

\Large d_j=

\left{

\begin{array}{lcl}

\frac{1}{3}(\frac{m}{|s_1|}+\frac{m}{|s_2|}+\frac{m-t}{m}) & &m\neq0 \

0&&m=0\

\end{array} \right.

$$

$|s_i|$是字符串$s_i$的长度

m 是两个字符串匹配字符的数量

t 是换位数目的一半

其中t换位数目表示:两个分别来自S1和S2的字符如果相距不超过

$$

\Large |\frac{max(|s_1|,|s_2|)}{2}-1|

$$

我们就认为这两个字符串是匹配的;而这些相互匹配的字符则决定了换位的数目t,简单来说就是不同顺序的匹配字符的数目的一半即为换位的数目t,举例来说,MARTHA与MARHTA的字符都是匹配的,但是这些匹配的字符中,T和H要换位才能把MARTHA变为MARHTA,那么T和H就是不同的顺序的匹配字符,t=2/2=1。

而Jaro-Winkler则给予了起始部分就相同的字符串更高的分数,他定义了一个前缀权重p,给予两个字符串,如果前缀部分有长度为$l$ 的部分相同,则Jaro-Winkler Distance为:

$$

\Large d_w=d_j+(lp(1-d_j))

$$

$d_j$是两个字符串的Jaro Distance

l是前缀的相同的长度,但是规定最大为4

$p$则是调整分数的常数,规定不能超过0.25,不然可能出现dw大于1的情况,Winkler将这个常数定义为0.1

def Jaro_Winkler(string1, string2,is_jaro=False):

"""

计算jaro或jaro winkler相似度

参数

-------------------------------------------------

string1 字符串1

string2 字符串2

is_jaro 是否使用jaro,默认为False,使用jaro_winkler

返回

--------------------------------------------------

string1和string2的jaro相似度

"""

len_str1 = len(string1)

len_str2 = len(string2)

if len_str1==0 or len_str2==0:

return 0

max_len = max(len_str1, len_str2)

search_range =(max_len // 2) - 1

if search_range < 0:

search_range = 0

#定义两个字符串的匹配标记

flags_s1 = np.zeros(len_str1, dtype=np.int32)

flags_s2 = np.zeros(len_str2, dtype=np.int32)

common_chars = 0

low = 0

high = 0

i = 0

j = 0

#找到两个字符串的共有字符

for i in range(0,len_str1):

low = i - search_range if i > search_range else 0

high = i + search_range if i + search_range < len_str2 else len_str2 - 1

for j in range(low,high+1):

if flags_s2[j]==0 and string2[j]==string1[i]:

flags_s1[i]=flags_s2[j]=1

common_chars=common_chars+1

break

if common_chars == 0:

return 0

#需要变换的位数

trans_count = 0

#已经匹配过的字符位数

k = 0

#得到需要变换的位数

for i in range(0,len_str1):

if flags_s1[i]==1:

for j in range(k,len_str2):

if flags_s2[j]==1:

k=j+1

break

if string1[i]!=string2[j]:

trans_count=trans_count+1

trans_count =trans_count // 2

sim = (common_chars / len_str1 + common_chars / len_str2 +

(common_chars - trans_count) / common_chars) / 3

if is_jaro==False:

ms1=''

for i in range(len_str1):

if flags_s1[i]==1:

ms1=''+string1[i]

ms2=''

for j in range(len_str2):

if flags_s2[j]==1:

ms2=''+string2[j]

#字符串共有前缀

prefix = 0

for mi in range(len(ms1)):

if ms1[mi]==ms2[mi]:

prefix=prefix+1

sim=sim+prefix*0.1*(1-sim)

return sim

Jaccard 相似度

用于比较有限样本集之间的相似性与差异性。Jaccard系数值越大,样本相似度越高。

$\Large J(A,B)=\frac{|A\bigcap B|}{|A\bigcup B|}$

jaccard距离

Jaccard distance (A, B) = 1 - Jaccard(A, B)

下面提供两种计算jaccard相似度的方法,一种不考虑重复项,一种考虑重复项。

不考虑重复项公式如上。

考虑重复项时将jaccard变为乘法:

$\Large J(A,B)=\frac{|\sum_{i\in A }dA_idB_i|}{|A| \times |B|}$

$dA_i,dB_i$分别表示集合A和集合B中的词i的出现次数

def jaccard(str1,str2):

'''

计算jaccard相似度,不考虑str中是否有重复项

参数

-----------------

str1 字符串列表

str2 字符串列表

'''

return len((set(a)&set(b)))/len((set(a)|set(b)))

from collections import Counter

def jaccard_times(str1,str2):

'''

计算jaccard相似度,考虑str中的重复项

参数

----------------

str1 字符串列表

str2 字符串列表

'''

c1=Counter(str1)

c2=Counter(str2)

s=0

for i in c1.keys():

s=s+c1.get(i,0)*c2.get(i,0)

return s/(len(c1)*len(c2))

TextDistance使用记录

一个计算文本距离的包

Algorithms

Edit based

Algorithm

Class

Functions

Hamming

hamming

Mlipns

mlipns

Levenshtein

levenshtein

DamerauLevenshtein

damerau_levenshtein

JaroWinkler

jaro_winkler, jaro

StrCmp95

strcmp95

NeedlemanWunsch

needleman_wunsch

Gotoh

gotoh

SmithWaterman

smith_waterman

Token based

Algorithm

Class

Functions

Jaccard

jaccard

Sorensen

sorensen, sorensen_dice, dice

Tversky

tversky

MongeElkan

monge_elkan

Sequence based

Compression based

Work in progress. Now all algorithms compare two strings as array of bits, not by chars.

NCD - normalized compression distance.

Functions:

bz2_ncd

lzma_ncd

arith_ncd

rle_ncd

bwtrle_ncd

zlib_ncd

Phonetic

Algorithm

Class

Functions

MRA

mra

Editex

editex

Simple

Algorithm

Class

Functions

Prefix similarity

Prefix

prefix

Postfix similarity

Postfix

postfix

Length distance

Length

length

Identity similarity

Identity

identity

Matrix similarity

Matrix

matrix

Installation

Stable:

pip install textdistance

Dev:

pip install -e git+https://github.com/orsinium/textdistance.git#egg=textdistance

Usage

All algorithms have 2 interfaces:

Class with algorithm-specific params for customizing.

Class instance with default params for quick and simple usage.

All algorithms have some common methods:

.distance(*sequences) -- calculate distance between sequences.

.similarity(*sequences) -- calculate similarity for sequences.

.maximum(*sequences) -- maximum possible value for distance and similarity. For any sequence: distance + similarity == maximum.

.normalized_distance(*sequences) -- normalized distance between sequences. The return value is a float between 0 and 1, where 0 means equal, and 1 totally different.

.normalized_similarity(*sequences) -- normalized similarity for sequences. The return value is a float between 0 and 1, where 0 means totally different, and 1 equal.

Most common init arguments:

qval-- q-value for split sequences into q-grams. Possible values:

1 (default) -- compare sequences by chars.

2 or more -- transform sequences to q-grams.

None -- split sequences by words.

as_set-- for token-based algorithms:

True -- t and ttt is equal.

False (default) -- t and ttt is different.

Example

import textdistance

textdistance.hamming('test', 'text')

# 1

textdistance.hamming.distance('test', 'text')

# 1

textdistance.hamming.similarity('test', 'text')

# 3

textdistance.hamming.normalized_distance('test', 'text')

# 0.25

textdistance.hamming.normalized_similarity('test', 'text')

# 0.75

textdistance.Hamming(qval=2).distance('test', 'text')

# 2

>>> textdistance.Hamming.similarity(['test'],['text'])

0

>>> textdistance.Hamming.similarity(['text','abc'],['text'])

1

Any other algorithms have same interface.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值