SVM za pomocą scikit learn działa bez końca i nigdy nie kończy wykonywania


76

Próbuję uruchomić SVR przy użyciu scikit learn (python) na zbiorze danych szkoleniowych posiadającym 595605 wierszy i 5 kolumn (funkcji) oraz testowym zbiorze danych posiadającym 397070 wierszy. Dane zostały wstępnie przetworzone i uregulowane.

Jestem w stanie z powodzeniem uruchomić przykłady testowe, ale po uruchomieniu przy użyciu mojego zestawu danych i pozostawieniu go na ponad godzinę nadal nie widziałem żadnego wyjścia ani zakończenia programu. Próbowałem wykonać przy użyciu innego IDE, a nawet z terminala, ale nie wydaje się, żeby to był problem. Próbowałem także zmienić wartość parametru „C” z 1 na 1e3.

Mam podobne problemy ze wszystkimi implementacjami svm korzystającymi z programu scikit.

Czy nie czekam wystarczająco długo, aby się skończyć? Ile czasu powinna zająć ta egzekucja?

Z mojego doświadczenia nie powinno to wymagać więcej niż kilku minut.

Oto moja konfiguracja systemu: Ubuntu 14.04, 8 GB pamięci RAM, dużo wolnej pamięci, procesor i7 4. generacji


Czy możesz podać kod? Czy szkolenie lub testowanie zajmuje tak dużo czasu? Co powiesz na mniejsze zestawy danych szkoleniowych / testowych?
zaprzyjaźnij się

Właśnie czytam dane z pliku csv do ramki danych pandy i przekazuję je do funkcji uczenia się scikit. To wszystko! Podanie kodu tak naprawdę by tu nie pomogło
tejaskhot

6
Implementacja SVM sklearn obejmuje co najmniej 3 kroki: 1) utworzenie obiektu SVR, 2) dopasowanie modelu, 3) prognozowanie wartości. Pierwszy krok opisuje używane jądro, które pomaga lepiej zrozumieć wewnętrzne procesy. Drugi i trzeci krok są całkiem różne i musimy przynajmniej wiedzieć, który z nich trwa tak długo. Jeśli jest to trening, może być w porządku, ponieważ czasami nauka jest powolna. Jeśli testuje, oznacza to prawdopodobnie błąd, ponieważ testowanie w SVM jest naprawdę szybkie. Ponadto może to być odczyt CSV, który zajmuje tyle czasu, a wcale nie SVM. Wszystkie te szczegóły mogą być ważne.
zaprzyjaźnij się

Mam również ten sam problem za pośrednictwem svm, ale czy ktoś może mi powiedzieć, ile czasu zajmie normalizacja?
kashyap kitchlu

Odpowiedzi:


69

Jądra SVM wymagają obliczenia funkcji odległości między każdym punktem zestawu danych, co jest dominującym kosztem . Przechowywanie odległości jest obciążeniem dla pamięci, dlatego są one przeliczane w locie. Na szczęście przez większość czasu potrzebne są tylko punkty najbliższe granicy decyzji. Często obliczane odległości są przechowywane w pamięci podręcznej. Jeśli pamięć podręczna jest obciążona, czas działania zwiększa się do O ( n cech x n 3 obserwacji ) .O(nfeatures×nobservations2)O(nfeatures×nobservations3)

Możesz zwiększyć tę pamięć podręczną, wywołując SVR as

model = SVR(cache_size=7000)

Ogólnie rzecz biorąc, to nie zadziała. Ale nie wszystko stracone. Możesz podpróbkować dane i wykorzystać resztę jako zestaw sprawdzania poprawności lub wybrać inny model. Powyżej 200 000 zakresu obserwacji mądrze jest wybrać uczniów liniowych.

SVM jądra można aproksymować, przybliżając matrycę jądra i podając ją do liniowego SVM. Pozwala to na kompromis między dokładnością a wydajnością w czasie liniowym.

Popularnym sposobem osiągnięcia tego jest użycie około 100 centrów klastrów znalezionych przez kmeans / kmeans ++ jako podstawy funkcji jądra. Nowe funkcje pochodne są następnie wprowadzane do modelu liniowego. W praktyce działa to bardzo dobrze. Narzędzia takie jak Sophia -ml i Wabbit Wabbit to sposób, w jaki robią to Google, Yahoo i Microsoft. Wejście / wyjście staje się dominującym kosztem dla prostych uczniów liniowych.

W obfitości danych modele nieparametryczne działają mniej więcej tak samo w przypadku większości problemów. Wyjątek stanowią uporządkowane dane wejściowe, takie jak tekst, obrazy, szeregi czasowe, dźwięk.

Dalsza lektura


16

SVM rozwiązuje problem optymalizacji rzędu kwadratowego.

Nie mam nic do dodania, co nie zostało tu powiedziane. Chcę tylko zamieścić link do strony sklearn o SVC, która wyjaśnia, co się dzieje:

Implementacja oparta jest na libsvm. Złożoność czasu dopasowania jest więcej niż kwadratowa w stosunku do liczby próbek, co utrudnia skalowanie do zestawu danych zawierającego więcej niż kilka 10000 próbek.

Jeśli nie chcesz używać jądra, a wystarcza liniowy SVM, istnieje LinearSVR, który jest znacznie szybszy, ponieważ wykorzystuje podejście optymalizacyjne ala regresje liniowe. Będziesz jednak musiał znormalizować swoje dane, na wypadek, gdybyś tego jeszcze nie zrobił, ponieważ stosuje to normalizacji do współczynnika przechwytywania, co prawdopodobnie nie jest tym, czego chcesz. Oznacza to, że jeśli średnia danych jest daleka od zera, nie będzie w stanie rozwiązać jej w zadowalający sposób.

Można również użyć stochastycznego spadku gradientu w celu rozwiązania problemu optymalizacji. Sklearn posiada SGDRegressor . Musisz użyć, loss='epsilon_insensitive'aby uzyskać wyniki podobne do liniowej SVM. Zobacz dokumentację. Używałbym jednak zejścia gradientowego tylko w ostateczności, ponieważ implikuje to wiele ulepszeń hiperparametrów, aby uniknąć utknięcia w lokalnych minimach. Użyj, LinearSVRjeśli możesz.


Miałem zestaw danych z wieloma wierszami. SVC zaczęło mi zajmować zbyt długo około 150 000 wierszy danych. Użyłem twojej sugestii z LinearSVR, a milion wierszy zajmuje tylko kilka minut. PS stwierdził również, że klasyfikator LogisticRegression daje podobne wyniki jak LinearSVR (w moim przypadku) i jest jeszcze szybszy.
jeffery_the_wind

8

Czy uwzględniłeś skalowanie na etapie wstępnego przetwarzania? Miałem ten problem podczas uruchamiania mojej SVM. Mój zestaw danych to ~ 780 000 próbek (wiersz) z 20 funkcjami (kol.). Mój zestaw treningowy to ~ 235 000 próbek. Okazuje się, że po prostu zapomniałem skalować moje dane! W takim przypadku spróbuj dodać ten bit do swojego kodu:

przeskaluj dane do [-1,1]; zwiększyć prędkość SVM:

z sklearn.preprocessing import MinMaxScaler
skalowanie = MinMaxScaler (feature_range = (- 1,1)). fit (X_train)
X_train = scaling.transform (X_train)
X_test = scaling.transform (X_test)


2
Czy ktoś może wyjaśnić, dlaczego przyspiesza to dopasowanie SVM?
lppier

1
Czy istnieje powód, dla którego wybrałeś MinMaxScaler zamiast jakiegokolwiek innego? Na przykład StandardScaler?
raspi

@Ippier: zasadniczo zmniejszasz możliwą przestrzeń graniczną dla każdej opcji w sposób, który sprawia, że ​​poziom wysiłku jest znacznie mniejszy dla twojej maszyny.
ike

7

Przy tak ogromnym zestawie danych myślę, że lepiej byłoby użyć sieci neuronowej, głębokiego uczenia się, losowego lasu (są zaskakująco dobre) itp.

Jak wspomniano we wcześniejszych odpowiedziach, czas potrzebny jest proporcjonalny do trzeciej potęgi liczby próbek treningowych. Nawet czas przewidywania jest wielomianowy pod względem liczby wektorów testowych.

Jeśli naprawdę musisz korzystać z SVM, zalecam przyspieszenie GPU lub zmniejszenie rozmiaru zestawu danych treningowych. Spróbuj najpierw z próbką (może 10 000 wierszy) danych, aby zobaczyć, czy nie jest to problem z formatem lub dystrybucją danych.

Jak wspomniano w innych odpowiedziach, jądra liniowe są szybsze.


3

Ostatnio napotkałem podobny problem, ponieważ zapomniałem skalować funkcje w moim zbiorze danych, który wcześniej był używany do trenowania rodzaju modelu zespołu. Skalowanie danych może być prawdopodobnym winowajcą, jak wskazała Shelby Matlock. Możesz wypróbować różne skalery dostępne w sklearn, takie jak RobustScaler :

from sklearn.preprocessing import RobustScaler scaler = RobustScaler() X = scaler.fit_transfrom(X)

X jest teraz przekształcany / skalowany i gotowy do dostarczenia do żądanego modelu.


2

To ma sens. IIUC, szybkość wykonywania operacji na wektorach nośnych jest ograniczona liczbą próbek, a nie wymiarowością. Innymi słowy, ogranicza go czas procesora, a nie pamięć RAM. Nie jestem pewien, ile dokładnie to powinno zająć, ale przeprowadzam testy, aby się dowiedzieć.


1

Pozostaw na noc lub dłużej przez 24 godziny. Jakie jest twoje wykorzystanie procesora? Jeśli żaden z rdzeni nie działa przy 100%, oznacza to problem. Prawdopodobnie z pamięcią. Czy sprawdziłeś, czy Twój zestaw danych w ogóle pasuje do 8 GB? Czy próbowałeś SGDClassifier? Jest to jeden z najszybszych tam. Warto spróbować najpierw, mając nadzieję, że zakończy się za około godzinę.


SGDClassifiernie obsługuje jąder. Jeśli OP chce liniowej SVM, polecam najpierw spróbować LinearSVR. Jest znacznie szybszy niż SVRdlatego, że rozwiązuje problem za pomocą biblioteki regresji liniowej, a globalne minimum jest gwarantowane (w przeciwieństwie do gradientu spadku).
Ricardo Cruz

Doceń swój komentarz. Czy możesz wyjaśnić, dlaczego obsługa jądra stanowi problem?
Diego,

Z dokumentacji , To The loss function to be used. Defaults to ‘hinge’, which gives a linear SVM.samo dla SGDRegressor. SGDRegressorjest równoważne z używaniem SVR(kernel='linear'). Jeśli tego właśnie chce OP, to świetnie. Miałem wrażenie, że chciał używać SVM z jądrem. Jeśli tak nie jest, poleciłbym, żeby najpierw spróbował LinearSVR.
Ricardo Cruz,

1

Spróbuj normalizować dane do [-1,1]. Napotkałem podobny problem i po normalizacji wszystko działało dobrze. Możesz łatwo znormalizować dane, używając:

from sklearn import preprocessing X_train = preprocessing.scale(X_train) X_test = preprocessing.scale(X_test)


@Archie To jest odpowiedź na pytanie, a nie pytanie.
timleathart

1

Zetknąłem się z tym problemem i cache_sizejak sugerują inni, wcale nie pomaga. Możesz zobaczyć ten post i ten jako główny autor sugerujący, że powinieneś zmienić kod ręcznie.

Jak wiesz, SVCi SVRsą problemy optymalizacyjne i przestać kiedy margines błędu jest tak mało, gdzie dalsza optymalizacja jest daremny. Jest więc kolejny parametr, w max_iterktórym możesz ustawić, ile iteracji ma wykonać.

Użyłem sklearnw Pythonie, a także e1071w R i R znacznie szybciej dochodzi do wyniku bez ustawiania max_iteri sklearntrwa 2-4 razy dłużej. Jedynym sposobem, w jaki mogłem skrócić czas obliczeń dla Pythona, było użycie max_iter. To jest w stosunku do złożoności modelu, numeru funkcji, jąder i hiperparametrów, ale dla małego zbioru danych użyłem około 4000 Datapoint i max_iterbyła 10000wyniki nie różniły się w ogóle i to było do zaakceptowania.


0

Właśnie miałem podobny problem z zestawem danych, który zawiera tylko 115 elementów i tylko jedną cechę (dane międzynarodowych linii lotniczych). Rozwiązaniem było skalowanie danych. Do tej pory w odpowiedziach brakowało mi użycie rurociągu:

from sklearn.svm import SVR
from sklearn.preprocessing import StandardScaler, MinMaxScaler

model = Pipeline([('scaler', StandardScaler()),
                  ('svr', SVR(kernel='linear'))])

Możesz trenować modeljak zwykły model klasyfikacji / regresji i oceniać go w ten sam sposób. Nic się nie zmienia, tylko definicja modelu.


Co to jest Pipeline? Nie importujesz tego.
Bram Vanroy

0

Musisz skalować swoje dane. Skalowanie znormalizuje punkty danych do zakresu od -1 do 1, co pomoże w szybszej konwergencji.

Spróbuj użyć następującego kodu:

# X is your numpy data array.

from sklearn import preprocessing

X = preprocessing.scale(X)

Witamy w Data Science SE! Czy możesz wyjaśnić, w jaki sposób twoja sugestia pomoże OP? Sugerujesz skalowanie tablicy. Nie jest jasne, jak może to wpłynąć na algorytm SVR w scikit learn.
Stereo
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.