Pakiet e1071

set.seed(123)
x1 <- runif(200, 0, 1)
x2 <- runif(200, 0, 1)

y <- ((x1^2 + x2^2 - 2*x1*x2 < 0.25) & (x1+x2+x1^2)/(x1*x2) < 6) | (x1 + x2 < 0.3)
y <- factor(as.numeric(y)+1)

df <- data.frame(x1, x2, y)

png('svm1.png')
plot(x1, x2, col=y)
dev.off()
str(df)
## 'data.frame':    200 obs. of  3 variables:
##  $ x1: num  0.288 0.788 0.409 0.883 0.94 ...
##  $ x2: num  0.239 0.962 0.601 0.515 0.403 ...
##  $ y : Factor w/ 2 levels "1","2": 1 2 2 2 1 1 1 1 1 1 ...

Możemy dopasować model, domyśle jądro to jądro radialne. Na wykresie widać: prawdziwe klasy - oznaczone kolorem znaczków “x” i “o” czerwony/czarny, klasy przewidywane przez model - pełny kolor różowy/cyjan, “x” - wektory podpierające, “o” - pozostałe punkty w danych.

library(e1071)
svm.default <- svm(y~., data=df)

png('svm2.png')
plot(svm.default, data=df, formula=x2~x1)
dev.off()

Predykcja

obs <- data.frame(x1=0.5, x2=0.6)

mod.svm <- svm(y~., data=df)
predict(mod.svm, newdata=obs)
## 1 
## 2 
## Levels: 1 2
mod.svm <- svm(y~., data=df, probability=TRUE)
predict(mod.svm, newdata=obs, probability=TRUE)
## 1 
## 2 
## attr(,"probabilities")
##              1         2
## 1 0.0004886053 0.9995114
## Levels: 1 2
attr(predict(mod.svm, newdata=obs, probability=TRUE), "probabilities")
##              1         2
## 1 0.0004886053 0.9995114

Zmiana jądra

svm.rad <- svm(y~., data=df, kernel="radial")
svm.lin <- svm(y~., data=df, kernel="linear")
svm.pol <- svm(y~., data=df, kernel="polynomial", degree=3)
svm.sig <- svm(y~., data=df, kernel="sigmoid")
png('svm31.png')
plot(svm.rad, data=df)
dev.off()
png('svm32.png')
plot(svm.lin, data=df)
dev.off()
png('svm33.png')
plot(svm.pol, data=df)
dev.off()
png('svm34.png')
plot(svm.sig, data=df)
dev.off()

Jądro radialne Jądro liniowe Jądro wielomianowe Jądro sigmoidalne

Zmiana innych parametrów

gamma, parametr potrzebny do wszystkich jąder oprócz liniowego:

  • linear: u’*v
  • polynomial: (gammau’v + coef0)^degree
  • radial basis: exp(-gamma*|u-v|^2)
  • sigmoid: tanh(gammau’v + coef0)

cost - ten parametr, który stoi przy wyrazie odpowiadającym regularyzacji

degree - jeśli jądro wielomianowe, to to odpowiada za stopień wielomianu

coef0 - do wielomianowego i sigmoidalnego

mod.inne.parametry <- svm(y~., data=df, gamma=0.1, cost=1.5)

“Tuningowanie” parametrów

par.svm <- tune.svm(y~., data=df, 
                    gamma=c(0.01, 0.3, 0.5, 0.8, 1), 
                    cost=c(1, 1.5, 2, 2.5, 3))
summary(par.svm)
## 
## Parameter tuning of 'svm':
## 
## - sampling method: 10-fold cross validation 
## 
## - best parameters:
##  gamma cost
##      1  2.5
## 
## - best performance: 0.045 
## 
## - Detailed performance results:
##    gamma cost error dispersion
## 1   0.01  1.0 0.235 0.09442810
## 2   0.30  1.0 0.085 0.10013879
## 3   0.50  1.0 0.065 0.08181958
## 4   0.80  1.0 0.060 0.07745967
## 5   1.00  1.0 0.075 0.08249579
## 6   0.01  1.5 0.225 0.10069205
## 7   0.30  1.5 0.080 0.09775252
## 8   0.50  1.5 0.055 0.05986095
## 9   0.80  1.5 0.055 0.06433420
## 10  1.00  1.5 0.065 0.06687468
## 11  0.01  2.0 0.220 0.11105554
## 12  0.30  2.0 0.060 0.06992059
## 13  0.50  2.0 0.060 0.06582806
## 14  0.80  2.0 0.060 0.06582806
## 15  1.00  2.0 0.065 0.06258328
## 16  0.01  2.5 0.225 0.10865337
## 17  0.30  2.5 0.055 0.06851602
## 18  0.50  2.5 0.065 0.06687468
## 19  0.80  2.5 0.065 0.06258328
## 20  1.00  2.5 0.045 0.06433420
## 21  0.01  3.0 0.215 0.11067972
## 22  0.30  3.0 0.060 0.07745967
## 23  0.50  3.0 0.075 0.08249579
## 24  0.80  3.0 0.055 0.08316650
## 25  1.00  3.0 0.050 0.07817360
par.svm$best.parameters
##    gamma cost
## 20     1  2.5
mod.svm.best <- svm(y~., data=df, 
                    gamma=par.svm$best.parameters$gamma,
                    cost=par.svm$best.parameters$cost)
# plot(mod.svm.best, data=df)

Wykres przedstawia zależność błędu od parametrów:

png("svm4.png")
plot(par.svm)
dev.off()

Pakiet kernlab

library(kernlab)

ksvm.default <- ksvm(y~., data=df)
predict(ksvm.default, newdata=obs)
## [1] 2
## Levels: 1 2
ksvm.prob <- ksvm(y~., data=df, prob.model=TRUE)
predict(ksvm.prob, newdata=obs, type="probabilities")
##                 1         2
## [1,] 9.764555e-05 0.9999024
png("svm5.png")
plot(ksvm.default, data=df)
dev.off()

Tu można znaleźć te i inne pakiety

https://epub.wu.ac.at/1500/1/document.pdf