Сравните производительность SVM с и без стохастического градиентного спуска - PullRequest
0 голосов
/ 18 декабря 2018

Я бы хотел сравнить производительность классификатора SVM с и без стохастического градиентного спуска.В sklearn я нашел только SGDClassifier (который я могу поместить в конвейер).Разве sklearn не обеспечивает реализацию нестохастического (пакетного) классификатора градиентного спуска?Должен ли я самостоятельно применять оба классификатора для проведения анализа?

1 Ответ

0 голосов
/ 18 декабря 2018

Когда SVM и SGD не могут быть объединены

SVM часто используются в сочетании с трюком ядра, который позволяет классифицировать нелинейно разделимые данные.Этот ответ объясняет, почему вы не будете использовать стохастический градиентный спуск для решения SVM с ядром: https://stats.stackexchange.com/questions/215524/is-gradient-descent-possible-for-kernelized-svms-if-so-why-do-people-use-quadr

Линейные SVM

Если мы будем придерживаться линейных SVM, то мыможно запустить эксперимент, используя sklearn, так как он предоставляет оболочки для libsvm (SVC), liblinear (LinearSVC), а также предлагает SGDClassifier.Рекомендуем прочитать связанную документацию libsvm и liblinear, чтобы понять, что происходит под капотом.

Сравнение на примере набора данных

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

import time
import numpy as np
import matplotlib.pyplot as plt

from sklearn.svm import SVC, LinearSVC
from sklearn.linear_model import SGDClassifier
from sklearn.model_selection import train_test_split

# Randomly generated dataset
# Linear function + noise
np.random.seed(0)
X = np.random.normal(size=(50000, 10))
coefs = np.random.normal(size=10)
epsilon = np.random.normal(size=50000)
y = (X @ coefs + epsilon) > 0

# Classifiers to compare
algos = {
    'LibSVM': {
        'model': SVC(),
        'max_n': 4000,
        'time': [],
        'error': []
    },
    'LibLinear': {
        'model': LinearSVC(dual=False),
        'max_n': np.inf,
        'time': [],
        'error': []
    },
    'SGD': {
        'model': SGDClassifier(max_iter=1000, tol=1e-3),
        'max_n': np.inf,
        'time': [],
        'error': []
    }
}

splits = list(range(100, 1000, 100)) + \
         list(range(1500, 5000, 500)) + \
         list(range(6000, 50000, 1000))
for i in splits:
    X_train, X_test, y_train, y_test = train_test_split(X, y,
                                                        test_size=1-i/50000,
                                                        random_state=0)
    for k, v in algos.items():
        if i < v['max_n']:
            model = v['model']
            t0 = time.time()
            model.fit(X_train, y_train)
            t1 = time.time()
            v['time'].append(t1 - t0)
            preds = model.predict(X_test)
            e = (preds != y_test).sum() / len(y_test)
            v['error'].append(e)

При построении результатов мы видим, что традиционный решатель libsvm нельзя использовать для больших n, в то время как реализации liblinear и SGD хорошо масштабируются в вычислительном отношении.

plt.figure()
for k, v in algos.items():
    plt.plot(splits[:len(v['time'])], v['time'], label='{} time'.format(k))
plt.legend()
plt.semilogx()
plt.title('Time comparison')
plt.show()

enter image description here

При составлении графика ошибки мы видим, что SGD хуже, чем LibSVM для того же тренировочного набора, но если у вас большой тренировочный набор, это становитсянезначительный момент.Алгоритм liblinear лучше всего работает с этим набором данных:

plt.figure()
for k, v in algos.items():
    plt.plot(splits[:len(v['error'])], v['error'], label='{} error'.format(k))
plt.legend()
plt.semilogx()
plt.title('Error comparison')
plt.xlabel('Number of training examples')
plt.ylabel('Error')
plt.show()

enter image description here

...