Qual è un buon modo per trasformare gli attributi ordinali ciclici?


21

Sto avendo il campo 'hour' come mio attributo, ma ci vogliono valori ciclici. Come potrei trasformare la funzione per conservare le informazioni come '23' e '0' ora non sono vicine.

Un modo in cui potrei pensare è fare la trasformazione: 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]

Esiste uno standard per gestire tali attributi?

Aggiornamento: userò l'apprendimento supervisionato, per addestrare il classificatore casuale delle foreste!


1
Ottima prima domanda! Puoi aggiungere qualche informazione in più su quale è il tuo obiettivo di realizzare questa specifica trasformazione delle caratteristiche? Intendi utilizzare questa funzionalità trasformata come input per un problema di apprendimento supervisionato? In tal caso, ti preghiamo di considerare di aggiungere tali informazioni in quanto potrebbero aiutare gli altri a rispondere meglio a questa domanda.
Nitesh,

1
@Nitesh, vedi aggiornamento
Mangat Rai Modi


Scusa ma non posso commentare. @ AN6U5 potresti ampliare il modo in cui considerare contemporaneamente il giorno della settimana e l'ora dopo il tuo fantastico approccio, per favore? Sto lottando su questo da una settimana e ho anche pubblicato un Q ma non l'hai letto.
Seymour,

Risposte:


33

Il modo più logico per trasformare l'ora è in due variabili che oscillano avanti e indietro dal lavandino. Immagina la posizione della fine della lancetta delle ore di un orologio di 24 ore. La xposizione oscilla avanti e indietro dal lavandino con la yposizione. Per un orologio di 24 ore è possibile raggiungere questo obiettivo con x=sin(2pi*hour/24), y=cos(2pi*hour/24).

Sono necessarie entrambe le variabili o si perde il movimento corretto nel tempo. Ciò è dovuto al fatto che la derivata di sin o cos cambia nel tempo in cui la (x,y)posizione varia in modo uniforme mentre percorre il cerchio unitario.

Infine, considera se vale la pena aggiungere una terza funzione per tracciare il tempo lineare, che può essere costruito le mie ore (o minuti o secondi) dall'inizio del primo record o un timestamp Unix o qualcosa di simile. Queste tre caratteristiche forniscono quindi proxy per la progressione ciclica e lineare del tempo, ad esempio è possibile estrarre fenomeni ciclici come i cicli del sonno nel movimento delle persone e anche una crescita lineare come la popolazione rispetto al tempo.

Spero che sia di aiuto!

Aggiunta di un codice di esempio pertinente che ho generato per un'altra risposta:

Esempio di realizzazione:

# 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

inserisci qui la descrizione dell'immagine

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

Ora proviamo:

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

inserisci qui la descrizione dell'immagine

Riesci a malapena a vedere che ci sono alcuni dopo mezzanotte inclusi nel cluster verde prima di mezzanotte. Ora consente di ridurre il numero di cluster e mostrare che prima e dopo la mezzanotte possono essere collegati in un singolo cluster in modo più dettagliato:

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

inserisci qui la descrizione dell'immagine

Scopri in che modo il cluster blu contiene i periodi precedenti e successivi alla mezzanotte raggruppati nello stesso cluster ...

QED!


Modo brillante per gestirlo. Darebbe punteggi simili a 0 e 23 ore ma non renderebbe simili anche le ore am / pm? Che in realtà è separato dalla finestra di 12 ore.
Mangat Rai Modi,

Il tempo di 12 ore (AM / PM) non funziona, basta convertirlo in tempo di 24 ore.
AN6U5,

Ho appena notato che stai dividendo per 24. Quando hai dato analogia all'orologio, ho pensato che fosse un orologio standard di 12 ore. Comunque stai prendendo l'orologio 24 ore. Sembra essere il modo migliore per trasformarmi. Grazie!
Mangat Rai Modi,

Risposta incredibile Esattamente quello che stavo cercando Grazie ..
Aditya

La risposta accettata che combina sin () & cost () è ottima; qui come complemento un'altra spiegazione molto dettagliata e piacevole per questo di Ian London.
FlorianH,

3

La domanda è molto interessante e non ricordo di leggere risposte interessanti. Per questo, ho il coraggio di darti una possibile soluzione anche se sembra abbastanza folle.

Di solito si evita di avere le stesse informazioni in più funzionalità, poiché molti algoritmi non sono in grado di gestirle. Ma questo non è il caso della foresta casuale. Regressione lineare contrastante (e tutti i modelli basati su idee simili), foreste casuali testano tutte le caratteristiche, prendendo in considerazione ciascuna caratteristica alla volta. In questo modo è possibile codificare le stesse informazioni in più modi senza influire sulle prestazioni di apprendimento, onyly spazio e tempo di esecuzione.

Quindi il mio suggerimento sarebbe quello di creare 24 funzionalità, ciascuna del modulo (h+offSet). È come quando si codifica l'ora nei fusi orari locali. In questo modo dai la possibilità a RF di rilevare usando le stesse unità alcuni agglomerati interessanti in alcune ore, perché ogni possibile ora ha la possibilità di essere codificata correttamente in almeno 1 su 24 funzioni.

Spreca tempo e spazio, ma vorrei provarlo per vedere come funziona.


0

Idealmente non hai bisogno di alcuna trasformazione. La differenza di tempo relativa tra due punti può essere utilizzata come funzione di distanza. Dove la classificazione può essere basata su questo.

a 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
Va bene, ma la domanda ha bisogno di qualcos'altro ..
Aditya,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.