web-dev-qa-db-fra.com

Comment fractionner les données en 3 ensembles (formation, validation et test)?

J'ai un pandas _ dataframe et je souhaite le diviser en 3 ensembles distincts. Je sais qu'en utilisant train_test_split de sklearn.cross_validation, on peut diviser les données en deux ensembles (train et test). Cependant, je n'ai trouvé aucune solution pour diviser les données en trois ensembles. De préférence, j'aimerais avoir les indices des données d'origine.

Je sais qu'une solution de contournement consisterait à utiliser train_test_split deux fois et à ajuster les index. Mais existe-t-il un moyen plus standard/intégré de fractionner les données en 3 ensembles au lieu de 2?

108
CentAu

Solution Numpy. Nous allons diviser notre ensemble de données dans les parties suivantes:

  • 60% - ensemble de train,
  • 20% - ensemble de validation,
  • 20% - set de test

In [305]: train, validate, test = np.split(df.sample(frac=1), [int(.6*len(df)), int(.8*len(df))])

In [306]: train
Out[306]:
          A         B         C         D         E
0  0.046919  0.792216  0.206294  0.440346  0.038960
2  0.301010  0.625697  0.604724  0.936968  0.870064
1  0.642237  0.690403  0.813658  0.525379  0.396053
9  0.488484  0.389640  0.599637  0.122919  0.106505
8  0.842717  0.793315  0.554084  0.100361  0.367465
7  0.185214  0.603661  0.217677  0.281780  0.938540

In [307]: validate
Out[307]:
          A         B         C         D         E
5  0.806176  0.008896  0.362878  0.058903  0.026328
6  0.145777  0.485765  0.589272  0.806329  0.703479

In [308]: test
Out[308]:
          A         B         C         D         E
4  0.521640  0.332210  0.370177  0.859169  0.401087
3  0.333348  0.964011  0.083498  0.670386  0.169619

[int(.6*len(df)), int(.8*len(df))] - est un tableau indices_or_sections pour numpy.split () .

Voici une petite démonstration pour np.split() usage - divisons le tableau de 20 éléments en parties suivantes: 80%, 10%, 10%:

In [45]: a = np.arange(1, 21)

In [46]: a
Out[46]: array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])

In [47]: np.split(a, [int(.8 * len(a)), int(.9 * len(a))])
Out[47]:
[array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16]),
 array([17, 18]),
 array([19, 20])]
118
MaxU

Remarque:

Une fonction a été écrite pour gérer l’ensemencement de la création d’ensembles aléatoires. Vous ne devez pas compter sur le fractionnement d’ensembles qui ne randomise pas les ensembles.

import numpy as np
import pandas as pd

def train_validate_test_split(df, train_percent=.6, validate_percent=.2, seed=None):
    np.random.seed(seed)
    perm = np.random.permutation(df.index)
    m = len(df.index)
    train_end = int(train_percent * m)
    validate_end = int(validate_percent * m) + train_end
    train = df.ix[perm[:train_end]]
    validate = df.ix[perm[train_end:validate_end]]
    test = df.ix[perm[validate_end:]]
    return train, validate, test

Manifestation

np.random.seed([3,1415])
df = pd.DataFrame(np.random.Rand(10, 5), columns=list('ABCDE'))
df

enter image description here

train, validate, test = train_validate_test_split(df)

train

enter image description here

validate

enter image description here

test

enter image description here

41
piRSquared

Cependant, une approche pour diviser le jeu de données en train, test, cv avec 0.6, 0.2, 0.2 serait d'utiliser le train_test_split méthode deux fois.

from sklearn.model_selection import train_test_split

x, x_test, y, y_test = train_test_split(xtrain,labels,test_size=0.2,train_size=0.8)
x_train, x_cv, y_train, y_cv = train_test_split(x,y,test_size = 0.25,train_size =0.75)
28
blitu12345

Une approche consiste à utiliser la fonction train_test_split deux fois.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test 
= train_test_split(X, y, test_size=0.2, random_state=1)

X_train, X_val, y_train, y_val 
= train_test_split(X_train, y_train, test_size=0.25, random_state=1)
8
rohan chikorde

Il est très pratique d'utiliser train_test_split sans effectuer de réindexation après la division en plusieurs ensembles et sans écrire de code supplémentaire. La meilleure réponse ci-dessus ne mentionne pas qu'en séparant deux fois en utilisant train_test_split ne pas modifier la taille des partitions ne donnera pas la partition initialement prévue:

x_train, x_remain = train_test_split(x, test_size=(val_size + test_size))

Alors la partie des ensembles de validation et de test dans la modification x_remain et peut être compté comme

new_test_size = np.around(test_size / (val_size + test_size), 2)
# To preserve (new_test_size + new_val_size) = 1.0 
new_val_size = 1.0 - new_test_size

x_val, x_test = train_test_split(x_remain, test_size=new_test_size)

A cette occasion, toutes les partitions initiales sont enregistrées.

1
A.Ametov