我正在尝试用Julia实现一个SVM对偶优化问题。我的数据集是60000×784的MNIST数字识别数据集。我使用的是一对多策略来结合10个分类器,所以这只是基础二元分类器的组件,其中$\pmb y_i \in {-1,1}$
线性版本非常快:
function dual_loss(α::Vec, X::Mat, y::Vec) where {T<:AbstractFloat, Vec<:AbstractVector{T}, Mat<:AbstractMatrix{T}} t = α .* y return sum(α) - t' * X * X' * tend
然而,核版本极其缓慢,我没有耐心等待它完成:
function dual_loss(α::Vec, X::Mat, y::Vec, kernel::Function=dot) where {T<:AbstractFloat, Vec<:AbstractVector{T}, Mat<:AbstractMatrix{T}} t = α .* y return sum(α) - sum(@views 0.5 * t[i] * t[j] * kernel(X[i, :], X[j, :]) for i=1:size(X, 1), j=1:size(X, 1))end
我还尝试使用了MLKernel.jl库,但仍然非常慢。我想知道这是因为问题本身的规模(我在笔记本电脑上使用CPU运行),还是因为我的代码不够优化?如果是后者,有什么方法可以提高其性能吗?
回答:
虽然我不太熟悉Julia,但我会尝试回答这个问题。SVM将你提供的数据转换到更高维度,以便在数据分类之间找到线性分割。这带来了一些困惑,因为不清楚如何用线性分割来区分10个不同的数字(MNIST数据集包含0-9)。
在线性分割代码中,我不确定它如何将数据分成不同的组,因为我认为线性SVM不会有太大作用。这就是为什么它运行得非常快,但很可能非常不准确(我不知道你的结果,只是假设)。另外一点是,我认为这只是将数据转换到比原始维度稍大的维度,这对分离帮助不大。
在核代码中,这应该比线性版本花费更长的时间,因为据我了解,它在确定最终分割线之前被转换到更高的维度。
我认为你的代码无法进一步优化…特别是在非常大的数据集上,核方法可能非常耗费资源。我在用电脑的CPU运行其他机器学习方法时也有同样的问题;它会占用100%的CPU并花几个小时来执行。你可以考虑租用一些配置更高的云服务器来运行你的代码。
我还建议你考虑其他分类方法,因为我不明白如何对10个不同的标签进行二元分类。
希望这些对你有帮助!