SVM с использованием scikit learn работает бесконечно и никогда не завершает выполнение

76

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

Я могу успешно запустить тестовые примеры, но, выполнив мой набор данных и оставив его работать более часа, я все равно не смог увидеть какой-либо вывод или завершение программы. Я пытался выполнить с использованием другой IDE и даже из терминала, но это не проблема. Я также попытался изменить значение параметра «C» с 1 до 1e3.

Я сталкиваюсь с похожими проблемами со всеми реализациями SVM с использованием Scikit.

Разве я не жду достаточно, чтобы завершить? Сколько времени должно занять это выполнение?

Из моего опыта это не должно занять более нескольких минут.

Вот моя конфигурация системы: Ubuntu 14.04, 8 ГБ ОЗУ, много свободной памяти, процессор 4-го поколения i7

tejaskhot
источник
Не могли бы вы предоставить код? Кроме того, обучение или тестирование занимают так много времени? Как насчет небольших наборов данных для обучения / тестирования?
друг
Я просто читаю данные из CSV-файла в pandas dataframe и передаю их в функцию обучения Scikit. Вот и все! Предоставление кода здесь не очень поможет
tejaskhot
6
Реализация SVM в sklearn подразумевает как минимум 3 шага: 1) создание объекта SVR, 2) подбор модели, 3) прогнозирование значения. Первый шаг описывает используемое ядро, которое помогает лучше понять внутренние процессы. Второй и третий этапы довольно разные, и нам нужно знать, по крайней мере, какой из них занимает столько времени. Если это тренировка, то это может быть нормально, потому что иногда обучение медленное. Если это тестирование, то, вероятно, есть ошибка, потому что тестирование в SVM действительно быстрое. Кроме того, это может быть чтение CSV, которое занимает столько времени, а не SVM вообще. Так что все эти детали могут быть важны.
друг
я сталкиваюсь с той же проблемой через svm, но кто-нибудь может сказать мне, сколько времени это займет после нормализации?
kashyap kitchlu

Ответы:

70

O(nfeatures×nobservations2)O(nfeatures×nobservations3)

Вы можете увеличить этот кеш, вызывая SVR как

model = SVR(cache_size=7000)

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

Ядро SVM может быть аппроксимировано путем аппроксимации матрицы ядра и подачи ее в линейный SVM. Это позволяет вам выбирать между точностью и производительностью за линейное время.

Популярное средство для достижения этой цели - использовать около 100 кластерных центров, найденных kmeans / kmeans ++, в качестве основы вашей функции ядра. Новые производные функции затем вводятся в линейную модель. Это очень хорошо работает на практике. Google, Yahoo и Microsoft делают это с помощью таких инструментов, как sophia-ml и vowpal wabbit . Ввод / вывод становится доминирующей стоимостью для простых линейных учеников.

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

дальнейшее чтение

Джессика Мик
источник
16

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

Мне нечего добавить, что здесь не было сказано. Я просто хочу опубликовать ссылку на страницу sklearn о SVC, которая разъясняет, что происходит:

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

Если вы не хотите использовать ядра, и достаточно линейного SVM, есть LinearSVR, который намного быстрее, потому что он использует подход оптимизации, основанный на линейных регрессиях. Однако вам придется нормализовать данные, если вы этого еще не сделали, потому что они применяют регуляризацию к коэффициенту перехвата, что, вероятно, не то, что вам нужно. Это означает, что если ваше среднее значение данных далеко от нуля, оно не сможет решить его удовлетворительно.

Вы также можете использовать стохастический градиентный спуск для решения задачи оптимизации. Склеарн Особенности SGDRegressor . Вы должны использовать, loss='epsilon_insensitive'чтобы получить результаты, аналогичные линейному SVM. Смотрите документацию. Я бы использовал градиентный спуск только в крайнем случае, потому что он подразумевает много настроек гиперпараметров, чтобы избежать застревания в локальных минимумах. Используйте, LinearSVRесли можете.

Рикардо Круз
источник
У меня был набор данных со многими строками. SVC начал занимать у меня слишком много времени около 150 тыс. Строк данных. Я использовал ваше предложение с LinearSVR, и миллион строк занимает всего пару минут. PS также обнаружил, что классификатор LogisticRegression дает результаты, аналогичные LinearSVR (в моем случае), и даже быстрее.
jeffery_the_wind
8

Вы включили масштабирование на этапе предварительной обработки? У меня была эта проблема при запуске моего SVM. Мой набор данных ~ 780 000 образцов (строка) с 20 функциями (столбец). Мой тренировочный набор составляет ~ 235 тыс. Образцов. Оказывается, я просто забыл масштабировать свои данные! Если это так, попробуйте добавить этот бит в ваш код:

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

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

Шелби Мэтлок
источник
2
Кто-нибудь может объяснить, почему это ускоряет подгонку SVM?
больше
1
Есть ли причина, по которой вы выбрали MinMaxScaler вместо любой другой? StandardScaler, например?
распи
@Ippier: по сути, вы уменьшаете возможное граничное пространство для каждой опции таким образом, чтобы уровень усилий значительно уменьшился для вашей машины.
IKE
7

С таким огромным набором данных, я думаю, вам лучше использовать нейронную сеть, глубокое обучение, случайный лес (они на удивление хороши) и т. Д.

Как упоминалось в предыдущих ответах, время, затрачиваемое на обучение, пропорционально третьей степени числа обучающих выборок. Даже время прогнозирования является полиномиальным по количеству тестовых векторов.

Если вам действительно нужно использовать SVM, то я бы порекомендовал использовать ускорение графического процессора или уменьшение размера набора обучающих данных. Попробуйте сначала с примером (возможно, 10000 строк) данных, чтобы увидеть, не является ли это проблемой с форматом данных или распределением.

Как упоминалось в других ответах, линейные ядра работают быстрее.

Лила Прабху
источник
3

Недавно я столкнулся с подобной проблемой, потому что забыл масштабировать объекты в моем наборе данных, который ранее использовался для обучения ансамблевой модели. Неспособность масштабировать данные может быть вероятным виновником, как указал Шелби Мэтлок. Вы можете попробовать различные скейлеры, доступные в sklearn, такие как RobustScaler :

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

X теперь преобразован / масштабирован и готов к передаче в нужную вам модель.

Dutse I
источник
2

Это имеет смысл. IIUC, скорость выполнения опорных векторных операций зависит от количества выборок, а не от размерности. Другими словами, он ограничен временем процессора, а не оперативной памятью. Я не уверен, сколько именно времени это займет, но я провожу некоторые тесты, чтобы узнать.

Джайдев Дешпанде
источник
1

Оставьте его на ночь или лучше на 24 часа. Какова загрузка вашего процессора? Если ни одно из ядер не работает на 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)

Sujay_K
источник
@ Арчи Это ответ на вопрос, а не вопрос.
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.
Стерео