SVM的不同导致R具有相同的输入和参数

时间:2016-07-28 12:27:00

标签: r machine-learning svm scalability

我使用以下参数为列车数据集中的欺诈检测开发了SVM模型:

set.seed(1234)
gamma.optimal <- 0.02
cost.optimal <- 4
svm_model1 <- svm(log(response+0.00012345) ~ . , data_test, kernel="radial", gamma=gamma.opt, cost=cost.opt)

创建SVM后,我在测试数据集中评估了我的svm_model1以获取总欺诈数量: sum(response)它等于30.080美元:

predictions <- exp(predict(svm_model1 , testing))

在笔记本电脑(使用R GUI的本地模式)和使用SparkR的小型集群(4个节点和1个使用Cloudera 5.6的主服务器)中,此结果相同。

对这些结果感到满意我尝试使用相同的测试数据集执行相同的R脚本使用{{保存的相同svm_model1 1}}在.Rdata可执行文件中,但这次是在2个不同的系统中:Oracle BDA(6个从属节点和1个主节点),另一个有4个从属节点和Cloudera 5.7。

这两个最终系统的结果是:set.seed(1234)等于30.130美元,使用相同的。

sum(response)

我的问题是:

1)如果我使用相同的脚本,相同的模型保存在可执行文件(.Rdata)中,并且数据相同;带有径向内核的predictions <- exp(predict(svm_model1 , testing)) svm怎么可能给出不同的结果呢?

2)这些结果是否与径向内核性质和并行处理问题或不同的硬件特性有关?或者,如果您使用e1071,那么无论您使用哪种硬件,结果在使用set.seed()函数的R中都必须相同?

我非常感谢您的时间和帮助。最好的问候。

3 个答案:

答案 0 :(得分:1)

由于预测函数(显然)是确定性的,结果应该是相同的 - 但e1071使用LIBSVM,即C ++代码 - 并且浮点运算可以(并且将)在硬件平台之间变化(甚至对于不同的编译器)标志和/或编译器)。 您可以尝试编写自己的R预测函数,该函数应该(对于固定模型)在所有平台上给出相同的答案。

答案 1 :(得分:0)

我认为你可以检查发生了什么的最简单方法是自己计算预测值(不使用预测函数)。以下是如何手动计算e1071中创建的svm模型对象的预测值的说明。

#TO GENERAGE TOY DATA
set.seed(994522)
Se <- 0.15
D <- data.frame(X=runif(n=20,min=0,max=6))
D$ActualY <- 3 + sin(D$X)
D <- D[order(D$X),]
rownames(D) <- 1:nrow(D)
D$Residual <- rnorm(n=nrow(D),mean=0,sd=Se)
NoisyPoints <- sample(1:nrow(D),8,replace=F)
D$Noise <- ifelse(rownames(D) %in% NoisyPoints,rnorm(n=nrow(D),mean=0,sd=2*Se),0)
D$Noisy <- ifelse(rownames(D) %in% NoisyPoints,1,0)
D$Y <- D$ActualY + D$Residual + D$Noise
D[,-5] <- round(D[,-5],digits=2)

#PARAMETER GRID
(MyEpsilons <- mean(D$Y)*c(0.01, seq(0.05, 0.20, 0.05)))
(MyGammas <- 10^(seq(-3, 3, 1)))
(MyCosts <- 10^(0:3))

#PARAMETER TUNING
TunesRBF <- tune.svm(x=D$X, y=D$Y, gamma=MyGammas, cost=MyCosts, epsilon=MyEpsilons, kernel="radial")
(BestPar <- summary(TunesRBF)$best.parameters)
(BestSVRrbf <- best.svm(x=D$X, y=D$Y,tunecontrol=tune.control(cross=5),cost=MyCosts,epsilon=MyEpsilons,gamma=MyGammas))

#SVM FITTING
(SVRrbf <- svm(x=D$X, y=D$Y, gamma=BestPar$gamma, cost=BestPar$cost, epsilon=BestPar$epsilon, kernel="radial"))

#TO GENERATE NEW SAMPLES
set.seed(224599)
NewSamples <- data.frame(X=runif(n=5,min=0,max=6))
NewSamples$PredY <- predict(SVRrbf,NewSamples)
NewSamples <- round(NewSamples,digits=2)

#TO EXTRACT MODEL PARAMETERS
V <- as.matrix(SVRrbf$SV)
A <- as.matrix(SVRrbf$coefs)
(g <- SVRrbf$gamma)
(C <- SVRrbf$cost)
(r <- SVRrbf$rho)

#TO MANUALLY GET PREDICTED VALUES NEW SAMPLES
X <- NewSamples[,1,drop=F]
KernelNewSamples <- matrix(0, nrow(NewSamples), nrow(V))
MeanX <- mean(D[,1])  #YOU NEED THIS FOR STANDARDIZING NEW SAMPLES
SdX <- sd(D[,1])  #YOU NEED THIS FOR STANDARDIZING NEW SAMPLES
#STANDARDIZATION
Xs <- (NewSamples[,1,drop=F]-MeanX)/SdX
#GETTING THE KERNEL FOR THE rbf
for (i in 1:nrow(NewSamples)) {
    for (j in 1:nrow(V)) {
        Xi <- Xs[i,]
        Vj <- V[j,]
        XiMinusVj <- Xi - Vj
        SumSqXiMinusVj <- XiMinusVj %*% XiMinusVj
        KernelNewSamples[i,j] <- exp(-g*SumSqXiMinusVj)
    }
}

#TO PREDICT NEW SAMPLES
PredNewSamples <- KernelNewSamples %*% A - r
#TO BACK TRANSFORM TO ORIGINAL Y SCALE
MeanY <- as.numeric(SVRrbf$y.scale[1])
StdY <- as.numeric(SVRrbf$y.scale[2])
PredNewSamples <- PredNewSamples*StdY + rep(MeanY,nrow(NewSamples))
cbind(NewSamples,PredNewSamples)

答案 2 :(得分:0)

svr软件包还建议进行交叉验证,在tune.svr情况下默认为k = 10(k倍交叉验证)

由于选择集合的过程是相当随机的,因此在每次执行中可能导致不同的结果(但非常相似),因此对于SVM而言,预测结果也不同。

在Wikipedia中,关于交叉验证的内容为:

  

在k折交叉验证中,原始样本是随机的   分成k个大小相等的子样本。在k个子样本中,   保留单个子样本作为检验数据的验证数据   模型,其余的k − 1个子样本用作训练数据。   然后,将交叉验证过程重复k次,每次   k个子样本仅使用一次作为验证数据。 k   然后可以将结果取平均以产生单个估计值。