Quelle est la bonne façon de transformer les attributs ordinaux cycliques?

21

J'ai le champ «heure» comme attribut, mais cela prend des valeurs cycliques. Comment pourrais-je transformer la fonctionnalité pour préserver les informations telles que «23» et «0» heure sont proches non loin.

Une façon dont je pourrais penser est de faire de la transformation: 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]

Existe-t-il une norme pour gérer ces attributs?

Mise à jour: je vais utiliser l'apprentissage supervisé pour former un classificateur de forêt aléatoire!

Mangat Rai Modi
la source
1
Excellente première question! Pouvez-vous ajouter plus d'informations sur votre objectif de réaliser cette transformation de fonctionnalité spécifique? Avez-vous l'intention d'utiliser cette fonctionnalité transformée comme entrée pour un problème d'apprentissage supervisé? Dans l'affirmative, veuillez envisager d'ajouter ces informations, car cela pourrait aider les autres à mieux répondre à cette question.
Nitesh
1
@Nitesh, veuillez voir la mise à jour
Mangat Rai Modi
Vous pouvez trouver des réponses ici: datascience.stackexchange.com/questions/4967/…
MrMeritology
Désolé mais je ne peux pas commenter. @ AN6U5 pourriez-vous s'il vous plaît étendre la façon de considérer simultanément le jour de la semaine et l'heure suivant votre approche incroyable, s'il vous plaît? Je me bats là-dessus depuis une semaine et j'ai également posté un Q mais vous ne l'avez pas lu.
Seymour

Réponses:

33

Le moyen le plus logique de transformer l'heure est en deux variables qui oscillent d'avant en arrière hors de l'évier. Imaginez la position de la fin de l'aiguille des heures d'une horloge de 24 heures. La xposition oscille d'avant en arrière de l'évier avec la yposition. Pour une horloge de 24 heures, vous pouvez accomplir cela avecx=sin(2pi*hour/24) , y=cos(2pi*hour/24).

Vous avez besoin des deux variables ou le bon mouvement dans le temps est perdu. Cela est dû au fait que la dérivée de sin ou cos change dans le temps alors que(x,y) position varie en douceur lorsqu'elle se déplace autour du cercle unitaire.

Enfin, demandez-vous s'il est utile d'ajouter une troisième fonctionnalité pour tracer le temps linéaire, qui peut être construite mes heures (ou minutes ou secondes) depuis le début du premier enregistrement ou un horodatage Unix ou quelque chose de similaire. Ces trois caractéristiques fournissent ensuite des indicateurs pour la progression cyclique et linéaire du temps, par exemple, vous pouvez extraire un phénomène cyclique comme les cycles de sommeil dans le mouvement des personnes et également une croissance linéaire comme la population en fonction du temps.

J'espère que cela t'aides!

Ajout d'un exemple de code pertinent que j'ai généré pour une autre réponse:

Exemple de réalisation:

# 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

entrez la description de l'image ici

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

Essayons maintenant:

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

entrez la description de l'image ici

Vous pouvez à peine voir qu'il y en a certains après minuit inclus avec le cluster vert avant minuit. Permet maintenant de réduire le nombre de clusters et de montrer qu'avant et après minuit peuvent être connectés en un seul cluster plus en détail:

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

entrez la description de l'image ici

Voyez comment le cluster bleu contient des heures antérieures et postérieures à minuit regroupées dans le même cluster ...

QED!

AN6U5
la source
Une manière brillante de le gérer. Cela donnerait des scores similaires à 0 et 23 heures, mais cela ne rendra-t-il pas le temps am / pm similaire aussi? Qui est en fait séparé par une fenêtre de 12 heures.
Mangat Rai Modi
Le temps de 12 heures (AM / PM) ne fonctionne pas, il suffit de le convertir en 24 heures.
AN6U5
Je viens de remarquer que vous divisez par 24. Lorsque vous avez fait une analogie avec l'horloge, je pensais que c'était une horloge standard de 12 heures. Cependant, vous prenez une horloge de 24 heures. Cela semble être le meilleur moyen pour moi de me transformer. Je vous remercie!
Mangat Rai Modi
Réponse étonnante Exactement ce que je cherchais Merci ..
Aditya
La réponse acceptée combinant sin () & cost () est excellente; ici en complément une autre explication très détaillée et agréable par Ian London.
FlorianH
3

La question est très intéressante et je ne me souviens pas d'avoir lu des réponses intéressantes. Pour cette raison, j'ose vous donner une solution possible même si elle semble assez folle.

Habituellement, on évite d'avoir les mêmes informations dans plusieurs fonctionnalités, car de nombreux algorithmes ne peuvent pas gérer cela. Mais ce n'est pas le cas de la forêt aléatoire. Contrastant la régression linéaire (et tous les modèles basés sur des idées similaires), les forêts aléatoires testent toutes les caractéristiques, en prenant en considération chaque caractéristique une à la fois. De cette façon, il est possible de coder les mêmes informations de plusieurs manières sans affecter les performances d'apprentissage, l'espace et la durée d'exécution.

(h+oFFset) . C'est comme lorsque vous encodez l'heure dans des fuseaux horaires locaux. Ainsi vous donnez l'occasion à rf de détecter en utilisant les mêmes unités des agglomérations intéressantes autour de quelques heures, car chaque heure possible a la chance d'être encodée correctement dans au moins 1 des 24 fonctionnalités.

Cela gaspille un peu de temps et d'espace, mais je voudrais essayer de voir comment cela fonctionne.

rapaio
la source
0

Idéalement, vous n'avez besoin d'aucune transformation. La différence de temps relative entre deux points peut être utilisée comme fonction de distance. Où la classification peut être basée sur cela.

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
la source
1
C'est bien mais la question a besoin d'autre chose ..
Aditya