比较具有和没有随机梯度下降的SVM的性能

时间:2018-12-17 22:05:56

标签: python svm gradient-descent

我想比较使用和不使用随机梯度下降的SVM分类器的性能。在sklearn中,我仅找到了SGDClassifier(可以将其放入管道中)。 sklearn是否不提供非随机(批量)梯度下降分类器的实现?为了进行分析,我是否必须自己实现两个分类器?

1 个答案:

答案 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进行实验,因为它提供了libsvmSVC),liblinear({{3 }}),还提供了LinearSVC。建议阅读libsvmliblinear的链接文档,以了解幕后发生的事情。

示例数据集比较

下面是随机生成的数据集(可能不代表您的问题)的计算性能和准确性的比较。您应该根据您的要求更改问题。

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()

SGDClassifier

标出错误,对于相同的训练集,我们看到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