Повышение производительности прогнозирования SVC для отдельных выборок

У меня есть большие модели SVC (~ 50 МБ cPickles) для классификации текста, и я пробую различные способы их использования в производственной среде. Классификация пакетов документов работает очень хорошо (около 1 тыс. документов в минуту с использованием как predict, так и predict_proba). Однако предсказание для одного документа — это совсем другая история, как объясняется в комментарии к этот вопрос:

Вы делаете прогнозы партиями? Метод SVC.predict, к сожалению, влечет за собой большие накладные расходы, поскольку он должен реконструировать структуру данных LibSVM, аналогичную той, которую создал обучающий алгоритм, выполнять неглубокое копирование опорных векторов и преобразовывать тестовые образцы в формат LibSVM, который может отличаться от форматов NumPy/SciPy. Следовательно, предсказание по одной выборке неизбежно будет медленным. – ларсманс

Я уже использую модели SVC в качестве веб-приложений Flask, поэтому часть накладных расходов исчезла (распаковка), но время прогнозирования для отдельных документов по-прежнему велико (0,25 с). Я просмотрел код в методах predict, но не могу понять, есть ли способ «предварительно разогреть» их, предварительно реконструируя структуру данных LibSVM при запуске сервера... есть идеи?

def predict(self, X):
    """Perform classification on samples in X.

    For an one-class model, +1 or -1 is returned.

    Parameters
    ----------
    X : {array-like, sparse matrix}, shape = [n_samples, n_features]

    Returns
    -------
    y_pred : array, shape = [n_samples]
        Class labels for samples in X.
    """
    y = super(BaseSVC, self).predict(X)
    return self.classes_.take(y.astype(np.int))

person emiguevara    schedule 29.01.2014    source источник
comment
Не используйте SVC для классификации текста, оно того не стоит.   -  person Fred Foo    schedule 30.01.2014
comment
Привет, я понимаю, что вы имеете в виду, но я должен был указать, что это мультиклассовая классификация настроений (очень разные размеры классов). Пока что я пытаюсь достичь максимальной точности. До сих пор SVC с ядрами RBF превосходил все остальные классификаторы, хотя и с небольшим отрывом (например, SVC 0,898, PassiveAggressiveClassifier 0,868, MultinomialNB 0,837). Тем не менее, SVC в значительной степени превосходит конкурентов с самыми маленькими классами (например, F1 SVC 0,84, PAC 0,76, MNB 0,68). Если бы SVC работал немного быстрее с одним документом, я бы не видел причин не использовать его с моими текущими данными.   -  person emiguevara    schedule 30.01.2014


Ответы (2)


Я вижу три возможных решения.

Пользовательский сервер

Дело не в том, чтобы что-то разогреть. Просто - libSVM - это библиотека C, и вам нужно упаковать/распаковать данные в правильный формат. Этот процесс более эффективен для всей матрицы, чем для каждой строки в отдельности. Единственный способ преодолеть это - написать более эффективную оболочку между вашей производственной средой и libSVM (вы можете написать сервер на основе libsvm, который будет использовать какую-то общую память с вашим сервисом). К сожалению, это индивидуальная проблема, которую можно решить с помощью существующих реализаций.

Пакеты

Наивный подход, такой как буферизация запросов, является опцией (если это высокопроизводительная система с тысячами запросов, вы можете просто хранить их в пакетах из N-элементов и отправлять их в libSVM в таких пакетах).

Собственная классификация

Наконец, классификация с использованием SVM действительно простая задача. Вам не нужна libSVM для выполнения классификации. Только обучение представляет собой сложную задачу. Как только вы получите все опорные векторы (SV_i), ядро ​​(K), множители ларагиана (alpha_i) и член пересечения (b), вы классифицируете, используя:

cl(x) = sgn( SUM_i y_i alpha_i K(SV_i, x) + b)

Вы можете кодировать эту операцию непосредственно в своем приложении, без необходимости упаковывать/распаковывать/отправлять что-либо в libsvm. Это может ускорить процесс на порядок. Очевидно, что вероятность получить сложнее, так как она требует масштабирования Платта, но все же возможно.

person lejlot    schedule 29.01.2014
comment
Очень полезно, спасибо. Я думаю, что партии будут решением на данный момент, но я попробую классифицировать, как только у меня будет время :-) - person emiguevara; 30.01.2014

Вы не можете создать структуру данных LibSVM заранее. Когда приходит запрос на классификацию документа, вы получаете текст документа, делаете из него вектор тогда и только потом конвертируете в формат LibSVM, чтобы можно было получить решение.

LinearSVC должен быть значительно быстрее, чем SVC с линейным ядром, поскольку он использует liblinear. Вы можете попробовать использовать другой классификатор, если это не слишком сильно снижает производительность.

person mbatchkarov    schedule 29.01.2014
comment
Конечно, вы не можете избежать обработки одного документа, который вы получаете по запросу. Однако разница в производительности в зависимости от количества сэмплов настолько велика, что мне все же интересно, можно ли что-то сделать заранее. Например, вызов predict и predict_proba для каждого документа: 100 документов 5,6157 с, 10 документов 0,9705 с, 2 документа 0,4969 с, 1 документ 0,4551 с. - person emiguevara; 29.01.2014
comment
Изменение классификатора не входило в вопрос. - person emiguevara; 29.01.2014
comment
LinearSVC — это просто оптимизированная версия SVC, так что на самом деле вы не меняете классификатор. stackoverflow.com/questions/11508788 / - person mbatchkarov; 29.01.2014
comment
Вы в курсе различий между вариантами LinearSVC и SVC (читай: нелинейные ядра)??? Повторяю: это не было частью моего вопроса, не нужно предлагать изменить классификатор. - person emiguevara; 29.01.2014