我想比较使用和不使用随机梯度下降的SVM分类器的性能。在sklearn中,我仅找到了SGDClassifier(可以将其放入管道中)。 sklearn是否不提供非随机(批量)梯度下降分类器的实现?为了进行分析,我是否必须自己实现两个分类器?
答案 0 :(得分:2)
无法将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
({{3 }}),还提供了LinearSVC
。建议阅读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()
标出错误,对于相同的训练集,我们看到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()