Comment fractionner des données en train et test en utilisant la division temporelle.
Je sais que train_test_split le scinde de manière aléatoire, comment le scinder en fonction du temps.
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)
# this splits the data randomly as 67% test and 33% train
Comment diviser le même ensemble de données basé sur le temps que 67% de train et 33% de test?
L'ensemble de données a une colonne TimeStamp.
J'ai essayé de chercher sur des questions similaires mais je n'étais pas sûr de l'approche.
Quelqu'un peut expliquer brièvement
Sur les séries de données temporelles, le fractionnement des données s'effectue d'une manière différente. Voir ce lien pour plus d'informations. Vous pouvez également essayer TimeSeriesSplit à partir du paquet scikit-learn. Donc, l’idée principale est la suivante: supposons que vous ayez 10 points de données en fonction de l’horodatage. Maintenant, les scissions seront comme ceci:
Split 1 :
Train_indices : 1
Test_indices : 2
Split 2 :
Train_indices : 1, 2
Test_indices : 3
Split 3 :
Train_indices : 1, 2, 3
Test_indices : 4
Split 4 :
Train_indices : 1, 2, 3, 4
Test_indices : 5
Etc., etc. Vous pouvez consulter l'exemple présenté dans le lien ci-dessus pour avoir une meilleure idée du fonctionnement de TimeSEriesSPlit dans sklearn.
Update Si vous avez une colonne time distincte, vous pouvez simplement trier les données en fonction de cette colonne et appliquer timeSeriesSplit comme indiqué ci-dessus pour obtenir les divisions.
Pour assurer 67% de formation et 33% de données de test dans la division finale, spécifiez le nombre de divisions comme suit:
no_of_split = int((len(data)-3)/3)
Exemple
X = np.array([[1, 2], [3, 4], [1, 2], [3, 4],[1, 2], [3, 4],[3, 4],[1, 2], [3, 4],[3, 4],[1, 2], [3, 4] ])
y = np.array([1, 2, 3, 4, 5, 6,7,8,9,10,11,12])
tscv = TimeSeriesSplit(n_splits=int((len(y)-3)/3))
for train_index, test_index in tscv.split(X):
print("TRAIN:", train_index, "TEST:", test_index)
#To get the indices
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
SORTIE:
('TRAIN:', array([0, 1, 2]), 'TEST:', array([3, 4, 5]))
('TRAIN:', array([0, 1, 2, 3, 4, 5]), 'TEST:', array([6, 7, 8]))
('TRAIN:', array([0, 1, 2, 3, 4, 5, 6, 7, 8]), 'TEST:', array([ 9, 10, 11]))
Un séjour sans faille
Si vous avez un jeu de données simple dans lequel chaque ligne est une observation (par exemple, un jeu de données non chronologique pour un problème de classification) et que vous souhaitez le scinder en train et test, cette fonction se scinde en train et test en fonction d'une colonne de dates:
import pandas as pd
import numpy as np
from math import ceil
def train_test_split_sorted(X, y, test_size, dates):
"""Splits X and y into train and test sets, with test set separated by most recent dates.
Example:
--------
>>> from sklearn import datasets
# Fake dataset:
>>> gen_data = datasets.make_classification(n_samples=10000, n_features=5)
>>> dates = np.array(pd.date_range('2016-01-01', periods=10000, freq='5min'))
>>> np.random.shuffle(dates)
>>> df = pd.DataFrame(gen_data[0])
>>> df['date'] = dates
>>> df['target'] = gen_data[1]
# Separate:
>>> X_train, X_test, y_train, y_test = train_test_split_sorted(df.drop('target', axis=1), df['target'], 0.33, df['date'])
>>> print('Length train set: {}'.format(len(y_train)))
Length train set: 8000
>>> print('Length test set: {}'.format(len(y_test)))
Length test set: 2000
>>> print('Last date in train set: {}'.format(X_train['date'].max()))
Last date in train set: 2016-01-28 18:35:00
>>> print('First date in test set: {}'.format(X_test['date'].min()))
First date in test set: 2016-01-28 18:40:00
"""
n_test = ceil(test_size * len(X))
sorted_index = [x for _, x in sorted(Zip(np.array(dates), np.arange(0, len(dates))), key=lambda pair: pair[0])]
train_idx = sorted_index[:-n_test]
test_idx = sorted_index[-n_test:]
if isinstance(X, (pd.Series, pd.DataFrame)):
X_train = X.iloc[train_idx]
X_test = X.iloc[test_idx]
else:
X_train = X[train_idx]
X_test = X[test_idx]
if isinstance(y, (pd.Series, pd.DataFrame)):
y_train = y.iloc[train_idx]
y_test = y.iloc[test_idx]
else:
y_train = y[train_idx]
y_test = y[test_idx]
return X_train, X_test, y_train, y_test
L'argument dates
peut en réalité être n'importe quel type de tableau ou de série que vous souhaitez utiliser pour trier vos données.
Dans votre cas, vous devez appeler: X_train, X_test, y_train, y_test = train_test_split_sorted(X, y, 0.333, TimeStamp)
, TimeStamp
étant le tableau ou la colonne contenant les informations relatives à l'horodatage de chaque observation.