比较使用和不使用随机梯度下降的 SVM 的性能
Compare performance of the SVM with and without stochastic gradient descent
我想比较使用和不使用随机梯度下降的 SVM 分类器的性能。在 sklearn 中,我只找到了 SGDClassifier(我可以将其放入管道中)。
sklearn 不提供非随机(批量)梯度下降分类器的实现吗?我是否必须自己实现两个分类器才能进行分析?
当 SVM 和 SGD 不能结合时
支持向量机通常与内核技巧结合使用,可以对非线性可分数据进行分类。这个答案解释了为什么你不会使用随机梯度下降来解决核化 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
) and also offers the 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()
绘制错误,我们看到对于相同的训练集,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()
我想比较使用和不使用随机梯度下降的 SVM 分类器的性能。在 sklearn 中,我只找到了 SGDClassifier(我可以将其放入管道中)。 sklearn 不提供非随机(批量)梯度下降分类器的实现吗?我是否必须自己实现两个分类器才能进行分析?
当 SVM 和 SGD 不能结合时
支持向量机通常与内核技巧结合使用,可以对非线性可分数据进行分类。这个答案解释了为什么你不会使用随机梯度下降来解决核化 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
) and also offers the 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()
绘制错误,我们看到对于相同的训练集,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()