¿Cuál es una buena manera de transformar los atributos ordinales cíclicos?

21

Tengo el campo 'hora' como mi atributo, pero toma valores cíclicos. ¿Cómo podría transformar la función para preservar la información como '23' y '0' hora?

Una forma en que podría pensar es hacer la transformación: 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]

¿Hay algún estándar para manejar tales atributos?

Actualización: ¡Usaré aprendizaje supervisado para entrenar clasificador forestal aleatorio!

Mangat Rai Modi
fuente
1
Excelente primera pregunta! ¿Puede agregar más información sobre cuál es su objetivo para llevar a cabo esta transformación de características específicas? ¿Tiene la intención de utilizar esta función transformada como una entrada a un problema de aprendizaje supervisado? Si es así, considere agregar esa información, ya que puede ayudar a otros a responder mejor esta pregunta.
Nitesh
1
@Nitesh, mira la actualización
Mangat Rai Modi
Puede encontrar respuestas aquí: datascience.stackexchange.com/questions/4967/…
MrMeritology
Lo siento pero no puedo comentar. @ AN6U5 ¿podría ampliar cómo considerar simultáneamente el día de la semana y la hora después de su enfoque sorprendente, por favor? Estoy luchando por esto desde hace una semana y también publiqué una Q pero no la leíste.
Seymour

Respuestas:

33

La forma más lógica de transformar la hora es en dos variables que se balancean de un lado a otro. Imagine la posición de la manecilla de fin de hora de un reloj de 24 horas. La xposición oscila de un lado a otro del fregadero con la yposición. Para un reloj de 24 horas se puede lograr esto con x=sin(2pi*hour/24), y=cos(2pi*hour/24).

Necesita ambas variables o se pierde el movimiento adecuado a través del tiempo. Esto se debe al hecho de que la derivada de sin o cos cambia en el tiempo cuando la (x,y)posición varía suavemente a medida que viaja alrededor del círculo unitario.

Finalmente, considere si vale la pena agregar una tercera característica para rastrear el tiempo lineal, que se puede construir mis horas (o minutos o segundos) desde el comienzo del primer registro o una marca de tiempo Unix o algo similar. Estas tres características proporcionan proxies para la progresión cíclica y lineal del tiempo, por ejemplo, puede extraer fenómenos cíclicos como los ciclos de sueño en el movimiento de las personas y también el crecimiento lineal como la población frente al tiempo.

¡Espero que esto ayude!

Agregando un código de ejemplo relevante que generé para otra respuesta:

Ejemplo de si se está logrando:

# 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

ingrese la descripción de la imagen aquí

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

Ahora probemos:

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

ingrese la descripción de la imagen aquí

Apenas puede ver que hay algunos momentos posteriores a la medianoche incluidos con el clúster verde anterior a la medianoche. Ahora reduzcamos el número de clústeres y demostremos que antes y después de la medianoche se pueden conectar en un solo clúster con más detalle:

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

ingrese la descripción de la imagen aquí

Vea cómo el clúster azul contiene horas anteriores y posteriores a la medianoche que se agrupan en el mismo clúster ...

QED!

AN6U5
fuente
Brillante forma de manejarlo. Daría puntajes similares de 0 y 23 horas, pero ¿no hará que el horario am / pm también sea similar? Que de hecho está separado por una ventana de 12 horas.
Mangat Rai Modi
El tiempo de 12 horas (AM / PM) no funciona, solo conviértalo a 24 horas.
AN6U5
Me acabo de dar cuenta de que estás dividiendo entre 24. Cuando le diste la analogía al reloj, pensé que era un reloj estándar de 12 horas. Sin embargo, está tomando un reloj de 24 horas. Parece ser la mejor forma de transformarme. ¡Gracias!
Mangat Rai Modi
Increíble respuesta Exactamente lo que estaba buscando Gracias ..
Aditya
La respuesta aceptada que combina pecado () y costo () es excelente; aquí como complemento otra explicación muy detallada y agradable de Ian London.
FlorianH
3

La pregunta es muy interesante y no recuerdo haber leído sobre respuestas interesantes. Por eso me atrevo a darle una posible solución, incluso si parece lo suficientemente loco.

Por lo general, se evita tener la misma información en múltiples funciones, ya que muchos algoritmos no pueden manejar eso. Pero este no es el caso del bosque aleatorio. En contraste con la regresión lineal (y todos los modelos basados ​​en ideas similares), los bosques aleatorios prueban todas las características, teniendo en cuenta cada característica de una en una. De esta manera, es posible codificar la misma información de múltiples maneras sin afectar el rendimiento del aprendizaje, solo el espacio y el tiempo de ejecución.

Entonces, mi sugerencia sería crear 24 características, cada una de las formas . Es como cuando codifica la hora en zonas horarias locales. Por lo tanto, le da la oportunidad a rf de detectar usando las mismas unidades algunas aglomeraciones interesantes alrededor de algunas horas, porque cada hora posible tiene la posibilidad de codificarse correctamente en al menos 1 de las 24 características.(h+oFFsmit)

Pierde algo de espacio y tiempo, pero lo probaría para ver cómo funciona.

rapaio
fuente
0

Idealmente, no necesitas ninguna transformación. La diferencia de tiempo relativa entre dos puntos se puede utilizar como función de distancia. Donde la clasificación puede basarse en esto.

en 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);
        }
    }
}
shiva.n404
fuente
1
Eso está bien, pero la pregunta necesita algo más ...
Aditya