Python - Was genau ist sklearn.pipeline.Pipeline?

117

Ich kann nicht herausfinden, wie das sklearn.pipeline.Pipelinegenau funktioniert.

Das Dokument enthält einige Erklärungen . Was meinen sie zum Beispiel mit:

Pipeline von Transformationen mit einem endgültigen Schätzer.

Was sind meine Fragen, um meine Frage klarer zu machen steps? Wie arbeiten Sie?

Bearbeiten

Dank der Antworten kann ich meine Frage klarer machen:

Wenn ich Pipeline aufrufe und als Schritte zwei Transformatoren und einen Schätzer übergebe, z.

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

Was passiert, wenn ich das nenne?

pipln.fit()
OR
pipln.fit_transform()

Ich kann nicht herausfinden, wie ein Schätzer ein Transformator sein kann und wie ein Transformator eingebaut werden kann.

farhawa
quelle
3
Nach meinem Verständnis hilft Ihnen die Pipeline dabei, mehrere Schritte des Lernprozesses zu automatisieren. Wie das Trainieren und Testen von Modellen oder die Auswahl von Features ... Wenn Sie also eine Regression mischen möchten, verwenden Sie diese beispielsweise, um einen Klassifikator zu füttern. Ihre Schritte sind das Training dieser Regression und dann des Klassifikators. Bearbeiten: Details hinzufügen
M0rkHaV
1
queirozf.com/entries/scikit-learn-pipeline-examples Ich fand das hilfreich
randomSampling

Antworten:

178

Transformer in Scikit-Learn - eine Klasse mit Fit- und Transformationsmethode oder Fit_transform-Methode.

Predictor - eine Klasse mit Fit- und Predict-Methoden oder fit_predict-Methode.

Pipeline ist nur ein abstrakter Begriff, es ist kein existierender ml-Algorithmus. In ML-Aufgaben müssen Sie häufig eine Folge verschiedener Transformationen (Satz von Merkmalen suchen, neue Merkmale generieren, nur einige gute Merkmale auswählen) des Rohdatensatzes ausführen, bevor Sie den endgültigen Schätzer anwenden.

Hier ist ein gutes Beispiel für die Verwendung von Pipelines. Die Pipeline bietet Ihnen eine einzige Schnittstelle für alle drei Transformationsschritte und den daraus resultierenden Schätzer. Es kapselt Transformatoren und Prädiktoren im Inneren, und jetzt können Sie Folgendes tun:

    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)

Nur mit:

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)

Mit Pipelines können Sie auf einfache Weise eine Rastersuche über Parametersätze für jeden Schritt dieses Meta-Schätzers durchführen. Wie im obigen Link beschrieben. Alle Schritte außer dem letzten müssen Transformationen sein, der letzte Schritt kann ein Transformator oder ein Prädiktor sein. Antwort zum Bearbeiten : Wenn Sie anrufen, wird pipln.fit()jeder Transformator in der Pipeline an die Ausgänge des vorherigen Transformators angepasst (der erste Transformator wird anhand des Rohdatensatzes gelernt). Der letzte Schätzer kann ein Transformator oder ein Prädiktor sein. Sie können fit_transform () in der Pipeline nur aufrufen, wenn Ihr letzter Schätzer ein Transformator ist (der fit_transform implementiert oder die Transformations- und Anpassungsmethoden separat implementiert). Sie können fit_predict () oder Predict () in der Pipeline nur aufrufen, wenn Ihr letzter Schätzer ist Prädiktor. Sie können also nicht fit_transform aufrufen oder in der Pipeline transformieren, deren letzter Schritt der Prädiktor ist.

Ibraim Ganiev
quelle
1
Was meinst du damit predicted = pipeline.fit(Xtrain).predict(Xtrain)?
Farhawa
@farhawa, Vorhersage von Klassen am Trainingsset.
Ibraim Ganiev
4
Warum hat das nicht mehr Stimmen? Es sollte ein Blog-Beitrag sein.
R Claven
1
@iamgin, Die Schnittstelle der meisten Scikit-Learn-Transformatoren erlaubt es nicht, die benötigten Spalten auszuwählen, die wir transformieren möchten. Sie können jedoch Ihre eigene "Artikelauswahl" schreiben, mit deren Hilfe Sie den Transformator nur mit den erforderlichen Spalten versorgen können. Hier ist ein gutes Beispiel mit ItemSelector und FeatureUnion scikit-learn.org/stable/auto_examples/…
Ibraim Ganiev
1
Möchten Sie im ersten Beispiel nicht vermeiden, dass Sie erneut zum Test-Set passen? Sollte es nicht nur transform statt fit_transform aufrufen? Und prognostiziert die Pipeline intern den Aufruf von fit_transform oder nur die Transformation? Kann es gesteuert werden?
Steven
18

Ich denke, dass M0rkHaV die richtige Idee hat. Scikit-Learn Pipeline - Klasse ist ein nützliches Werkzeug für die neben einem Schätzer zu einem Objekt mehrere verschiedene Transformatoren einkapseln, so dass Sie nur Ihre wichtigen Methoden einmal aufrufen müssen ( fit(), predict()usw.). Lassen Sie uns die beiden Hauptkomponenten aufschlüsseln:

  1. Transformatoren sind Klassen, die sowohl fit()als auch implementieren transform(). Möglicherweise kennen Sie einige der sklearn-Vorverarbeitungstools wie TfidfVectorizerund Binarizer. Wenn Sie sich die Dokumente für diese Vorverarbeitungstools ansehen, werden Sie feststellen, dass beide Methoden implementiert sind. Was ich ziemlich cool finde, ist, dass einige Schätzer auch als Transformationsschritte verwendet werden können, z LinearSVC.

  2. Schätzer sind Klassen, die sowohl fit()als als auch implementieren predict(). Sie werden feststellen, dass viele der Klassifikatoren und Regressionsmodelle beide Methoden implementieren, und als solche können Sie problemlos viele verschiedene Modelle testen. Es ist möglich, einen anderen Transformator als endgültigen Schätzer zu verwenden (dh er muss nicht unbedingt implementiert predict(), aber definitiv implementiert werden fit()). Das bedeutet nur, dass Sie nicht anrufen können predict().

Was Ihre Bearbeitung betrifft: Lassen Sie uns ein textbasiertes Beispiel durchgehen. Mit LabelBinarizer möchten wir eine Liste von Beschriftungen in eine Liste von Binärwerten umwandeln.

bin = LabelBinarizer()  #first we initialize

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

Wenn der Binarizer nun auf einige Daten angewendet wird, hat er eine Struktur namens classes_ , die die eindeutigen Klassen enthält, über die der Transformator "Bescheid weiß". Ohne fit()den Binarizer aufzurufen, hat er keine Ahnung, wie die Daten aussehen, sodass ein Aufruf transform()keinen Sinn ergibt. Dies gilt, wenn Sie die Liste der Klassen ausdrucken, bevor Sie versuchen, die Daten anzupassen.

print bin.classes_  

Beim Versuch wird folgende Fehlermeldung angezeigt:

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

Aber wenn Sie den Binarizer auf die montieren vec Liste setzen:

bin.fit(vec)

und versuche es erneut

print bin.classes_

Ich bekomme folgendes:

['cat' 'dog']


print bin.transform(vec)

Und jetzt, nach dem Aufruf von transform on the vec wir Objekt aufgerufen haben, erhalten wir Folgendes:

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

Für Schätzer, die als Transformatoren verwendet werden, verwenden wir den DecisionTreeKlassifikator als Beispiel für einen Merkmalsextraktor. Entscheidungsbäume sind aus vielen Gründen großartig. Für unsere Zwecke ist es jedoch wichtig, dass sie Funktionen bewerten können, die der Baum für die Vorhersage als nützlich erachtet hat. Wenn Sie transform()einen Entscheidungsbaum aufrufen , nimmt er Ihre Eingabedaten und findet heraus, was seiner Meinung nach die wichtigsten Funktionen sind. Sie können sich also vorstellen, Ihre Datenmatrix (n Zeilen mal m Spalten) in eine kleinere Matrix (n Zeilen mal k Spalten) umzuwandeln, in der die k Spalten die k wichtigsten Merkmale sind, die der Entscheidungsbaum gefunden hat.

NBartley
quelle
Was ist der Unterschied zwischen fit()und transform()ist die Transformatoren? Wie können Schätzer als Transformatoren verwendet werden?
Farhawa
2
fit()ist die Methode, die Sie aufrufen, um Ihren Transformator anzupassen oder zu „trainieren“, wie Sie es bei einem Klassifikator oder einem Regressionsmodell tun würden. Dies transform()ist die Methode, die Sie aufrufen, um die Eingabedaten tatsächlich in die Ausgabedaten umzuwandeln. Zum Beispiel kann ein Aufruf Binarizer.transform([8,2,2])(nach dem Anpassen!) Dazu führen [[1,0],[0,1],[0,1]]. In Bezug auf die Verwendung von Schätzern als Transformatoren werde ich ein kurzes Beispiel in meiner Antwort bearbeiten.
NBartley
9

ML-Algorithmen verarbeiten normalerweise tabellarische Daten. Möglicherweise möchten Sie diese Daten vor und nach Ihrem ML-Algorithmus vorverarbeiten und nachbearbeiten. Eine Pipeline ist eine Möglichkeit, diese Datenverarbeitungsschritte zu verketten.

Was sind ML-Pipelines und wie funktionieren sie?

Eine Pipeline besteht aus einer Reihe von Schritten, in denen Daten transformiert werden. Es stammt aus dem alten Entwurfsmuster "Pipe and Filter" (Sie können sich beispielsweise Unix-Bash-Befehle mit Pipes "|" oder Umleitungsoperatoren ">" vorstellen). Pipelines sind jedoch Objekte im Code. Daher haben Sie möglicherweise eine Klasse für jeden Filter (auch bekannt als jeder Pipeline-Schritt) und dann eine andere Klasse, um diese Schritte in der endgültigen Pipeline zu kombinieren. Einige Pipelines können andere Pipelines in Reihe oder parallel kombinieren, mehrere Ein- oder Ausgänge haben und so weiter. Wir betrachten Pipelines für maschinelles Lernen gerne als:

  • Rohr und Filter . Die Schritte der Pipeline verarbeiten Daten und verwalten ihren inneren Zustand, der aus den Daten gelernt werden kann.
  • Verbundwerkstoffe . Pipelines können verschachtelt sein: Beispielsweise kann eine gesamte Pipeline als einzelner Pipeline-Schritt in einer anderen Pipeline behandelt werden. Ein Pipeline-Schritt ist nicht unbedingt eine Pipeline, aber eine Pipeline ist per Definition selbst mindestens ein Pipeline-Schritt.
  • Directed Acyclic Graphs (DAG) . Die Ausgabe eines Pipeline-Schritts kann an viele andere Schritte gesendet werden, und dann können die resultierenden Ausgaben neu kombiniert werden und so weiter. Randnotiz: Obwohl Pipelines azyklisch sind, können sie mehrere Elemente nacheinander verarbeiten. Wenn sich ihr Status ändert (z. B. jedes Mal mit der Methode fit_transform), können sie als sich im Laufe der Zeit immer wieder entfaltend angesehen werden, wobei ihre Zustände beibehalten werden (denken Sie wie) ein RNN). Dies ist eine interessante Möglichkeit, Pipelines für das Online-Lernen zu sehen, wenn sie in Produktion gehen und auf mehr Daten trainiert werden.

Methoden einer Scikit-Learn-Pipeline

Pipelines (oder Schritte in der Pipeline) müssen diese beiden Methoden haben :

  • " Fit ", um anhand der Daten zu lernen und den Zustand zu erfassen (z. B. die neuronalen Gewichte des neuronalen Netzwerks sind solche Zustände)
  • " Transformieren " (oder "Vorhersagen"), um die Daten tatsächlich zu verarbeiten und eine Vorhersage zu generieren.

Es ist auch möglich, diese Methode aufzurufen, um beide zu verketten:

  • " Fit_transform " zum Anpassen und anschließenden Transformieren der Daten, jedoch in einem Durchgang, was potenzielle Codeoptimierungen ermöglicht, wenn die beiden Methoden direkt nacheinander ausgeführt werden müssen.

Probleme der Klasse sklearn.pipeline.Pipeline

Das Designmuster „Rohr und Filter“ von Scikit-Learn ist einfach wunderschön. Aber wie kann man es für Deep Learning, AutoML und komplexe Pipelines auf Produktionsebene verwenden?

Scikit-Learn hatte seine erste Veröffentlichung im Jahr 2007, eine Zeit vor dem tiefen Lernen . Es ist jedoch eine der bekanntesten und am weitesten verbreiteten Bibliotheken für maschinelles Lernen und wächst weiter. Darüber hinaus wird das Pipe and Filter-Entwurfsmuster als Software-Architekturstil verwendet. Dies macht Scikit-Learn so fabelhaft und bietet zusätzlich gebrauchsfertige Algorithmen. Es gibt jedoch massive Probleme, wenn es darum geht, Folgendes zu tun, was wir bereits 2020 tun sollten:

  • Automatisches maschinelles Lernen (AutoML),
  • Deep Learning Pipelines,
  • Komplexere Pipelines für maschinelles Lernen.

Lösungen, die wir für die Probleme von Scikit-Learn gefunden haben

Natürlich ist Scikit-Learn sehr praktisch und gut gebaut. Es muss jedoch aktualisiert werden. Hier sind unsere Lösungen mit Neuraxle , um Scikit-Learn in modernen Computerprojekten frisch und nutzbar zu machen!

Zusätzliche Pipeline-Methoden und -Funktionen, die von Neuraxle angeboten werden

Hinweis: Wenn für einen Schritt einer Pipeline keine der Anpassungs- oder Transformationsmethoden erforderlich ist , kann er von NonFittableMixin oder NonTransformableMixin erben , um eine Standardimplementierung einer dieser Methoden bereitzustellen , um nichts zu tun.

Als Starter können Pipelines oder deren Schritte optional auch folgende Methoden definieren :

  • " Setup ", das bei jedem Schritt die "Setup" -Methode aufruft. Wenn ein Schritt beispielsweise ein neuronales TensorFlow-, PyTorch- oder Keras-Netzwerk enthält, können die Schritte ihre neuronalen Diagramme erstellen und sie vor dem Anpassen in der Setup-Methode bei der GPU registrieren. Es wird aus mehreren Gründen davon abgeraten, die Diagramme direkt in den Konstruktoren der Schritte zu erstellen, z. B. wenn die Schritte kopiert werden, bevor sie mehrmals mit verschiedenen Hyperparametern in einem automatischen Algorithmus für maschinelles Lernen ausgeführt werden, der nach den besten Hyperparametern für Sie sucht.
  • " Teardown ", das Gegenteil der "Setup" -Methode: Es löscht Ressourcen.

Die folgenden Methoden werden standardmäßig bereitgestellt , um die Verwaltung von Hyperparametern zu ermöglichen:

  • " Get_hyperparams " gibt Ihnen ein Wörterbuch der Hyperparameter zurück. Wenn Ihre Pipeline mehr Pipelines enthält (verschachtelte Pipelines), werden die Schlüssel der Hyperparameter mit doppelten Unterstrichen "__" getrennt.
  • Mit „ set_hyperparams “ können Sie neue Hyperparameter im selben Format festlegen, in dem Sie sie erhalten.
  • Mit " get_hyperparams_space " können Sie den Raum des Hyperparameters abrufen , der nicht leer ist, wenn Sie einen definiert haben. Der einzige Unterschied zu "get_hyperparams" besteht darin, dass Sie statistische Verteilungen als Werte anstelle eines genauen Werts erhalten. Zum Beispiel könnte ein Hyperparameter für die Anzahl der Schichten a sein, RandInt(1, 3)was 1 bis 3 Schichten bedeutet. Sie können .rvs()dieses Diktat aufrufen , um einen Wert zufällig auszuwählen und an „set_hyperparams“ zu senden, um zu versuchen, darauf zu trainieren.
  • " Set_hyperparams_space " kann verwendet werden, um einen neuen Raum unter Verwendung der gleichen Hyperparameter-Verteilungsklassen wie in "get_hyperparams_space" festzulegen.

Weitere Informationen zu unseren Lösungsvorschlägen finden Sie in den Einträgen in der großen Liste mit den obigen Links.

Guillaume Chevalier
quelle