对数字集的相似度进行评分的算法

时间:2020-03-06 14:47:12  来源:igfitidea点击:

有什么算法可以将多组数字与目标集进行比较,以确定哪些数字最"相似"?

该算法的一种用途是将今天的每小时天气预报与历史天气预报记录进行比较,以找到天气相似的一天。

两组的相似性有点主观,因此算法实际上只需要区分好匹配和坏匹配。我们有很多历史数据,因此我想通过自动抛出不接近的数据集并尝试将"最佳"匹配项放在用户的顶部来缩小用户需要浏览的天数列表。

编辑:
理想情况下,该算法的结果可以与使用不同数据集的结果进行比较。例如,使用Niles建议的均方误差会产生很好的结果,但是由于温度的大小不同,因此无法将比较温度时生成的数字与使用其他数据(例如"风速"或者"降水")生成的数字进行比较。一些非天气数据非常大,因此与使用温度生成的数万或者数百相比,均方误差算法生成的数以万计的数字。

解决方案

首先,问问自己这些是集合还是有序集合。

我假设这些是重复的有序集合。最明显的算法是选择一个公差,在该公差内数字被认为是相同的,并在该度量下计算数字相同的插槽数。

我认为均方误差指标可能适用于诸如天气比较之类的应用。它很容易计算并给出有意义的数字。

由于我们想随时间比较测量结果,因此可以从计算中忽略缺失值。

对于没有时间限制甚至没有排序的值,多维散点数据会有些困难。选择良好的距离度量成为分析此类数据的技术的一部分。

在金融中,他们使用Beta来测量2个数字序列的相关性。例如,Beta可以回答以下问题:"在过去的一年中,如果S&P 500指数的价格上涨5%,那么IBM的价格会上涨多少?"它处理移动百分比,因此2个系列可以具有不同的比例。

在我的示例中,Beta是协方差(IBM,S&P 500)/方差(S&P 500)。

维基百科上有解释协方差,方差和Beta的页面:http://en.wikipedia.org/wiki/Beta_(finance)

看统计站点。我认为我们正在寻找相关性。

我确实在我的应用程序中为此实现了一个解决方案,但是我正在寻找是否存在更好或者更"正确"的东西。对于每个历史日,我都会执行以下操作:

function calculate_score(historical_set, forecast_set)
{
    double c = correlation(historical_set, forecast_set);
    double avg_history = average(historical_set);
    double avg_forecast = average(forecast_set);
    double penalty = abs(avg_history - avg_forecast) / avg_forecast
    return c - penalty;
}

然后,我将所有结果从高到低排序。

由于相关性是一个从-1到1的值,表示数字是一起下降还是一起上升,因此我用百分比差对这两组数字的平均值进行"惩罚"。

举例来说,我假设我们正在测量温度,风向和降水。我们将这些项目称为"功能"。因此,有效值可能是:

  • 温度:-50至100F(我在美国明尼苏达州)
  • 风:0到120英里/小时(不确定这是否切合实际,但请忍受)
  • 沉淀:0至100

首先规范化数据。 Temp的范围是150个单位,Wind的范围是120个单位,Precip的范围是100个单位。将风单位乘以1.25,将Precip乘以1.5,以使其与温度大致相同。我们可以在这里花哨的地方,制定权衡一个功能比其他功能更有价值的规则。在此示例中,风的范围可能很大,但通常保持在较小的范围内,因此我们希望减轻其重量以防止其影响结果。

现在,将每个测量想象为多维空间中的一个点。本示例测量3d空间(温度,风,降水)。令人高兴的是,如果我们添加更多功能,我们只是增加了空间的维数,而数学却保持不变。无论如何,我们想找到最接近我们当前点的历史点。最简单的方法是欧几里得距离。因此,测量从我们当前点到每个历史点的距离,并保持最接近的匹配:

for each historicalpoint

    distance = sqrt(
        pow(currentpoint.temp - historicalpoint.temp, 2) + 
        pow(currentpoint.wind - historicalpoint.wind, 2) +
        pow(currentpoint.precip - historicalpoint.precip, 2))

    if distance is smaller than the largest distance in our match collection
        add historicalpoint to our match collection
        remove the match with the largest distance from our match collection

next

这是一种蛮力的方法。如果有时间,我们可以得到很多爱好者。多维数据可以表示为kd树或者r树之类的树。如果我们有大量数据,那么将当前观察值与每个历史观察值进行比较会太慢。树木加快了搜索速度。我们可能想看看数据集群和最近邻居搜索。

干杯。

几次,我们提到我们不知道数据的分布,这是正确的。我的意思是,明天可能会有华氏150度,有2000km / hr的风,但是似乎不太可能。

我认为我们对分配非常了解,因为我们有很长的历史记录。鉴于此,我们可以将所有内容都放在历史分布的分位数上,并在所有度量上使用分位数的绝对或者平方差来执行某些操作。这是另一种归一化方法,但是它解决了数据中的非线性问题。

任何样式的规范化都应使所有变量具有可比性。

例如,假设一天是刮风,炎热的一天:温度分位数为.75,风分位数为.75. 用于热量的.76分位数可能相距1度,而用于风的分位数可能相距3kmh。

对经验分布的关注也很容易理解,并且可能比正态估计(如均方误差)更强健。

与统计学家交谈。

严重地。

他们以这种事情为生。

我们写道"两组的相似性有点主观",但它不是主观的,这是确定问题领域相似性的适当标准的问题。

在这种情况下,与专业人士交谈比问一群程序员要好得多。

使用皮尔逊相关系数。我想出了如何在SQL查询中计算该值的方法:http://vanheusden.com/misc/pearson.php

这两个数据集是否有序?

如果订购,索引是否相同?等距?

如果这些指标是通用的(例如,在同一天(但位置不同)测得的温度),则可以将第一个数据集与第二个数据集进行回归,
然后测试斜率等于1,并且截距为0。
http://stattrek.com/AP-Statistics-4/Test-Slope.aspx?Tutorial=AP

否则,我们可以对y = values对其索引进行两次回归。 http://en.wikipedia.org/wiki/Correlation。我们仍然想要比较斜率和截距。

====

如果无序,我想我们想看看累积分布函数
http://en.wikipedia.org/wiki/Cumulative_distribution_function

一个相关的测试是Kolmogorov-Smirnov:
http://en.wikipedia.org/wiki/Kolmogorov-Smirnov_test

你也可以看看

学生的t检验,
http://en.wikipedia.org/wiki/Student%27s_t-test

或者Wilcoxon签名等级测试http://en.wikipedia.org/wiki/Wilcoxon_signed-rank_test

测试两个样本之间均值的均等性。

我们可以使用Levene检验http://www.itl.nist.gov/div898/handbook/eda/section3/eda35a.htm来检验方差是否相等

注意:不同的数据集可能具有相同的均值和方差-根据我们想要的严格程度(以及我们拥有多少数据),我们也可以考虑测试较高矩是否相等。