Python - Czym dokładnie jest sklearn.pipeline.Pipeline?

118

Nie wiem, jak to sklearn.pipeline.Pipelinedokładnie działa.

W dokumencie znajduje się kilka wyjaśnień . Na przykład co oznaczają przez:

Potok przekształceń z estymatorem końcowym.

Aby wyjaśnić moje pytanie, co to jest steps? Jak oni pracują?

Edytować

Dzięki odpowiedziom mogę wyjaśnić moje pytanie:

Kiedy wywołuję pipeline i przechodzę, jako kroki, dwa transformatory i jeden estymator, np:

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

Co się stanie, kiedy to zadzwonię?

pipln.fit()
OR
pipln.fit_transform()

Nie mogę zrozumieć, jak estymator może być transformatorem i jak można go zamontować.

farhawa
źródło
3
Z tego, co zrozumiałem, potok pomaga zautomatyzować kilka etapów procesu uczenia się. Takich jak szkolenie i testowanie modeli lub wybór cech ... Więc jeśli chcesz mieszać regresję, a następnie użyj jej do zasilenia na przykład klasyfikatora, twoje kroki będą trenowaniem tej regresji, a następnie klasyfikatora. edycja: dodaj szczegóły
M0rkHaV
1
queirozf.com/entries/scikit-learn-pipeline-examples Znalazłem to pomocne
randomSampling

Odpowiedzi:

180

Transformer w scikit-learn - jakaś klasa, która ma metodę fit and transform lub metodę fit_transform.

Predictor - klasa, która ma metody dopasowywania i przewidywania lub metoda fit_predict.

Pipeline to tylko abstrakcyjne pojęcie, nie jest to jakiś istniejący algorytm ML. Często w zadaniach ML trzeba wykonać sekwencję różnych transformacji (znaleźć zestaw cech, wygenerować nowe cechy, wybrać tylko niektóre dobre cechy) surowego zbioru danych przed zastosowaniem ostatecznego estymatora.

Oto dobry przykład użycia rurociągu. Pipeline zapewnia jeden interfejs dla wszystkich 3 etapów transformacji i estymatora wynikowego. Hermetyzuje wewnątrz transformatory i predyktory, a teraz możesz zrobić coś takiego:

    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)

Tylko z:

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)

Dzięki potokom można łatwo przeprowadzić wyszukiwanie w siatce zestawu parametrów dla każdego kroku tego meta-estymatora. Jak opisano w linku powyżej. Wszystkie kroki z wyjątkiem ostatniego muszą być transformacjami, ostatni krok może być transformatorem lub predyktorem. Odpowiedź do edycji : Kiedy zadzwonisz pipln.fit()- każdy transformator wewnątrz rurociągu zostanie zamontowany na wyjściach poprzedniego transformatora (pierwszy transformator jest uczony na surowym zestawie danych). Ostatnim estymatorem może być transformator lub predyktor, możesz wywołać fit_transform () na potoku tylko wtedy, gdy ostatnim estymatorem jest transformer (który implementuje metody fit_transform lub transform and fit oddzielnie), możesz wywołać fit_predict () lub Predict () na potoku tylko wtedy, gdy Twoim ostatnim estymatorem jest predyktor. Więc po prostu nie możesz wywołać fit_transform ani transformacji na potoku, którego ostatnim krokiem jest predyktor.

Ibraim Ganiev
źródło
1
Co masz na myśli predicted = pipeline.fit(Xtrain).predict(Xtrain)?
farhawa
@farhawa, przewidując zajęcia na zestawie treningowym.
Ibraim Ganiev
4
Dlaczego to nie ma więcej głosów? Powinien to być wpis na blogu.
R Claven
1
@iamgin, Interfejs większości transformatorów scikit-learn nie pozwala na wybranie potrzebnych kolumn, które chcemy przekształcić. Ale możesz napisać swój własny "Selektor pozycji", który pomoże ci zasilić transformator tylko potrzebnymi kolumnami. Oto dobry przykład z ItemSelector i FeatureUnion scikit-learn.org/stable/auto_examples/…
Ibraim
1
Czy w pierwszym przykładzie nie chcesz uniknąć ponownego dopasowania do zestawu testowego? Czy nie powinno tylko wywoływać transformację zamiast fit_transform? I podobnie, czy potok przewiduje wewnętrzne wywołanie fit_transform, czy po prostu transformację? Czy można to kontrolować?
Steven
18

Myślę, że M0rkHaV ma dobry pomysł. Scikit-learn za klasa rurociągu jest użytecznym narzędziem do enkapsulacji wielu różnych transformatorów wraz estymatora do jednego obiektu, tak że trzeba tylko zadzwonić ważnych metod Once ( fit(), predict()itp). Podzielmy dwa główne komponenty:

  1. Transformatory to klasy, które implementują zarówno fit()i transform(). Być może znasz niektóre narzędzia do wstępnego przetwarzania sklearn, takie jak TfidfVectorizeri Binarizer. Jeśli spojrzysz na dokumentację tych narzędzi do wstępnego przetwarzania, zobaczysz, że implementują one obie te metody. To, co uważam za całkiem fajne, to fakt, że niektóre estymatory mogą być również używane jako kroki transformacji, np. LinearSVC!

  2. Estymatory to klasy, które implementują zarówno fit()i predict(). Przekonasz się, że wiele klasyfikatorów i modeli regresji implementuje obie te metody, dzięki czemu możesz łatwo przetestować wiele różnych modeli. Możliwe jest użycie innego transformatora jako ostatecznego estymatora (tj. Niekoniecznie implementuje predict(), ale zdecydowanie implementuje fit()). Wszystko to oznacza, że ​​nie byłbyś w stanie zadzwonić predict().

Jeśli chodzi o twoją edycję: przejdźmy przez przykład tekstowy. Korzystając z LabelBinarizer, chcemy zmienić listę etykiet w listę wartości binarnych.

bin = LabelBinarizer()  #first we initialize

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

Teraz, gdy binarizer jest dopasowany do pewnych danych, będzie miał strukturę o nazwie, classes_która zawiera unikalne klasy, o których „wie” transformator. Bez wywołania fit()binarizera nie ma pojęcia, jak wyglądają dane, więc wywołanie transform()nie miałoby sensu. Dzieje się tak, jeśli wydrukujesz listę klas przed próbą dopasowania danych.

print bin.classes_  

Podczas próby pojawia się następujący błąd:

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

Ale kiedy zmieścisz binarizer na vecliście:

bin.fit(vec)

i spróbuj ponownie

print bin.classes_

Otrzymuję następujące informacje:

['cat' 'dog']


print bin.transform(vec)

A teraz, po wywołaniu transformacji na vecobiekcie, otrzymujemy:

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

Jeśli chodzi o estymatory używane jako transformatory, użyjmy DecisionTreeklasyfikatora jako przykładu ekstraktora cech. Drzewa decyzyjne są świetne z wielu powodów, ale dla naszych celów ważne jest to, że mają one możliwość rangowania cech, które drzewo uznało za przydatne do przewidywania. Kiedy wywołujesz transform()drzewo decyzyjne, pobierze ono twoje dane wejściowe i znajdzie to , co uważa za najważniejsze funkcje. Możesz więc pomyśleć o przekształceniu macierzy danych (n wierszy na m kolumn) w mniejszą macierz (n wierszy na k kolumn), gdzie k kolumn to k najważniejszych cech znalezionych przez Drzewo decyzyjne.

NBartley
źródło
Jaka jest różnica między fit()i transform()jest Transformers? , jak estymatory mogą być używane jako transformatory?
farhawa
2
fit()to metoda, którą wywołujesz, aby dopasować lub „wytrenować” swój transformator, tak jak w przypadku modelu klasyfikatora lub modelu regresji. Jeśli chodzi o transform(), jest to metoda, którą wywołujesz, aby faktycznie przekształcić dane wejściowe w dane wyjściowe. Na przykład wywołanie Binarizer.transform([8,2,2])(po dopasowaniu!) Może spowodować [[1,0],[0,1],[0,1]]. Jeśli chodzi o używanie estymatorów jako transformatorów, zredaguję krótki przykład w mojej odpowiedzi.
NBartley
9

Algorytmy ML zazwyczaj przetwarzają dane tabelaryczne. Możesz chcieć wykonać wstępne przetwarzanie i przetwarzanie końcowe tych danych przed i po algorytmie ML. Potok to sposób na połączenie etapów przetwarzania danych.

Co to są potoki ML i jak działają?

Potok to seria kroków, w których dane są przekształcane. Pochodzi ze starego wzorca projektowego „potok i filtr” (na przykład można pomyśleć o poleceniach unix bash z potokami „|” lub operatorach przekierowania „>”). Jednak potoki są obiektami w kodzie. W związku z tym możesz mieć klasę dla każdego filtru (inaczej każdy krok potoku), a następnie inną klasę, aby połączyć te kroki w ostateczny potok. Niektóre potoki mogą łączyć inne potoki szeregowo lub równolegle, mieć wiele wejść lub wyjść i tak dalej. Lubimy postrzegać potoki uczenia maszynowego jako:

  • Rury i filtry . Kroki potoku przetwarzają dane i zarządzają swoim stanem wewnętrznym, którego można się nauczyć z danych.
  • Kompozyty . Potoki mogą być zagnieżdżane: na przykład cały potok można traktować jako pojedynczy krok w innym potoku. Krok potoku niekoniecznie jest potokiem, ale potok sam w sobie jest przynajmniej z definicji krokiem potoku.
  • Skierowane grafy acykliczne (DAG) . Dane wyjściowe kroku potoku mogą być wysyłane do wielu innych kroków, a następnie wynikowe dane wyjściowe mogą być ponownie łączone i tak dalej. Na marginesie: mimo że potoki są acykliczne, mogą przetwarzać wiele elementów jeden po drugim, a jeśli ich stan zmienia się (np. Za każdym razem za pomocą metody fit_transform), to można je postrzegać jako cyklicznie rozwijające się w czasie, zachowując swoje stany (pomyśl numer RNN). To ciekawy sposób, aby zobaczyć potoki do uczenia się online, gdy wprowadzasz je do produkcji i trenujesz je na większej ilości danych.

Metody rurociągu Scikit-Learn

Rurociągi (lub stopnie w rurociągu) muszą mieć te dwie metody :

  • Zdatny ” do uczenia się na danych i uzyskiwania stanu (np .: wagi neuronowe sieci neuronowej są takim stanem)
  • Przekształcić ” (lub „przewidzieć”), aby faktycznie przetworzyć dane i wygenerować prognozę.

Możliwe jest również wywołanie tej metody w celu połączenia obu:

  • Fit_transform ”, aby dopasować, a następnie przekształcić dane, ale w jednym przebiegu, co pozwala na potencjalną optymalizację kodu, gdy dwie metody muszą być wykonywane bezpośrednio jedna po drugiej.

Problemy klasy sklearn.pipeline.Pipeline

Wzorzec projektowy „rurka i filtr” Scikit-Learn jest po prostu piękny. Ale jak go używać do Deep Learning, AutoML i złożonych potoków na poziomie produkcji?

Scikit-Learn wydało swoje pierwsze wydanie w 2007 roku, czyli w erze przed głębokim uczeniem się . Jest to jednak jedna z najbardziej znanych i przyjętych bibliotek uczenia maszynowego i wciąż się rozwija. Ponadto wykorzystuje wzorzec projektowy Pipe and Filter jako styl architektoniczny oprogramowania - to właśnie sprawia, że ​​Scikit-Learn jest tak fantastyczny, a ponadto zapewnia algorytmy gotowe do użycia. Ma jednak ogromne problemy, jeśli chodzi o wykonanie następujących czynności, które powinniśmy być w stanie zrobić już w 2020 roku:

  • Automatyczne uczenie maszynowe (AutoML),
  • Potoki uczenia głębokiego,
  • Bardziej złożone potoki uczenia maszynowego.

Rozwiązania, które znaleźliśmy dla tych problemów Scikit-Learn

Z pewnością Scikit-Learn jest bardzo wygodny i dobrze zbudowany. Jednak wymaga odświeżenia. Oto nasze rozwiązania z Neuraxle, dzięki którym Scikit-Learn jest świeży i przydatny w nowoczesnych projektach komputerowych!

Dodatkowe metody i funkcje potoku oferowane przez Neuraxle

Uwaga: jeśli krok potoku nie musi mieć jednej z metod dopasowania lub transformacji, może dziedziczyć po NonFittableMixin lub NonTransformableMixin, aby zapewnić domyślną implementację jednej z tych metod, aby nic nie robić.

Na początek możliwe jest, aby rurociągi lub ich stopnie opcjonalnie zdefiniowały również te metody :

  • Setup ”, który wywoła metodę „setup” na każdym etapie. Na przykład, jeśli krok zawiera sieć neuronową TensorFlow, PyTorch lub Keras, kroki mogą tworzyć ich grafy neuronowe i rejestrować je w GPU metodą „konfiguracji” przed dopasowaniem. Odradza się tworzenie wykresów bezpośrednio w konstruktorach kroków z kilku powodów, na przykład jeśli kroki są kopiowane przed wielokrotnym uruchomieniem z różnymi hiperparametrami w ramach algorytmu automatycznego uczenia maszynowego, który wyszukuje najlepsze hiperparametry dla Ciebie.
  • Porzucenie ”, które jest przeciwieństwem metody „konfiguracji”: usuwa zasoby.

Do Następujące metody są domyślnie w celu umożliwienia zarządzania hiperparametrów:

  • Get_hyperparams ” zwróci słownik hiperparametrów. Jeśli twój potok zawiera więcej potoków (potoki zagnieżdżone), wówczas klucze hiperparametru są połączone w łańcuch z podwójnymi podkreśleniami „__”.
  • Set_hyperparams ” pozwoli ci ustawić nowe hiperparametry w tym samym formacie, w jakim je otrzymałeś.
  • Get_hyperparams_space ” pozwala uzyskać przestrzeń hiperparametru, która nie będzie pusta, jeśli ją zdefiniujesz. Tak więc jedyną różnicą w przypadku „get_hyperparams” jest to, że otrzymujesz rozkłady statystyk jako wartości zamiast dokładnych wartości. Na przykład jednym hiperparametrem dla liczby warstw może być a, RandInt(1, 3)co oznacza od 1 do 3 warstw. Możesz wywołać .rvs()ten dykt, aby wybrać losowo wartość i wysłać ją do „set_hyperparams”, aby spróbować ją przetrenować.
  • Set_hyperparams_space ” może służyć do ustawiania nowej przestrzeni przy użyciu tych samych klas dystrybucji hiperparametrów, co w „get_hyperparams_space”.

Aby uzyskać więcej informacji na temat naszych sugerowanych rozwiązań, przeczytaj wpisy na dużej liście z linkami powyżej.

Guillaume Chevalier
źródło