web-dev-qa-db-fra.com

Régression avec la variable Date utilisant Scikit-learn

J'ai un Pandas DataFrame avec une colonne date (par exemple: 2013-04-01) de type d datetime.date. Lorsque j'inclus cette colonne dans X_train et que j'essaie de m'adapter au modèle de régression, j'obtiens l'erreur float() argument must be a string or a number. La suppression de la colonne date a évité cette erreur.

Quelle est la bonne façon de prendre en compte date dans le modèle de régression?

Code

data = sql.read_frame(...)
X_train = data.drop('y', axis=1)
y_train = data.y

rf = RandomForestRegressor().fit(X_train, y_train)

Erreur

TypeError                                 Traceback (most recent call last)
<ipython-input-35-8bf6fc450402> in <module>()
----> 2 rf = RandomForestRegressor().fit(X_train, y_train)

C:\Python27\lib\site-packages\sklearn\ensemble\forest.pyc in fit(self, X, y, sample_weight)
    292                 X.ndim != 2 or
    293                 not X.flags.fortran):
--> 294             X = array2d(X, dtype=DTYPE, order="F")
    295 
    296         n_samples, self.n_features_ = X.shape

C:\Python27\lib\site-packages\sklearn\utils\validation.pyc in array2d(X, dtype, order, copy)
     78         raise TypeError('A sparse matrix was passed, but dense data '
     79                         'is required. Use X.toarray() to convert to dense.')
---> 80     X_2d = np.asarray(np.atleast_2d(X), dtype=dtype, order=order)
     81     _assert_all_finite(X_2d)
     82     if X is X_2d and copy:

C:\Python27\lib\site-packages\numpy\core\numeric.pyc in asarray(a, dtype, order)
    318 
    319     """
--> 320     return array(a, dtype, copy=False, order=order)
    321 
    322 def asanyarray(a, dtype=None, order=None):

TypeError: float() argument must be a string or a number
17
Nyxynyx

La meilleure méthode consiste à décomposer la date en un ensemble de caractéristiques catégorielles codées sous forme booléenne à l’aide du codage 1-of-K (par exemple, comme indiqué par DictVectorizer ). Voici quelques fonctionnalités pouvant être extraites d'une date:

  • heure de la journée (24 fonctions booléennes)
  • jour de la semaine (7 fonctions booléennes)
  • jour du mois (jusqu'à 31 fonctions booléennes)
  • mois de l'année (12 fonctions booléennes)
  • année (autant d’entités booléennes que d’années différentes dans votre jeu de données) ...

Cela devrait permettre d'identifier des dépendances linéaires d'événements périodiques sur des cycles de vie typiques.

En outre, vous pouvez également extraire la date d'un seul flotteur: convertissez chaque date en nombre de jours depuis la date minimale de votre entraînement et divisez-la par la différence entre le nombre de jours entre la date maximale et le nombre de jours de la date minimale. . Cette caractéristique numérique devrait permettre d’identifier les tendances à long terme entre le résultat de la date de l’événement: p. Ex. une pente linéaire dans un problème de régression pour mieux prévoir l'évolution des prochaines années qui ne peut pas être encodée avec la variable catégorique booléenne pour l'entité année.

26
ogrisel

Vous avez deux options. Vous pouvez convertir la date en un ordinal, c'est-à-dire un entier représentant le nombre de jours depuis l'année 1 jour 1. Vous pouvez le faire à l'aide de la fonction toordinal de datetime.date

Sinon, vous pouvez transformer les dates en variables catégorielles à l'aide de OneHotEncoder de sklearn. Cela crée une nouvelle variable pour chaque date distincte. Ainsi, au lieu de quelque chose comme la colonne date avec les valeurs ['2013-04-01', '2013-05-01'], vous aurez deux colonnes, date_2013_04_01 avec les valeurs [1, 0] et date_2013_05_01 avec les valeurs [0, 1]

Je recommanderais d'utiliser l'approche toordinal si vous avez plusieurs dates différentes, et le seul encodeur chaud si le nombre de dates distinctes est petit (disons jusqu'à 10 - 100, en fonction de la taille de vos données et du type de relation entre a avec la variable de sortie).

8
Ando Saabas

Avant de procéder au codage booléen à l’aide du codage 1-of-K proposé par @ogrisel, vous pouvez essayer d’enrichir vos données et de jouer avec le nombre de fonctionnalités que vous pouvez extraire du type date/heure, à savoir jour de la semaine, jour du mois de l'année, semaine de l'année, trimestre, etc. Voir par exemple https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DatetimeIndex.weekofyear.html à d'autres fonctions.

1