仅通过知道级别数来识别一维数据的级别

recognize the levels of 1D data by only knowing the number of levels

我有一个输出数据由一个属性(单值)组成的传感器。排序数据打孔示例如下:

示例: 199 200 205 209 217 224 239 498 573 583 583 590 591 594 703 710 711 717 719 721 836 840 845 849 855 855 856 857 858 858 928 935 936 936 942 943 964 977

可以看到第一张图片的数据input.

数据分为等级。级别数是为我提供的(本例中为 5 个级别)。但是,每一层的样本数量是未知的,层与层之间的距离也是未知的。

我需要排除异常值并定义每个级别的中心(看第二张图输出

红色样本代表离群值,黄色代表水平中心)。有什么算法、数学公式、c++代码可以帮我实现这个要求吗?

我尝试了 KMeans(在此示例中 K = 5),但由于随机初始 K 质心,我得到了不好的结果。大多数情况下,一些初始质心共享同一级别,使该级别成为两个集群,而其他两个级别属于一个集群。如果我通过从每个级别选择一个质心来手动设置初始质心,我会得到很好的结果。

如果两个连续数据点之间的差异大于特定值(将其视为 Delta ),则它属于不同的集群。

for this data set : 199 200 205 209 217 224 239 498 573 583 583 590 591 594 703 710 711 717 719 721 836 840 845 849 855 855 856 857 858 858 928 935 936 936 942 943 964 977

假设 delta 为 15(根据传感器微调)如果连续数据点差异不大于 15,则它们属于同一集群。您可以通过找到集群的中间值来找到中心点。 如果点附近的点与 delta 的差异那么它可以被认为是离群值。另一种选择是我们可以根据数据集的当前值改变 delta。

这是@KarthikeyanMV 答案的扩展。 +1。是的,您需要能够确定 Delta 的值。这是一个可以做到这一点的过程。我正在用 R 编写代码,但我认为过程会很清楚。

大概是组间的差距比任何组内的差距都大,所以只看连续点之间的差异,问哪里差距大。既然你认为应该有5组,那么应该有4个大的差距,所以看第4大的差异。

## Your data
dat = c(199, 200, 205, 209, 217, 224, 239, 498, 573, 583, 
    583, 590, 591, 594, 703, 710, 711, 717, 719, 721, 
    836, 840, 845, 849, 855, 855, 856, 857, 858, 858, 
    928, 935, 936, 936, 942, 943, 964, 977)
(Delta = sort(diff(dat), decreasing=TRUE)[4])
[1] 75

看起来 Delta 应该是 75,但我们没有考虑异常值。 上方的下一个点和下方下方的下一个点是否有大于 Delta 的点?是的。

BigGaps = diff(dat) >= Delta
(Outliers = which(c(BigGaps, T) & c(T, BigGaps)))
[1] 8

点 8 太远,不属于上面或下面的组。因此,让我们将其删除并重试。

dat = dat[-Outliers]
(Delta = sort(diff(dat), decreasing=TRUE)[4])
[1] 70
BigGaps = diff(dat) >= Delta
(Outliers = which(c(BigGaps, T) & c(T, BigGaps)))
integer(0)

删除点 8 后,新的 Delta 为 70。我们使用新的 Delta (70) 检查异常值并找到 none。因此,让我们使用 Delta = 70 进行聚类。

Cluster = cumsum(c(1, diff(dat)>=Delta))
plot(dat, pch=20, col=Cluster+1)

这主要找到了您想要的聚类 除了 它包括最高聚类中的最后两个点而不是将它们声明为异常值。我不明白为什么他们应该是异常值而不是这个群体的一部分。也许您可以详细说明为什么您认为不应包括它们。

希望对您有所帮助。

我建议使用 DBSCAN 而不是 K-Means。

这是一种基于密度的聚类算法,可以将彼此接近的数据点分组,而无需像 K-Means 那样定义初始 k 或质心。

在DBSCAN中,距离和k-neighbors是用户定义的。 如果您知道 Index 具有一致的区间,DBSCAN 可能适合解决您的问题。

我注意到那些层次看起来有点像线条。你可以这样做:

1. sort the points
2. take the first two unprocessed points into an ordered set called the current line
3. lay a line between the first and last point of the set
4. test whether the line formed by the first point and the next unprocessed point
    form a line that has an angle lower than some threshold to the other line
5. If yes, add the point and go to 3
6. If no, store the current line somewhere and start again at 2

您也可以首先检查这条线的前两个点是否与 x-axis 的角度大于另一个阈值,如果是,则将第一个点存储为奇异点。异常值。

另一个版本是仅通过连接两点的角度到达 x-axis。在水平变化上,将有比水平上两点之间更大的角度(倾斜,斜率)。