首先,这似乎是一个非常好的问题!
现在进入正题。在来源中ksvm
我们可以发现使用用户定义的内核和内置内核之间的界限是什么时候:
if (type(ret) == "spoc-svc") {
if (!is.null(class.weights))
weightedC <- class.weights[weightlabels] * rep(C,
nclass(ret))
else weightedC <- rep(C, nclass(ret))
yd <- sort(y, method = "quick", index.return = TRUE)
xd <- matrix(x[yd$ix, ], nrow = dim(x)[1])
count <- 0
if (ktype == 4)
K <- kernelMatrix(kernel, x)
resv <- .Call("tron_optim", as.double(t(xd)), as.integer(nrow(xd)),
as.integer(ncol(xd)), as.double(rep(yd$x - 1,
2)), as.double(K), as.integer(if (sparse) xd@ia else 0),
as.integer(if (sparse) xd@ja else 0), as.integer(sparse),
as.integer(nclass(ret)), as.integer(count), as.integer(ktype),
as.integer(7), as.double(C), as.double(epsilon),
as.double(sigma), as.integer(degree), as.double(offset),
as.double(C), as.double(2), as.integer(0), as.double(0),
as.integer(0), as.double(weightedC), as.double(cache),
as.double(tol), as.integer(10), as.integer(shrinking),
PACKAGE = "kernlab")
reind <- sort(yd$ix, method = "quick", index.return = TRUE)$ix
alpha(ret) <- t(matrix(resv[-(nclass(ret) * nrow(xd) +
1)], nclass(ret)))[reind, , drop = FALSE]
coef(ret) <- lapply(1:nclass(ret), function(x) alpha(ret)[,
x][alpha(ret)[, x] != 0])
names(coef(ret)) <- lev(ret)
alphaindex(ret) <- lapply(sort(unique(y)), function(x)
which(alpha(ret)[,
x] != 0))
xmatrix(ret) <- x
obj(ret) <- resv[(nclass(ret) * nrow(xd) + 1)]
names(alphaindex(ret)) <- lev(ret)
svindex <- which(rowSums(alpha(ret) != 0) != 0)
b(ret) <- 0
param(ret)$C <- C
}
重要的部分有两件事,首先,如果我们提供ksvm
用我们自己的内核,然后ktype=4
(同时对于vanillakernel
, ktype=0
)所以它做了两个改变:
- 如果是用户定义的内核,则计算内核矩阵而不是实际使用内核
-
tron_optim
例程使用有关内核的信息运行
现在,在svm.cpp
我们可以找到tron
惯例,并在tron_run
(从调用tron_optim
), that LINEAR
内核有一个单独的优化例程
if (param->kernel_type == LINEAR)
{
/* lots of code here */
while (Cpj < Cp)
{
totaliter += s.Solve(l, prob->x, minus_ones, y, alpha, w,
Cpj, Cnj, param->eps, sii, param->shrinking,
param->qpsize);
/* lots of code here */
}
totaliter += s.Solve(l, prob->x, minus_ones, y, alpha, w, Cp, Cn,
param->eps, sii, param->shrinking, param->qpsize);
delete[] w;
}
else
{
Solver_B s;
s.Solve(l, BSVC_Q(*prob,*param,y), minus_ones, y, alpha, Cp, Cn,
param->eps, sii, param->shrinking, param->qpsize);
}
正如您所看到的,线性情况以更复杂、更详细的方式处理。有一个内部优化循环多次调用求解器。这需要对此处执行的实际优化进行真正深入的分析,但在这一步中,可以通过以下方式回答您的问题:
- 有no error在你的操作中
- kernlab的svm有一个单独的例程用于使用线性核训练 SVM,即根据类型传递给代码的内核,将“kernel”更改为“vanillakernel”使得
ksvm
认为它实际上与 vanillakernel 一起工作,因此执行了这个单独的优化例程
- It 看起来不是一个错误事实上,线性 SVM 在高效优化技术方面与核化版本有很大不同。需要处理的启发式问题和数值问题的数量确实很大。因此,需要一些近似值,并且可能会导致不同的结果。虽然对于丰富的特征空间(如 RBF 内核引起的特征空间)来说,这并不重要,但对于简单的线性内核来说,这种简化可能会导致显着的输出变化。