如何计算两个数值数组的相似度?SequenceMatcher结果存疑求替代方案
数值数组趋势相似度检测方案
问题背景
你拥有两个数值数组x和y,尝试用difflib.SequenceMatcher计算相似度得到39.33%,但从可视化图表来看两个数组趋势高度相似,结果与直观感受不符,需要适合的数值序列相似度检测方法、实现及数学原理。
为什么SequenceMatcher结果不符合预期?
difflib.SequenceMatcher是为字符串或离散元素序列设计的工具,它的相似度计算核心是统计相同位置元素完全匹配的比例。而你的数组是数值序列,趋势相似但具体数值存在差异,用它来计算自然会得到和直观感受不符的低相似度结果——它根本不适合衡量数值序列的趋势相关性。
适合的相似度检测方法及实现
1. 皮尔逊相关系数(Pearson Correlation Coefficient)
数学原理
衡量两个变量之间的线性相关程度,取值范围为[-1, 1]:
- 接近1:两个序列线性趋势高度一致
- 接近0:无线性相关性
- 接近-1:线性趋势完全相反
代码实现
import numpy as np # 你的原始数组 x = np.array([ 0., 0., 84., 80., 59., 22., 0., 0., 0., 0., 52., 122., 117., 1., 10., 0., 0., 0., 0., 0., 0., 92., 90., 74., 46., 0., 0., 0., 0., 28., 121., 117., 90., 54., 0., 0., 0., 0., 0., 0., 47., 62., 54., 57., 23., 63., 26., 62., 52., 138., 126., 98., 0., 0., 0., 0., 0., 0., 0., 0., 0., 19., 44., 74., 89., 119., 77., 141., 137., 119., 0., 0., 0., 0., 91., 115., 89., 143., 146., 45., 0., 0., 0., 65., 89., 1., 0., 0., 0.]) y = np.array([ 0., 0., 79., 90., 64., 3., 0., 0., 0., 0., 19., 113., 109., 1., 25., 0., 0., 0., 0., 0., 0., 90., 99., 73., 35., 0., 0., 0., 0., 46., 106., 113., 105., 52., 0., 0., 0., 0., 0., 0., 57., 68., 47., 20., 0., 17., 1., 14., 48., 120., 118., 105., 0., 0., 0., 0., 0., 0., 4., 1., 0., 0., 0., 42., 47., 80., 86., 125., 121., 111., 16., 0., 0., 0., 47., 72., 112., 123., 129., 82., 0., 0., 0., 87., 80., 0., 0., 5., 0.]) pearson_corr = np.corrcoef(x, y)[0, 1] print(f"皮尔逊相关系数: {round(pearson_corr, 4)}")
结果解释
针对你的数组,计算得到的皮尔逊相关系数会非常接近1,这和你看到的趋势高度一致的可视化结果完全匹配。
2. 余弦相似度(Cosine Similarity)
数学原理
将两个数组视为高维空间中的向量,计算它们之间夹角的余弦值,取值范围为[-1, 1]:
- 接近1:向量方向几乎一致,即序列的相对变化趋势高度相似
- 不关注数值的绝对值大小,只关注趋势的相对变化
代码实现
import numpy as np def cosine_similarity(a, b): dot_product = np.dot(a, b) norm_a = np.linalg.norm(a) norm_b = np.linalg.norm(b) return dot_product / (norm_a * norm_b) cos_sim = cosine_similarity(x, y) print(f"余弦相似度: {round(cos_sim, 4)}")
3. 动态时间规整(Dynamic Time Warping, DTW)
数学原理
专门针对时间序列(或有序数值序列)的相似度计算方法,允许通过动态对齐两个序列中的相似趋势片段(即使位置有轻微偏移),计算对齐后的累计距离,距离越小说明序列越相似。适合处理趋势相似但存在局部时间偏移的序列。
代码实现
先安装依赖库:pip install fastdtw
import numpy as np from scipy.spatial.distance import euclidean from fastdtw import fastdtw distance, _ = fastdtw(x, y, dist=euclidean) # 将距离归一化为0-1区间的相似度值 max_possible_dist = np.sqrt(len(x)) * max(np.max(x), np.max(y)) dtw_similarity = 1 - (distance / max_possible_dist) print(f"DTW归一化相似度: {round(dtw_similarity, 4)}")
内容的提问来源于stack exchange,提问作者stack offer
相关产品推荐
相关产品推荐

