我正在使用Python进行核密度估计和高斯混合模型,以对多维数据样本的可能性进行排名。每条数据都是一个角度,我不确定如何处理机器学习的角度数据的周期性。
首先,我通过添加 360 来删除所有负角度,因此所有负角度都变为正角度,-179 变为 181。 我相信这优雅地处理了 -179 的情况,与 179 和相似没有显着区别,但它不处理像 359 与 1 没有区别的实例。
我想解决这个问题的一种方法是同时保留负值和负+360值,并使用两者中的最小值,但这需要修改机器学习算法。
这个问题有没有很好的预处理解决方案? 有什么内置的东西内置在 scipy 或 scikit 中?
谢谢!
正如 Tal Darom 在评论中所写,在归一化为弧度后,您可以将每个周期性特征x
替换为两个特征cos(x)
和sin(x)
。这解决了 359 ≈ 1 问题:
>>> def fromdeg(d):
... r = d * np.pi / 180.
... return np.array([np.cos(r), np.sin(r)])
...
>>> np.linalg.norm(fromdeg(1) - fromdeg(359))
0.03490481287456796
>>> np.linalg.norm(fromdeg(1) - fromdeg(180))
1.9999238461283426
>>> np.linalg.norm(fromdeg(90) - fromdeg(270))
2.0
norm(a - b)
是向量a
和b
之间的旧欧几里得距离。正如您可以使用简单的绘图或意识到这些(cos,sin(对实际上是单位圆上的坐标来验证的那样,当原始角度相差180°时,这两个(cos,sin(向量之间的距离最大(点积最小(。
已经发布的方法的另一种方法是使用冯·米塞斯分布对角度变量进行建模。
这种分布似乎得到了 scipy 的支持,因此适应混合模型应该不会太困难。
另一种更简单的方法可能是使用时间作为角度测量,而不是度数测量(虽然不是DMS(。由于许多分析软件将时间作为数据类型,因此您可以使用其周期性来完成您的工作。
但请记住,您需要将 360 度缩放到 24 小时。
你需要使用 mod 函数。 在直接的python中,这将是(ang2-ang1)%360
但是对于scipy,看起来您可以使用numpy.mod()
- 请参阅文档。