SVM за допомогою scikit learn працює нескінченно і ніколи не завершує виконання


76

Я намагаюся запустити SVR за допомогою scikit learn (python) на навчальному наборі даних, що має 595605 рядків та 5 стовпців (функції) та тестовий набір даних, що має 397070 рядків. Дані попередньо оброблені та затверджені.

Я можу успішно запустити тестові приклади, але, виконуючи за допомогою мого набору даних і дозволяючи йому працювати протягом години, я все ще не міг побачити жодного виводу або припинення програми. Я намагався виконати за допомогою іншого IDE і навіть з терміналу, але це, здається, не було проблемою. Я також спробував змінити значення параметра "C" з 1 на 1e3.

Я стикаюся з подібними проблемами у всіх впровадженні svm за допомогою scikit.

Хіба я не чекаю, коли вона завершиться? Скільки часу має зайняти ця страта?

З мого досвіду, це не повинно вимагати протягом декількох хвилин.

Ось моя конфігурація системи: Ubuntu 14.04, 8 Гб оперативної пам’яті, багато вільної пам’яті, процесор i7 4-го покоління


Не могли б ви надати код? Крім того, чи займає це навчання чи тестування так багато часу? Як щодо менших наборів даних про навчання / тестування?
подруга

Я просто читаю дані з CSV-файлу в рамку даних панди і передаю їх у функцію навчання scikit. Це все! Надання коду насправді не допоможе тут
tejaskhot

6
Реалізація SVM sklearn передбачає щонайменше 3 кроки: 1) створення об'єкта SVR, 2) підгонка моделі, 3) значення прогнозування. Перший крок описує ядро, яке використовується, що допомагає зрозуміти внутрішні процеси набагато краще. Другий та третій кроки досить різні, і нам потрібно знати принаймні, який з них займає так довго. Якщо це тренування, то це може бути нормально, адже навчання іноді відбувається повільно. Якщо це тестування, то, ймовірно, помилка, тому що тестування в SVM дійсно швидко. Крім того, можливо, читання CSV займає так довго, а зовсім не SVM. Тому всі ці деталі можуть бути важливими.
подруга

Я зіткнувся з тією ж проблемою і через svm, але хто-небудь може сказати мені, скільки часу знадобиться після нормалізації?
кашяп кичлу

Відповіді:


69

Кернелізовані SVM вимагають обчислення функції відстані між кожною точкою набору даних, що є домінуючою вартістю . Збереження відстаней є тягарем для пам’яті, тому вони перераховуються на льоту. На щастя, більшість часу потрібні лише пункти, найближчі до межі рішення. Часто обчислювані відстані зберігаються в кеші. Якщо кеш обробляється, то час запуску підійде до .O(nfeatures×nobservations2)O(nfeatures×nobservations3)

Ви можете збільшити цей кеш, викликавши SVR як

model = SVR(cache_size=7000)

Взагалі це не спрацює. Але все не втрачено. Ви можете подати вибірку даних і використовувати решту як набір перевірки, або ви можете вибрати іншу модель. Вище 200 000 очок спостереження розумно вибирати лінійних учнів.

Ядро SVM можна наблизити, наблизивши матрицю ядра і подавши її до лінійної SVM. Це дозволяє торгуватися між точністю та продуктивністю в лінійний час.

Популярним засобом досягнення цього є використання 100 або близько центрів кластерів, знайдених kmeans / kmeans ++ як основу вашої функції ядра. Потім нові похідні функції подаються в лінійну модель. На практиці це дуже добре працює. Інструменти на зразок софії-мл та wawbit wawbit - це те, як це роблять Google, Yahoo та Microsoft. Введення / вихід стає домінуючою вартістю для простих лінійних учнів.

За безліччю даних непараметричні моделі працюють майже однаково для більшості проблем. Винятки становлять структуровані входи, такі як текст, зображення, часові ряди, аудіо.

Подальше читання


16

SVM вирішує оптимізаційну задачу квадратичного порядку.

Я не маю нічого додати, що тут не було сказано. Я просто хочу опублікувати посилання на sklearn сторінку про SVC, яка роз'яснює, що відбувається:

Реалізація заснована на libsvm. Складна складність часу є більш ніж квадратичною з кількістю вибірок, що ускладнює масштабування набору даних більш ніж на пару 10000 зразків.

Якщо ви не хочете використовувати ядра, і лінійний SVM є достатнім, існує LinearSVR, який набагато швидше, оскільки він використовує оптимізаційний підхід для лінійних регресій. Вам доведеться нормалізувати свої дані, якщо ви цього ще не робите, оскільки це застосовує регуляризацію до коефіцієнта перехоплення, що, мабуть, не є тим, що ви хочете. Це означає, що якщо ваші середні дані далеко не нульові, вони не зможуть її задовільно вирішити.

Для вирішення проблеми оптимізації ви також можете скористатися стохастичним градієнтом. Sklearn має SGDRegressor . Ви повинні використовувати, loss='epsilon_insensitive'щоб мати схожі результати з лінійною SVM. Дивіться документацію. Я б використовував градієнтний спуск лише в крайньому випадку, хоча це передбачає сильне налаштування гіперпараметрів, щоб не зациклюватися на локальних мінімумах. Використовуйте, LinearSVRякщо можете.


У мене був набір даних з багатьма рядками. SVC почав занадто довго переносити для мене близько 150 К рядків даних. Я використав вашу пропозицію з LinearSVR, і мільйон рядків займає всього пару хвилин. PS також виявив, що класифікатор LogisticRegression дає подібні результати, як LinearSVR (в моєму випадку) і ще швидший.
jeffery_the_wind

8

Чи включено ви масштабування в крок попередньої обробки? У мене виникла ця проблема під час запуску SVM. Мій набір даних становить ~ 780 000 зразків (рядок) з 20 функціями (col). Мій навчальний набір становить ~ 235 тис. Зразків. Виявляється, я просто забув масштабувати свої дані! Якщо це так, спробуйте додати цей біт у свій код:

дані масштабу до [-1,1]; збільшення швидкості SVM:

з sklearn.preprocessing import MinMaxScaler
масштабування = MinMaxScaler (feature_range = (- 1,1)). fit (X_train)
X_train = масштабування.transform (X_train)
X_test = масштабування.transform (X_test)


2
Хтось може пояснити, чому це прискорює пристосування SVM?
lppier

1
Чи є причина, чому ви вибрали MinMaxScaler замість будь-якого іншого? Наприклад, StandardScaler?
raspi

@Ippier: по суті, ви зменшуєте можливий граничний простір для кожної опції таким чином, щоб рівень зусиль був набагато меншим для вашої машини.
ike

7

З таким величезним набором даних, я думаю, вам буде краще використовувати нейронну мережу, глибоке навчання, випадковий ліс (вони дивно хороші) тощо.

Як було сказано у попередніх відповідях, витрачений час пропорційний третій потужності кількості навчальних зразків. Навіть час прогнозування є многочленом за кількістю тестових векторів.

Якщо ви дійсно повинні використовувати SVM, то я б рекомендував використовувати GPU для прискорення або зменшення розміру навчального набору даних. Спробуйте спочатку зі зразком (можливо, 10 000 рядків) даних, щоб побачити, чи це не проблема з форматом даних чи розповсюдженням.

Як згадується в інших відповідях, лінійні ядра швидші.


3

Нещодавно я стикався з подібною проблемою, тому що забув масштабувати функції в моєму наборі даних, який раніше використовувався для навчання типу ансамблю. Неможливість масштабування даних може бути ймовірним винуватцем, на що вказує Шелбі Матлок. Ви можете спробувати різні шкали, доступні в sklearn, такі як RobustScaler :

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

Тепер X перетворений / масштабований і готовий до подачі на вашу бажану модель.


2

Це має сенс. IIUC, швидкість виконання операцій підтримки вектора підтримується кількістю вибірок, а не розмірністю. Іншими словами, вона обмежена часом процесора, а не оперативною пам’яттю. Я не впевнений, скільки саме часу має зайняти, але я запускаю деякі орієнтири, щоб це з'ясувати.


1

Залиште його протягом ночі або краще протягом 24 годин. Яке використання CPU? Якщо жодне з ядер не працює на 100%, у вас є проблема. Напевно, з пам’яттю. Ви перевірили, чи відповідає ваш набір даних 8 Гб? Ви спробували SGDClassifier? Це одна з найшвидших там. Варто спробувати спершу сподіваючись, що це закінчиться через годину або близько того.


SGDClassifierне підтримує ядра. Якщо ОП хоче лінійний SVM, то я б рекомендував спершу спробувати LinearSVR. Це набагато швидше, ніж SVRчерез те, що воно вирішує проблему за допомогою лінійної бібліотеки регресії, і глобальний мінімум гарантований (на відміну від градієнта деценту).
Рікардо Крус

Вдячний за ваш коментар. Не могли б ви детальніше пояснити, чому підтримка ядра є проблемою?
Дієго

З документації , The loss function to be used. Defaults to ‘hinge’, which gives a linear SVM.те саме SGDRegressor. SGDRegressorеквівалентно використанню SVR(kernel='linear'). Якщо цього хоче ОП, це чудово. У мене було враження, що він хоче використовувати SVM з ядром. Якщо це не так, я б рекомендував спершу спробувати LinearSVR.
Рікардо Крус

1

Спробуйте нормалізувати дані до [-1,1]. Я зіткнувся з подібною проблемою і після нормалізації все працювало нормально. Ви можете легко нормалізувати дані, використовуючи:

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


@Archie Це відповідь на запитання, а не на питання.
timleathart

1

Я зіткнувся з цим питанням і, cache_sizeяк вважають інші, зовсім не допомагає. Ви можете бачити цю публікацію, і цей, як основний учасник, запропонував вам змінити код вручну.

Як відомо, SVCі SVRпроблеми з оптимізацією є, і вони зупиняються, коли межа помилок настільки мала, де подальша оптимізація є марною. Отже, в них є ще один параметр max_iter, де ви можете встановити, скільки ітерацій він повинен робити.

Я використовував і sklearnв python, і e1071в R і R, набагато швидше дістається до результату, не встановлюючи значення max_iterі sklearnзаймає 2-4 рази довше. Єдиний спосіб, який я міг би скоротити час обчислення для python, - це використовувати max_iter. Це щодо складності моделі, кількості ознак, ядер і гіперпараметров, але для невеликого набору даних я використовував близько 4000 і точок даних max_iterбув 10000результати не відрізнялося на всіх , і це було прийнятно.


0

У мене якраз була схожа проблема із набором даних, який містить лише 115 елементів і лише одну єдину функцію (дані міжнародних авіакомпаній). Рішенням було масштабування даних. Що я пропустив у відповідях поки що було використання трубопроводу:

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

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

Ви можете тренувати modelяк звичайну модель класифікації / регресії та оцінювати її так само. Нічого не змінюється, лише визначення моделі.


Що таке Pipeline? Ви не імпортуєте його.
Брам Ванрой

0

Потрібно масштабувати свої дані. Масштабування нормалізує ваші точки даних до діапазону від -1 до 1, що сприятиме більш швидкій конвергенції.

Спробуйте використовувати наступний код:

# X is your numpy data array.

from sklearn import preprocessing

X = preprocessing.scale(X)

Ласкаво просимо до Data Science SE! Чи можете ви пояснити, як ваша пропозиція допоможе ОП? Що ви пропонуєте - це масштабування масиву. Незрозуміло, як це може чи не може вплинути на алгоритм SVR в scikit learn.
Стерео
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.