2010-10-31 102 views
7

在相似性度量和距离度量之间转换是否有一种通用方法?如何在相似性度量和差异度量之间进行转换?

考虑一个相似性度量,比如两个字符串共有的2克数。

2-grams('beta', 'delta') = 1 
2-grams('apple', 'dappled') = 4 

如果我需要这个喂到预期差异的措施,如Levenshtein距离的优化算法?

这只是一个例子......我在寻找一个通用的解决方案,如果存在的话。就像如何从Levenshtein距离到相似性的度量?

我很感谢您可能提供的任何指导。

+3

我很想知道你的问题是否要求距离服从[三角不等式](http://en.wikipedia.org/wiki/Triangle_inequality),如果是的话,你认为哪些解决方案最令人满意。 – 2012-11-29 17:20:20

回答

1
similarity = 1/difference 

并观看了difference = 0

+7

所以你可以尝试'相似度= 1 /(差异+ 1)' – 2010-10-31 19:45:37

+0

这是有道理的...谢谢。 – 135498 2010-11-01 23:15:46

0

在Levenshtein距离的情况下,可以以1为每次序列比赛增加了SIM卡的分数;也就是说,每次您不需要删除,插入或替换时,都是1。这样,度量将是两个字符串共有多少个字符的线性度量。

2

如果你的相似度(S)为0和1之间,你可以使用其中的一个:

1-s 
sqrt(1-s) 
-log(s) 
(1/s)-1 
0

在我的项目之一(基于协同过滤),我不得不相关之间的转换(余弦在向量之间),从-1到1(更接近1更接近-1,更接近-1更加多样化)到归一化距离(接近0,距离更小并且接近1,距离更大)

在这种情况下:距离〜多样性

我为穆拉是:dist = 1 - (cor + 1)/2

如果你有相似的多样性和域为[0,1]在这两种情况下的simlest方法是:

dist = 1 - sim

sim = 1 - dist

4

做1 /相似度不会保留分配的属性。

最好的方法是 距离(a-> b)=最高相似度 - 相似度(a-> b)。具有最高相似度的 是具有最大值的相似度距离。您因此翻转您的分配。 最高相似度变为0等

9

d表示距离,小号表示相似性。到距离测量转换成相似性度量,我们首先需要正常化d为[0 1],通过使用d_norm = d /最高(d)。然后,相似性度量由下式给出:

s = 1-d_norm

其中s在[0 1]的范围内,其中1表示最高相似度(比较项目相同),0表示最低相似度(最大距离)。

0

Cosine similaritywidely used用于n克计数或TFIDF载体。

from math import pi, acos 
def similarity(x, y): 
    return sum(x[k] * y[k] for k in x if k in y)/sum(v**2 for v in x.values())**.5/sum(v**2 for v in y.values())**.5 

余弦相似性可以被用于计算一个正式的距离度量according to wikipedia。它遵循,你会期望的距离(对称,非负性,等等)的所有属性:

def distance_metric(x, y): 
    return 1 - 2 * acos(similarity(x, y))/pi 

这些度量的两个范围0和1之间

如果你有tokenizer产生N-从字符串克,你可以使用这些指标是这样的:

>>> import Tokenizer 
>>> tokenizer = Tokenizer(ngrams=2, lower=True, nonwords_set=set(['hello', 'and'])) 

>>> from Collections import Counter 
>>> list(tokenizer('Hello World again and again?')) 
['world', 'again', 'again', 'world again', 'again again'] 
>>> Counter(tokenizer('Hello World again and again?')) 
Counter({'again': 2, 'world': 1, 'again again': 1, 'world again': 1}) 
>>> x = _ 
>>> Counter(tokenizer('Hi world once again.')) 
Counter({'again': 1, 'world once': 1, 'hi': 1, 'once again': 1, 'world': 1, 'hi world': 1, 'once': 1}) 
>>> y = _ 
>>> sum(x[k]*y[k] for k in x if k in y)/sum(v**2 for v in x.values())**.5/sum(v**2 for v in y.values())**.5 
0.42857142857142855 
>>> distance_metric(x, y) 
0.28196592805724774 

我发现Counter优雅的内积this SO answer

相关问题