【问题标题】:increase speed for SVM with polynomial kernel使用多项式内核提高 SVM 的速度
【发布时间】:2019-08-23 14:10:45
【问题描述】:

我是机器学习的新手。
我正在使用带有“多项式”内核的支持向量机 (SVM) 进行多类分类。我的数据集大小是(56010395, 4),形式为(样本数,特征数)。但是,我的机器自过去 1 周以来一直在无休止地训练,但训练仍未完成。我的代码真的很基础,所以我不明白我的代码有什么问题。我无法对我的数据集进行子采样。我的 RAM 是 15 GB,我使用的是 i7 Intel CPU。

我已经尝试过使用线性分类器的 SVM,训练在 3 小时内完成,准确率达到 75%。此外,数据使用 MinMaxscaler 进行缩放。

from sklearn.svm import SVC
X_train, X_test, y_train, y_test = train_test_split(X_data, y_labels, test_size=0.3, random_state=0)

print('start training')
start = time. time()
svm_model_linear = SVC(kernel='poly', degree=3, C=1.0, gamma = 'auto').fit(X_train, y_train)
print('training_finished')
end = time. time()
print('time: ', end - start)
svm_predictions = svm_model_linear.predict(X_test)

【问题讨论】:

  • 尝试通过减少词汇量来进行特征选择
  • 这已经是一个减少特征的词汇表了。我无法进一步减少它。
  • 如果花了那么多时间,并不一定意味着你的代码有问题。线性 SVC 的扩展性要好得多,所以我不会对有这么大的时差感到惊讶。您的 RAM 非常大,因此一种选择可能是为您的内核使用 cache_size 参数。也许您可以尝试 cache_size = 500 (或更大的值)?在您的数据的子样本上尝试一下,看看它是否能给您带来任何改进。
  • 你有几节课?
  • 为什么不能对数据进行二次抽样?

标签: python performance machine-learning scikit-learn svm


【解决方案1】:

SVM 的训练时间与样本数量成二次方关系,或者更糟。对于 O(n^2),时间与 c * n^2) 成正比。 您的模型配置大约需要 20 秒,在我的机器上具有 100k 个功能,在c=2e9 附近给出一个常数。因此,56 010 395 样本的预期训练时间是 72 天,可能要长得多。

因此,要么对您的数据集进行二次抽样,要么使用其他分类器。您可以使用小型多层感知器来获得类似于具有多项式核的 SVM 的表现力。它可以使用 SGD 进行小批量训练。使用 Hinge 损失与 SVM 使用的损失相同。

顺便说一句,您基本上总是需要为 SVM 优化超参数 C。最佳实践方法是在网格搜索中进行 5 折交叉验证。所以你应该计划训练至少 50 个模型...


import time

from sklearn.svm import SVC
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split
import numpy
import pandas

def time_training(estimator, n_samples):
    X, y = make_moons(n_samples=n_samples, noise=0.1, random_state=1)
    X = numpy.concatenate([X, X], axis=1)
    assert (X.shape[1] == 4), X.shape

    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)

    start = time. time()
    estimator.fit(X_train, y_train)
    end = time.time()
    t = end-start
    print('took', n_samples, t)
    return t

def main():
    model = SVC(kernel='poly', degree=3, C=1.0, gamma = 'auto')
    sizes = numpy.array((100, 1e3, 1e4, 2e4, 4e4, 6e4, 1e5, 1.1e5, 1.2e5)).astype(int)
    times = [ time_training(model, s) for s in sizes ]

    df = pandas.DataFrame({
        'samples': sizes,
        'time': times,
    })
    df.to_csv('temp/svmtrain.csv')

if __name__ == '__main__':
    main()

[jon@jon-thinkpad ~]$ python3 temp/svm-training-time.py
took 100 0.0006172657012939453
took 1000 0.00444340705871582
took 10000 0.26808977127075195
took 20000 1.1068146228790283
took 40000 3.8822362422943115
took 60000 8.051671743392944
took 100000 20.05191993713379
took 110000 36.83517003059387
took 120000 61.012284994125366
>>> 0.26/(10000**2)
2.6e-09
>>> 20/(100000**2)
2e-09
>>> 2e-9*(56e6**2)/(3600*24)
72.5925925925926

【讨论】:

  • 嗨,感谢您的回答。我只是想使用 SVM,以便将其与 MLP 进行比较,但我可能会尝试找出是否可以对数据进行二次抽样。
  • 我尝试对我的数据进行二次抽样,现在我的数据包含 500 万个样本,其中包含 5000 万个样本。根据您的说法,分类应该在 2e-9*(56e5**2)/(3600*24) = 0.72 天内完成,但是已经 2 天了,我的分类器仍然没有收敛。你知道可能是什么问题
  • 您的数据集和机器都与我的不同。并且复杂度可能比 O(n**2) 差一些。在实践中,您应该从最小的数据大小运行二次采样并逐渐增大。这使您可以估计学习曲线 - 您将在等待较大模型的同时获得小模型的结果 :) 您可以使用其中的时序结果来估计较大模型需要多长时间
猜你喜欢
  • 2021-04-25
  • 2021-12-03
  • 2014-04-28
  • 2017-09-17
  • 2017-08-11
  • 1970-01-01
  • 2016-05-22
  • 1970-01-01
  • 2014-06-04
相关资源
最近更新 更多