Si j'exécute un modèle de régression d'arbre simple en utilisant des données via la fonction train_test_split, j'obtiens de bons scores r2 et des valeurs mse faibles.
training_data = pandas.read_csv("train"+".csv",usecols=['y','x1','x2','x3']) testing_data = pandas.read_csv("test"+".csv", usecols=['y','x1','x2','x3']) y_train = training_data.iloc[:,training_data.columns.str.contains('y')] X_train = training_data.iloc[:,training_data.columns.str.contains('|'.join(['x1','x2','x3']))] y_test = testing_data.iloc[:,testing_data.columns.str.contains('y')] X_test = testing_data.iloc[:,testing_data.columns.str.contains('|'.join(l_vars))] y_train = pandas.Series(y_train['y'], index=y_train.index) y_test = pandas.Series(y_test['y'], index=y_test.index) regressor = DecisionTreeRegressor(random_state = 0) regressor.fit(X_train, y_train) y_pred = regressor.predict(X_test)
encore si je divise le fichier de données manuellement en deux fichiers 2/3 train et 1/3 test. il y a une colonne appelée humain qui donne une valeur de 1 à 9 qui est humain, j'utilise humain 1-6 pour l'entraînement et 7-9 pour le test
j'obtiens des scores r2 négatifs et mse élevé
training_data = pandas.read_csv('data.csv',usecols=['y','x1','x2','x3']) y = training_data.iloc[:,0] x = training_data.iloc[:,1:] X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.33) regressor = DecisionTreeRegressor(random_state = 0) # fit the regressor with X and Y data regressor.fit(X_train, y_train) y_pred = regressor.predict(X_test)
Je m'attendais plus ou moins aux mêmes résultats, et tous les types de données semblent identiques pour les deux appels.
Que me manque-t-il? p>
4 Réponses :
La fonction train_test_split
de scikit-learn
utilise sklearn.model_selection.ShuffleSplit
selon le documentation et cela signifie que cette méthode randomise vos données lors du fractionnement.
Lorsque vous avez fractionné manuellement, vous ne l'avez pas randomisé, donc si vos étiquettes ne sont pas réparties uniformément dans votre ensemble de données, vous aurez bien sûr des problèmes de performances car votre modèle ne sera pas assez généralisé en raison de données d'entraînement ne contenant pas suffisamment échantillon d'autres étiquettes.
Si mes soupçons sont corrects, vous devriez obtenir un résultat similaire en passant shuffle = False
dans train_test_split
.
train_test_split retourne toujours la même chose car il définit une graine aléatoire, jamais moins je l'ai fait de toute façon et le problème persiste.
Je suppose que les deux méthodes ici font réellement ce que vous avez l'intention de faire et que les formes de votre X_train / test et y_train / tests sont les mêmes venant des deux méthodes. Vous pouvez soit tracer les distributions sous-jacentes de vos ensembles de données , soit comparer votre deuxième implémentation à un modèle à validation croisée (pour une meilleure rigueur).
Tracez les distributions (c'est-à-dire faites des graphiques à barres / des graphiques de densité) des étiquettes (y) dans le train initial - testez les ensembles par rapport aux seconds (à partir de l'implémentation manuelle). Vous pouvez plonger plus profondément et également tracer vos autres colonnes dans les données, voir si quelque chose concernant les distributions de vos données est différent entre les ensembles résultants des deux implémentations. Si les distributions sont différentes de ce qui a du sens, vous obtenez des écarts entre vos deux modèles. Si votre écart est énorme, il se peut que vos étiquettes (ou d'autres colonnes) soient réellement triées pour votre implémentation manuelle, vous obtenez donc des distributions très différentes dans les ensembles de données que vous comparez.
De plus, si vous voulez vous assurer que vos résultats de fractionnement manuel sont un ensemble `` représentatif '' (qui se généraliserait bien) basé sur les résultats du modèle au lieu des distributions de données sous-jacentes, je le comparerais aux résultats d'une validation croisée modèle, pas un seul ensemble de résultats.
Essentiellement, bien que la probabilité soit faible et que le train_test_split
effectue un brassage, vous pourriez essentiellement obtenir une paire «train / test» qui fonctionne bien juste par chance. (Pour réduire le risque de cela sans faire de validation croisée, je suggère d'utiliser l'argument stratify
de la fonction train_test_split
. Alors au moins vous êtes sûr que le premier implémentation 'essaie plus fort' d'obtenir des paires train / test équilibrées.)
Si vous décidez de faire une validation croisée (avec test_train_split
), vous obtenez une prédiction de modèle moyenne pour les plis et un intervalle de confiance autour de celle-ci et vous pouvez vérifier si les résultats de votre deuxième modèle se situent dans cet intervalle. Si ce n'est pas le cas, cela signifie simplement que votre fractionnement est en fait `` corrompu '' (par exemple en ayant des valeurs triées).
P.S. J'ajouterais également que les arbres de décision sont des modèles connus pour surajuster massivement [1]. Peut-être utiliser une forêt aléatoire à la place? (vous devriez obtenir des résultats plus stables en raison du bootstraping / bagging qui agirait de la même manière que la validation croisée pour réduire le risque de surajustement.)
1 - http: //cv.znu .ac.ir / afsharchim / AI / lectures / Decision% 20Trees% 203.pdf
merci pour la réponse et désolé si tard dans la lecture. J'ai vérifié les distributions et elles sont à peu près identiques. les données sont essentiellement 9 êtres humains, et au lieu de la division python, ma division manuelle est humaine 1-6 et le test est 7-9 donc devrait être la même représentation, j'aurais pensé au moins. malade continue de creuser. J'ai également fait des forêts aléatoires qui donnent de meilleurs résultats sur le fractionnement python, mais les mêmes problèmes sur mon fractionnement manuel. Merci
En fait, les distributions sont très différentes lors d'une sélection manuelle des humains 1-6 vs 7-9. Lors du fractionnement du pythome, il effectue un mélange comme celui mentionné ci-dessous, et les distributions sont presque identiques. Lorsque vous faites manuellement, ils sont très différents ... j'aimerais publier une image ici mais la barre d'outils manque pour le faire .. merci pour votre aide
Supposons que votre ensemble de données contienne ces données.
2 - 2 4 - 4#test data is subtraction
Supposons donc que vous souhaitiez une répartition à 50% du train. train_test_split le mélange comme ceci pour qu'il se généralise mieux
1 + 1 = 2 2 + 2 =4#only learned addition
Il sait donc quoi faire quand il voit ces données
2+2 4-4#since it learned both addition and subtraction
Mais lorsque vous les mélangez manuellement comme ceci
1+1=2 2-2= 0
Il ne sait pas quoi faire lorsqu'il voit ces données
1 + 1 = 2 2 + 2 = 4 4 - 4 = 0 2 - 2 = 0
J'espère que cela répond à votre question
Cela peut ressembler à une simple vérification mais ..
Dans le premier exemple, vous lisez des données à partir de 'data.csv', dans le deuxième exemple vous lisez à partir de 'train.csv' et 'test.csv' . Puisque vous dites que vous divisez le fichier manuellement, j'ai une question sur la façon dont cela a été fait. Si vous coupez simplement le fichier à la marque 2/3 et que vous le sauvegardez sous «train.csv» et le reste sous «test.csv», vous avez sans le savoir fait une hypothèse sur l'uniformité des données dans le fichier. Les fichiers de données peuvent avoir une structure ordonnée qui fausserait la formation ou le test, c'est pourquoi le train_test_split randomise les lignes. Si vous ne l'avez pas déjà fait, essayez d'abord de randomiser les lignes, puis d'écrire dans votre train et de tester le fichier csv pour vous assurer que vous disposez d'un ensemble de données homogène .
L'autre ligne la ligne 6 n'est peut-être pas à sa place:
X_test = testing_data.iloc[:,testing_data.columns.str.contains('|'.join(['x1','x2','x3']))]
Peut-être que les l_vars contiennent autre chose que ce que vous attendez. Peut-être devrait-il lire ce qui suit pour être plus cohérent.
X_test = testing_data.iloc[:,testing_data.columns.str.contains('|'.join(l_vars))]
bonne chance, faites-nous savoir si cela aide.
Comment faites-vous le
test.csv
ettrain.csv
dans l'exemple manuel? La répartition est-elle exactement la même entre les deux méthodes?le partage que je fais est manuellement sur les 2/3 premiers des enregistrements et le dernier 1/3. le split fait par la fonction split est cependant il le fait en interne, donc les ensembles sont différents mais de mêmes tailles .... je m'attends à ce que le r2score soit légèrement différent mais pas au point que c'est ... c'est à voir avec le types d'objets pas les données réelles je pense
Pourquoi faites-vous cela:
X_train = training_data.iloc [:, training_data.columns.str.contains ('|' .join (['x1', 'x2', 'x3'] ))] < / code>? Je pense que cela ne vous laisse peut-être rien ... avez-vous vérifié à quoi ressemble votre
X_train
après cette ligne? De plus, généralement,train_test_split
mélange les lignes au cas où il y aurait une sorte d'ordre dans l'ensemble de données, pour essayer d'obtenir une distribution uniforme des étiquettes.non cette partie fonctionne bien
Comment séparez-vous les données des fichiers?
train_test_split
randomise le fractionnement (échantillonne les données de manière uniforme). Si vous divisez le fichier à un endroit spécifique, vous risquez d'obtenir des données déséquilibrées (par exemple si les données sont triées pary
) ou d'autres problèmes similaires.Qu'est-ce que l_vars?
juste ['x1', 'x2', 'x3'] j'ai supprimé la première référence mais j'ai oublié la deuxième
Je pense que le problème est que la scission n'était pas aléatoire. Par exemple, disons que vous avez deux étiquettes, 0 et 1. Peut-être pour une raison, le premier fichier a 90% de zéros et 10% de uns et le fichier 1/3 a 100% de uns. Ensuite, l'algorithme essaiera de prédire le 1/3 avec un minimum de connaissances pour ceux-là. Donc, il donnera principalement des zéros, donc la précision sera très petite. La division de test de train divise l'ensemble de données de manière aléatoire. Si vous êtes sûr que la répartition était aléatoire, nous pouvons rechercher d'autres problèmes.
@BillyBonaros est sur la balle ici. Vous devez randomiser vos données de test / train, ou vous obtiendrez des résultats faussés.La principale question est de savoir pourquoi voulez-vous diviser vos données d'entraînement manuellement? Il est possible d'écrire un script qui randomise
data.csv
danstrain.csv
ettest.csv
mais vous pouvez aussi bien utiliser le < code> train_test_splitSi vous ajoutez le paramètre
shuffle = False
àX_train, X_test, y_train, y_test = train_test_split (x, y, test_size = 0.33)
obtenez-vous des résultats similaires?Si vous publiez vos csv dans une boîte de dépôt ou dans Google Drive, les gens peuvent confirmer leur hypothèse et être probablement plus utiles