转换循环序数属性的好方法是什么?


21

我将“小时”字段作为属性,但是它具有循环值。我如何转换功能以保留诸如“ 23”和“ 0”小时之类的信息,距离不远。

我认为的一种方法是进行转换: min(h, 23-h)

Input: [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]

Output: [0 1 2 3 4 5 6 7 8 9 10 11 11 10 9 8 7 6 5 4 3 2 1]

是否有任何标准可以处理此类属性?

更新:我将使用监督学习来训练随机森林分类器!


1
优秀的第一个问题!您是否可以添加更多有关执行此特定功能转换的目标的信息?您是否打算将此转换功能用作监督学习问题的输入?如果是这样,请考虑添加该信息,因为它可以帮助其他人更好地回答此问题。
Nitesh

1
@Nitesh,请查看更新
Mangat Rai Modi 2015年


抱歉,我不能发表评论。@ AN6U5,请您扩展一下如何以惊人的方式同时考虑周几和小时?一个星期以来,我一直在为此苦苦挣扎,我还发布了一个问题,但是您没有阅读。
西摩'18

Answers:


33

转换小时数的最合乎逻辑的方法是分为两个变量,这些变量在接收器中来回摆动。想象一下24小时制时针的末尾位置。该x位置与该y位置一起从水槽中来回摆动。对于24小时制,您可以使用x=sin(2pi*hour/24),完成y=cos(2pi*hour/24)

您需要两个变量,否则会丢失正确的移动时间。这是由于正弦或余弦的导数随时间变化的事实,即(x,y)位置在单位圆中移动时位置平滑变化。

最后,考虑是否值得添加第三项功能来跟踪线性时间,该时间可以从第一条记录的开始(小时或分钟或秒)或Unix时间戳或类似的时间构建。然后,这三个功能可提供时间的周期性和线性进展的代理,例如,您可以提取诸如人的运动中的睡眠周期之类的周期性现象,以及诸如人口与时间之类的线性增长。

希望这可以帮助!

添加我为另一个答案生成的一些相关示例代码:

如果完成的示例:

# Enable inline plotting
%matplotlib inline

#Import everything I need...

import numpy as np
import matplotlib as mp

import matplotlib.pyplot as plt
import pandas as pd

# Grab some random times from here: https://www.random.org/clock-times/
# put them into a csv.
from pandas import DataFrame, read_csv
df = read_csv('/Users/angus/Machine_Learning/ipython_notebooks/times.csv',delimiter=':')
df['hourfloat']=df.hour+df.minute/60.0
df['x']=np.sin(2.*np.pi*df.hourfloat/24.)
df['y']=np.cos(2.*np.pi*df.hourfloat/24.)

df

在此处输入图片说明

def kmeansshow(k,X):

    from sklearn import cluster
    from matplotlib import pyplot
    import numpy as np

    kmeans = cluster.KMeans(n_clusters=k)
    kmeans.fit(X)

    labels = kmeans.labels_
    centroids = kmeans.cluster_centers_
    #print centroids

    for i in range(k):
        # select only data observations with cluster label == i
        ds = X[np.where(labels==i)]
        # plot the data observations
        pyplot.plot(ds[:,0],ds[:,1],'o')
        # plot the centroids
        lines = pyplot.plot(centroids[i,0],centroids[i,1],'kx')
        # make the centroid x's bigger
        pyplot.setp(lines,ms=15.0)
        pyplot.setp(lines,mew=2.0)
    pyplot.show()
    return centroids

现在让我们尝试一下:

kmeansshow(6,df[['x', 'y']].values)

在此处输入图片说明

您几乎看不到午夜之前的绿色群集中包含一些午夜之后的时间。现在让我们减少集群的数量,并显示午夜前后可以更详细地连接到单个集群中:

kmeansshow(3,df[['x', 'y']].values)

在此处输入图片说明

查看蓝色群集如何包含午夜前后的时间,这些时间聚集在同一群集中...

QED!


出色的处理方式。它会给0和23小时类似的分数,但是它也不会使am / pm时间也相似吗?实际上是由12hr窗口分隔的。
Mangat Rai Modi

12小时(AM / PM)时间不起作用,只需将其转换为24小时时间即可。
AN6U5

我只是注意到您正在除以24。当您类比时钟时,我认为这是标准的12小时制。但是,您正在使用24小时制。这似乎是我转型的最佳方式。谢谢!
Mangat Rai Modi

令人惊奇的答案正是我想要的东西
。– Aditya

结合sin()和cost()的公认答案很棒;在此作为补充,伊恩·伦敦(Ian London)对此进行了非常详尽而优美的解释。
FlorianH

3

这个问题非常有趣,我不记得读过有趣的答案。因此,即使它看起来足够疯狂,我也敢为您提供一种可能的解决方案。

通常,人们会避免在多个功能中拥有相同的信息,因为许多算法无法处理这些信息。但这不是随机森林的情况。与线性回归(以及基于相似思想的所有模型)相反,随机森林通过一次考虑每个特征来测试所有特征。这样,可以以多种方式对相同的信息进行编码,而不会影响学习性能,空间和运行时间。

H+ØFFsËŤ

这浪费了一些时间和空间,但是我会尝试一下看看它是如何工作的。


0

理想情况下,您不需要任何转换。两点之间的相对时间差可用作距离函数。可以基于此进行分类。

在Java中:

public class TimeDistanceMeasurer implements DistanceMeasure {

    @Override
    public double compute(double[] a, double[] b) throws DimensionMismatchException {
        String time1 = String.format("%02d", (int)a[0]) + String.format("%02d", (int)a[0]);
        String time2 = String.format("%02d", (int)b[0]) + String.format("%02d", (int)b[0]);

        SimpleDateFormat format = new SimpleDateFormat("HHmm");
        try {
            Date date1 = format.parse(time1);
            Date date2 = format.parse(time2);
            return Math.abs(date2.getTime() - date1.getTime());
        } catch (Exception e) {
            throw new IllegalStateException("Something went wrong.", e);
        }
    }
}

1
没关系,但问题还需要其他
。.–阿迪亚
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.