通过仅知道级别数来识别一维数据的级别
Posted
技术标签:
【中文标题】通过仅知道级别数来识别一维数据的级别【英文标题】:recognize the levels of 1D data by only knowing the number of levels 【发布时间】:2018-08-29 11:38:33 【问题描述】:我有一个传感器,其输出数据由一个属性(单值)组成。序列数据打孔示例如下:
示例: 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章
您可以看到来自第一张图片的数据输入。
数据分为多个级别。级别数是给我的(本例中为 5 个级别)。但是,每个级别的样本数量是未知的,级别之间的距离也是未知的。
我需要排除异常值并定义每个级别的中心(查看第二张图像输出。
红色样本代表异常值,黄色代表水平中心)。有没有什么算法、数学公式、c++代码可以帮我实现这个要求?
我尝试了 KMeans(在本例中 K = 5),但由于随机的初始 K 质心,我得到了不好的结果。大多数时候,一些初始质心共享相同的级别,使该级别成为两个集群,而其他两个级别属于一个集群。如果我通过从每个级别中选择一个质心来手动设置初始质心,我会得到非常好的结果。
【问题讨论】:
不是一个真正的编码问题。你可以考虑cstheory.stackexchange.com或dsp.stackexchange.com或scicomp.stackexchange.com或datascience.stackexchange.com(好吧,也许有很多SE站点......) 【参考方案1】:如果两个连续数据点之间的差异大于特定值(将此视为 Delta ),则它属于不同的集群。
对于该数据集: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 P>
假设 delta 为 15(基于 Sensor 微调),如果连续数据点的差异不大于 15,则它们属于同一个集群。您可以通过查找集群的中间值来找到中心点。 如果点附近的点有差异,那么它可以被认为是异常值。另一个选项是我们可以根据数据集的当前值改变增量。
【讨论】:
如何定义增量。如您所见,级别的值以随机方式从一个级别变化到下一个级别。我需要类似“动态”增量的东西。或者如果有一些基于密度对数据进行分类的聚类算法会更好。很明显,属于一个级别的数据彼此非常接近,所以如果有某种聚类可以找出这种分布,我认为它会解决问题 @asker 然后做一些预处理,找出两个相邻点之间的平均距离和最大距离,然后在两者之间选择一些东西。我的意思是,如果不事先了解数据,我认为无法更清楚地说明这一点。【参考方案2】:这是@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) 检查异常值,但没有发现任何异常值。所以让我们使用 Delta = 70 进行聚类。
Cluster = cumsum(c(1, diff(dat)>=Delta))
plot(dat, pch=20, col=Cluster+1)
这主要是找到您想要的集群除了它包括最高集群中的最后两个点,而不是将它们声明为异常值。我不明白为什么他们应该是异常值而不是该组的一部分。也许您可以详细说明为什么您认为不应将它们包括在内。
我希望这会有所帮助。
【讨论】:
【参考方案3】:我建议 DBSCAN 而不是 K-Means。
这是一种基于密度的聚类算法,可将彼此接近的数据点分组,而无需定义初始 k 或 K-Means 等质心。
在 DBSCAN 中,距离和 k 邻居是用户定义的。 如果您知道 Index 具有一致的间隔,DBSCAN 可能适合解决您的问题。
【讨论】:
【参考方案4】:我注意到这些级别看起来有点像线条。你可以这样做:
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 轴的角度是否高于另一个阈值,如果是,则将第一个点存储为奇异值。异常值。
另一个版本是仅通过两点与 x 轴的连接角度。在水平变化时,角度(倾斜、坡度)将远大于水平上两点之间的角度。
【讨论】:
以上是关于通过仅知道级别数来识别一维数据的级别的主要内容,如果未能解决你的问题,请参考以下文章