Когда 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](https://i.stack.imgur.com/uWmlS.png)
При составлении графика ошибки мы видим, что 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](https://i.stack.imgur.com/yF5QP.png)