gpt4 book ai didi

r - (在 R 中)为什么使用用户定义的线性内核的 ksvm 的结果与使用 "vanilladot"的 ksvm 的结果不同?

转载 作者:行者123 更新时间:2023-11-30 08:29:02 29 4
gpt4 key购买 nike

我想在 R 中为 Ksvm 使用用户定义的内核函数。因此,我尝试制作一个 vanilladot 内核,并与“kernlab”中内置的“vanilladot”进行比较作为练习。

我按如下方式编写内核。

#
###vanilla kernel with class "kernel"
#
kfunction.k <- function(){
k <- function (x,y){crossprod(x,y)}
class(k) <- "kernel"
k}
l<-0.1 ; C<-1/(2*l)

###use kfunction.k
tmp<-ksvm(x,factor(y),scaled=FALSE, type = "C-svc", kernel=kfunction.k(), C = C)
alpha(tmp)[[1]]
ind<-alphaindex(tmp)[[1]]
x.s<-x[ind,] ; y.s<-y[ind]
w.class.k<-t(alpha(tmp)[[1]]*y.s)%*%x.s
w.class.k

我认为此操作的结果与以下操作的结果相同。然而事实并非如此。

#
###use "vanilladot"
#
l<-0.1 ; C<-1/(2*l)
tmp1<-ksvm(x,factor(y),scaled=FALSE, type = "C-svc", kernel="vanilladot", C = C)
alpha(tmp1)[[1]]
ind1<-alphaindex(tmp1)[[1]]
x.s<-x[ind1,] ; y.s<-y[ind1]
w.tmp1<-t(alpha(tmp1)[[1]]*y.s)%*%x.s
w.tmp1

我认为这个问题可能与内核类有关。当class设置为“kernel”时,就会出现这个问题。但是,当 class 设置为“vanillakernel”时,使用用户定义内核的 ksvm 的结果与使用 Kernlab 中内置的“vanilladot”的 ksvm 的结果相同。

#
###vanilla kernel with class "vanillakernel"
#
kfunction.v.k <- function(){
k <- function (x,y){crossprod(x,y)}
class(k) <- "vanillakernel"
k}
# The only difference between kfunction.k and kfunction.v.k is "class(k)".
l<-0.1 ; C<-1/(2*l)

###use kfunction.v.k
tmp<-ksvm(x,factor(y),scaled=FALSE, type = "C-svc", kernel=kfunction.v.k(), C = C)
alpha(tmp)[[1]]
ind<-alphaindex(tmp)[[1]]
x.s<-x[ind,] ; y.s<-y[ind]
w.class.v.k<-t(alpha(tmp)[[1]]*y.s)%*%x.s
w.class.v.k

我不明白为什么将类设置为“kernel”时结果与“vanilladot”不同。

我的操作有错误吗?

最佳答案

首先,这似乎是一个非常好的问题!

现在进入正题。来源 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 (而对于 vanillakernelktype=0 )因此它做了两个更改:

  • 如果是用户定义的内核,则计算内核矩阵,而不是实际使用内核
  • tron_optim例程使用有关内核的信息运行

现在,在 svm.cpp我们可以找到tron例程,以及 tron_run (从 tron_optim 调用),即 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);
}

正如您所看到的,线性情况以更复杂、更详细的方式处理。有一个内部优化循环多次调用求解器。这需要对此处执行的实际优化进行真正深入的分析,但在这一步中,可以通过以下方式回答您的问题:

  • 您的操作没有错误
  • kernlab 的 svm 有一个单独的例程,用于使用线性内核训练 SVM,它基于传递给代码的内核类型,将“kernel”更改为“vanillakernel” ” 做了ksvm 认为它实际上正在与 vanillakernel 一起工作,因此执行了这个单独的优化例程
  • 事实上,它看起来并不是一个错误,因为线性 SVM 实际上在高效优化技术方面与内核化版本有很大不同。需要处理的启发式问题和数值问题的数量确实很大。因此,需要一些近似值,并且可能会导致不同的结果。虽然对于丰富的特征空间(如 RBF 内核引起的特征空间)来说,这并不重要,但对于简单的线性内核 - 这种简化可能会导致显着的输出变化。

关于r - (在 R 中)为什么使用用户定义的线性内核的 ksvm 的结果与使用 "vanilladot"的 ksvm 的结果不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17691036/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com