Python - Qu'est-ce que sklearn.pipeline.Pipeline exactement?

118

Je ne peux pas comprendre comment cela sklearn.pipeline.Pipelinefonctionne exactement.

Il y a quelques explications dans le doc . Par exemple, que signifient-ils par:

Pipeline de transformations avec un estimateur final.

Pour clarifier ma question, qu'est-ce que c'est steps? Comment travaillent-ils?

Éditer

Grâce aux réponses, je peux clarifier ma question:

Quand j'appelle pipeline et que je passe, en étapes, deux transformateurs et un estimateur, par exemple:

pipln = Pipeline([("trsfm1",transformer_1),
                  ("trsfm2",transformer_2),
                  ("estmtr",estimator)])

Que se passe-t-il quand j'appelle ça?

pipln.fit()
OR
pipln.fit_transform()

Je ne peux pas comprendre comment un estimateur peut être un transformateur et comment un transformateur peut être installé.

farhawa
la source
3
D'après ce que j'ai compris, le pipeline vous aide à automatiser plusieurs étapes du processus d'apprentissage. Comme la formation et le test de modèles ou la sélection de fonctionnalités ... Donc si vous voulez mélanger une régression puis l'utiliser pour alimenter un classificateur par exemple, vos étapes seront l'apprentissage de cette régression puis du classificateur. edit: ajouter des détails
M0rkHaV
1
queirozf.com/entries/scikit-learn-pipeline-examples J'ai trouvé cela utile
randomSampling

Réponses:

180

Transformer dans scikit-learn - une classe qui a une méthode fit et transform, ou une méthode fit_transform.

Predictor - une classe qui a des méthodes d'ajustement et de prédiction, ou une méthode fit_predict.

Le pipeline n'est qu'une notion abstraite, ce n'est pas un algorithme ml existant. Souvent, dans les tâches de ML, vous devez effectuer une séquence de différentes transformations (trouver un ensemble d'entités, générer de nouvelles entités, ne sélectionner que quelques bonnes caractéristiques) de l'ensemble de données brutes avant d'appliquer l'estimateur final.

Voici un bon exemple d'utilisation de Pipeline. Pipeline vous offre une interface unique pour les 3 étapes de transformation et l'estimateur résultant. Il encapsule les transformateurs et les prédicteurs à l'intérieur, et vous pouvez maintenant faire quelque chose comme:

    vect = CountVectorizer()
    tfidf = TfidfTransformer()
    clf = SGDClassifier()

    vX = vect.fit_transform(Xtrain)
    tfidfX = tfidf.fit_transform(vX)
    predicted = clf.fit_predict(tfidfX)

    # Now evaluate all steps on test set
    vX = vect.fit_transform(Xtest)
    tfidfX = tfidf.fit_transform(vX)
    predicted = clf.fit_predict(tfidfX)

Avec juste:

pipeline = Pipeline([
    ('vect', CountVectorizer()),
    ('tfidf', TfidfTransformer()),
    ('clf', SGDClassifier()),
])
predicted = pipeline.fit(Xtrain).predict(Xtrain)
# Now evaluate all steps on test set
predicted = pipeline.predict(Xtest)

Avec les pipelines, vous pouvez facilement effectuer une recherche de grille sur un ensemble de paramètres pour chaque étape de ce méta-estimateur. Comme décrit dans le lien ci-dessus. Toutes les étapes sauf la dernière doivent être des transformations, la dernière étape peut être un transformateur ou un prédicteur. Réponse à modifier : Lorsque vous appelez pipln.fit()- chaque transformateur à l'intérieur du pipeline sera installé sur les sorties du transformateur précédent (le premier transformateur est appris sur le jeu de données brutes). Le dernier estimateur peut être un transformateur ou un prédicteur, vous pouvez appeler fit_transform () sur le pipeline uniquement si votre dernier estimateur est un transformateur (qui implémente fit_transform, ou les méthodes de transformation et d'ajustement séparément), vous pouvez appeler fit_predict () ou prédire () sur le pipeline uniquement si votre dernier estimateur est le prédicteur. Vous ne pouvez donc tout simplement pas appeler fit_transform ou transformer sur un pipeline, dont la dernière étape est le prédicteur.

Ibraim Ganiev
la source
1
Que voulez-vous dire predicted = pipeline.fit(Xtrain).predict(Xtrain)?
farhawa
@farhawa, prédire les classes sur l'ensemble d'entraînement.
Ibraim Ganiev
4
Pourquoi cela n'a-t-il pas plus de votes? Ce devrait être un article de blog.
R Claven
1
@iamgin, l'interface de la plupart des transformateurs scikit-learn ne permet pas de choisir les colonnes nécessaires que nous voulons transformer. Mais vous pouvez écrire votre propre "Item Selector", qui vous aidera à alimenter le transformateur uniquement avec les colonnes nécessaires. Voici un bon exemple avec ItemSelector et FeatureUnion scikit-learn.org/stable/auto_examples
Ibraim Ganiev
1
Dans le premier exemple, ne voulez-vous pas éviter de réajuster le jeu de test? Ne devrait-il pas seulement appeler transform au lieu de fit_transform? Et de même, le pipeline prédit-il l'appel interne fit_transform ou simplement transformer? Peut-il être contrôlé?
Steven
18

Je pense que M0rkHaV a la bonne idée. La classe de pipeline scikit-learn est un outil utile pour encapsuler plusieurs transformateurs différents à côté d' un estimateur en un seul objet, de sorte que vous suffit d'appeler vos méthodes importantes une fois ( fit(), predict(), etc.). Décomposons les deux principaux composants:

  1. Les transformateurs sont des classes qui implémentent à la fois fit()et transform(). Vous connaissez peut-être certains des outils de prétraitement sklearn, commeTfidfVectorizer et Binarizer. Si vous regardez la documentation de ces outils de prétraitement, vous verrez qu'ils implémentent ces deux méthodes. Ce que je trouve plutôt cool, c'est que certains estimateurs peuvent également être utilisés comme étapes de transformation, par exemple LinearSVC!

  2. Les estimateurs sont des classes qui implémentent à la fois fit()et predict(). Vous constaterez que de nombreux classificateurs et modèles de régression implémentent ces deux méthodes et, en tant que tels, vous pouvez facilement tester de nombreux modèles différents. Il est possible d'utiliser un autre transformateur comme estimateur final (c'est-à-dire qu'il n'implémente pas nécessairement predict(), mais qu'il implémente définitivement fit()). Tout cela signifie que vous ne pourrez pas appeler predict().

Quant à votre modification: passons par un exemple textuel. En utilisant LabelBinarizer, nous voulons transformer une liste d'étiquettes en une liste de valeurs binaires.

bin = LabelBinarizer()  #first we initialize

vec = ['cat', 'dog', 'dog', 'dog'] #we have our label list we want binarized

Maintenant, lorsque le binarizer est installé sur certaines données, il aura une structure appelée classes_qui contient les classes uniques que le transformateur «connaît». Sans appelerfit() le binarizer n'a aucune idée de ce à quoi ressemblent les données, donc appeler transform()n'aurait aucun sens. Cela est vrai si vous imprimez la liste des classes avant d'essayer d'ajuster les données.

print bin.classes_  

J'obtiens l'erreur suivante en essayant ceci:

AttributeError: 'LabelBinarizer' object has no attribute 'classes_'

Mais lorsque vous installez le binarizer sur le vec liste:

bin.fit(vec)

et essayez à nouveau

print bin.classes_

J'obtiens ce qui suit:

['cat' 'dog']


print bin.transform(vec)

Et maintenant, après avoir appelé transform sur le vec objet, nous obtenons ce qui suit:

[[0]
 [1]
 [1]
 [1]]

Quant aux estimateurs utilisés comme transformateurs, utilisons le DecisionTreeclassifieur comme exemple d'extraction de caractéristiques. Les arbres de décision sont excellents pour de nombreuses raisons, mais pour nos besoins, ce qui est important, c'est qu'ils ont la capacité de classer les fonctionnalités que l' arbre a trouvées utiles pour prédire. Lorsque vous appelez transform()un arbre de décision, il prend vos données d'entrée et trouve ce qu'il pense être les fonctionnalités les plus importantes. Vous pouvez donc y penser en transformant votre matrice de données (n lignes par m colonnes) en une matrice plus petite (n lignes par k colonnes), où les k colonnes sont les k caractéristiques les plus importantes trouvées par l'arbre de décision.

NBartley
la source
Quelle est la différence entre fit()et transform()est les Transformers? , comment les estimateurs peuvent-ils être utilisés comme transformateurs?
farhawa
2
fit()est la méthode que vous appelez pour ajuster ou «entraîner» votre transformateur, comme vous le feriez pour un classificateur ou un modèle de régression. En ce qui concerne transform(), c'est la méthode que vous appelez pour transformer réellement les données d'entrée en données de sortie. Par exemple, un appel Binarizer.transform([8,2,2])(après ajustement!) Peut entraîner [[1,0],[0,1],[0,1]]. Quant à l'utilisation d'estimateurs comme transformateurs, je modifierai un court exemple dans ma réponse.
NBartley
9

Les algorithmes de ML traitent généralement des données tabulaires. Vous souhaiterez peut-être effectuer un prétraitement et un post-traitement de ces données avant et après votre algorithme ML. Un pipeline est un moyen d'enchaîner ces étapes de traitement des données.

Que sont les pipelines ML et comment fonctionnent-ils?

Un pipeline est une série d'étapes dans lesquelles les données sont transformées. Il vient de l'ancien modèle de conception "pipe and filter" (par exemple, vous pourriez penser à des commandes bash unix avec des tubes "|" ou des opérateurs de redirection ">"). Cependant, les pipelines sont des objets dans le code. Ainsi, vous pouvez avoir une classe pour chaque filtre (aka chaque étape du pipeline), puis une autre classe pour combiner ces étapes dans le pipeline final. Certains pipelines peuvent combiner d'autres pipelines en série ou en parallèle, avoir plusieurs entrées ou sorties, etc. Nous aimons voir les pipelines de Machine Learning comme:

  • Tuyau et filtres . Les étapes du pipeline traitent les données et gèrent leur état interne qui peut être appris à partir des données.
  • Composites . Les pipelines peuvent être imbriqués: par exemple, un pipeline entier peut être traité comme une seule étape de pipeline dans un autre pipeline. Une étape de pipeline n'est pas nécessairement un pipeline, mais un pipeline est lui-même au moins une étape de pipeline par définition.
  • Graphiques acycliques dirigés (DAG) . La sortie d'une étape de pipeline peut être envoyée à de nombreuses autres étapes, puis les sorties résultantes peuvent être recombinées, et ainsi de suite. Note latérale: bien que les pipelines soient acycliques, ils peuvent traiter plusieurs éléments un par un, et si leur état change (par exemple: en utilisant la méthode fit_transform à chaque fois), ils peuvent être considérés comme se déroulant de manière récurrente dans le temps, en conservant leurs états (pensez comme un RNN). C'est une façon intéressante de voir les pipelines pour faire de l'apprentissage en ligne lors de leur mise en production et de leur formation sur plus de données.

Méthodes d'un pipeline Scikit-Learn

Les pipelines (ou les étapes du pipeline) doivent avoir ces deux méthodes :

  • « Fit » pour apprendre sur les données et acquérir l'état (par exemple: les poids neuronaux du réseau neuronal sont un tel état)
  • « Transformer » (ou «prédire») pour traiter réellement les données et générer une prédiction.

Il est également possible d'appeler cette méthode pour enchaîner les deux:

  • « Fit_transform » pour ajuster puis transformer les données, mais en un seul passage, ce qui permet des optimisations potentielles du code lorsque les deux méthodes doivent être effectuées l'une après l'autre directement.

Problèmes de la classe sklearn.pipeline.Pipeline

Le modèle de conception «tuyau et filtre» de Scikit-Learn est tout simplement magnifique. Mais comment l'utiliser pour le Deep Learning, AutoML et les pipelines complexes de niveau production?

Scikit-Learn a eu sa première version en 2007, qui était une ère pré-deep learning . Cependant, c'est l'une des bibliothèques d'apprentissage automatique les plus connues et les plus adoptées, et elle continue de croître. En plus de tout, il utilise le modèle de conception Pipe and Filter comme un style architectural logiciel - c'est ce qui rend Scikit-Learn si fabuleux, ajouté au fait qu'il fournit des algorithmes prêts à l'emploi. Cependant, il a d'énormes problèmes lorsqu'il s'agit de faire ce qui suit, ce que nous devrions pouvoir faire en 2020 déjà:

  • Apprentissage automatique automatique (AutoML),
  • Pipelines d'apprentissage profond,
  • Pipelines d'apprentissage automatique plus complexes.

Les solutions que nous avons trouvées aux problèmes de Scikit-Learn

Bien sûr, Scikit-Learn est très pratique et bien construit. Cependant, il a besoin d'un rafraîchissement. Voici nos solutions avec Neuraxle pour rendre Scikit-Learn frais et utilisable dans les projets informatiques modernes!

Méthodes et fonctionnalités de pipeline supplémentaires offertes par Neuraxle

Remarque: si une étape d'un pipeline n'a pas besoin d'avoir l'une des méthodes fit ou transform, elle pourrait hériter de NonFittableMixin ou NonTransformableMixin pour recevoir une implémentation par défaut de l'une de ces méthodes pour ne rien faire.

Pour commencer, il est possible pour les pipelines ou leurs étapes de définir éventuellement ces méthodes :

  • « Setup » qui appellera la méthode «setup» à chacune de ses étapes. Par exemple, si une étape contient un réseau neuronal TensorFlow, PyTorch ou Keras, les étapes peuvent créer leurs graphiques neuronaux et les enregistrer sur le GPU dans la méthode «setup» avant ajustement. Il est déconseillé de créer les graphiques directement dans les constructeurs des étapes pour plusieurs raisons, par exemple si les étapes sont copiées avant de s'exécuter plusieurs fois avec différents hyperparamètres dans un algorithme de Machine Learning automatique qui recherche les meilleurs hyperparamètres pour vous.
  • « Teardown », qui est l'opposé de la méthode «setup»: il efface les ressources.

Les méthodes suivantes sont fournies par défaut pour permettre la gestion des hyperparamètres:

  • « Get_hyperparams » vous renverra un dictionnaire des hyperparamètres. Si votre pipeline contient plus de pipelines (pipelines imbriqués), les clés des hyperparamètres sont enchaînées avec des doubles traits de soulignement «__» séparateurs.
  • « Set_hyperparams » vous permettra de définir de nouveaux hyperparamètres dans le même format que lorsque vous les obtenez.
  • « Get_hyperparams_space » vous permet d'obtenir l'espace de l'hyperparamètre, qui ne sera pas vide si vous en avez défini un. Donc, la seule différence avec «get_hyperparams» ici est que vous obtiendrez des distributions statistiques sous forme de valeurs au lieu d'une valeur précise. Par exemple, un hyperparamètre pour le nombre de couches pourrait être a, RandInt(1, 3)ce qui signifie 1 à 3 couches. Vous pouvez faire appel .rvs()à ce dict pour choisir une valeur au hasard et l'envoyer à «set_hyperparams» pour essayer de vous entraîner dessus.
  • « Set_hyperparams_space » peut être utilisé pour définir un nouvel espace en utilisant les mêmes classes de distribution d'hyperparamètres que dans «get_hyperparams_space».

Pour plus d'informations sur nos solutions suggérées, lisez les entrées dans la grande liste avec les liens ci-dessus.

Guillaume Chevalier
la source