我已经订购了数字列表(如条形码位置,光谱线),我试图比较相似性。理想情况下,我想比较两个列表,以获得1.0(匹配)优雅降级为0的值。
列表可以偏移任意数量,这不应该降低匹配。相邻项目之间的差异是最适用的特征。
由于系统中存在噪音,某些项目可能会丢失(或者,可能会插入额外的项目,具体取决于观点)。
可以重新排序差异值。
可以缩放diff值。
可以应用上面的多个转换,每个转换都应按比例降低相似性。
以下是一些测试数据:
# deltas
d = [100+(i*10) for i in xrange(10)] # [100, 110, 120, 130, 140, 150, 160, 170, 180, 190]
d_swap = d[:4] + [d[5]] + [d[4]] + d[6:] # [100, 110, 120, 130, 150, 140, 160, 170, 180, 190]
# absolutes
a = [1000+j for j in [0]+[sum(d[:i+1]) for i in xrange(len(d))]] # [1000, 1100, 1210, 1330, 1460, 1600, 1750, 1910, 2080, 2260, 2450]
a_offs = [i+3000 for i in a] # [4000, 4100, 4210, 4330, 4460, 4600, 4750, 4910, 5080, 5260, 5450]
a_rm = a[:2] + a[3:] # [1000, 1100, 1330, 1460, 1600, 1750, 1910, 2080, 2260, 2450]
a_add = a[:7] + [(a[6]+a[7])/2] + a[7:] # [1000, 1100, 1210, 1330, 1460, 1600, 1750, 1830, 1910, 2080, 2260, 2450]
a_swap = [1000+j for j in [0]+[sum(d_swap[:i+1]) for i in xrange(len(d_swap))]] # [1000, 1100, 1210, 1330, 1460, 1610, 1750, 1910, 2080, 2260, 2450]
a_stretch = [1000+j for j in [0]+[int(sum(d[:i+1])*1.1) for i in xrange(len(d))]] # [1000, 1110, 1231, 1363, 1506, 1660, 1825, 2001, 2188, 2386, 2595]
a_squeeze = [1000+j for j in [0]+[int(sum(d[:i+1])*0.9) for i in xrange(len(d))]] # [1000, 1090, 1189, 1297, 1414, 1540, 1675, 1819, 1972, 2134, 2305]
Sim(a,a_offs)应为1.0,因为偏移不被视为惩罚
Sim(a,a_rm)和Sim(a,a_add)应该约为0.91,因为12个中的10个或12个中的11个匹配。
Sim(a,a_swap)应该是大约0.96,因为一个差异不合适(如果移动多个位置,可能会根据距离进一步惩罚)。
Sim(a,a_stretch)和Sim(a,a_squeeze)应该约为0.9,因为差异在10中缩放了大约1个部分。
我正在考虑像difflib.SequenceMatcher
这样的东西,但它适用于具有模糊性的数值而不是硬比较的哈希。它还需要保持对diff(一阶导数)关系的一些认识。
这似乎是一个动态编程问题,但我无法弄清楚如何构建适当的成本指标。