Я пытаюсь понять, как построить границу решения для подобранной модели SVM в ggplot2. Прямо сейчас я пытаюсь сделать это с помощью stat_contour. Вот мой код с примером вызова моей функции в конце. Вы можете найти файлы данных, которые я использую, на моей странице github:
train <- read.table('train.txt', col.names = c('digit', 'intensity', 'symmetry'))
test <- read.table('test.txt', col.names = c('digit', 'intensity', 'symmetry'))
digits.SVM <- function(train, test, digits = c(1, 5), C = 0.01, kernel = 'radial', degree = 3, gamma = 1, coef0 = 0, scale = FALSE, type = 'C-classification', plotApproximation = FALSE) {
library(e1071)
library(ggplot2)
library(reshape2)
if(length(digits) != 1 && length(digits) != 2)
stop('Invalid length of digits vector. Must specify one or two digits to classify')
if(length(digits) == 2) {
train <- train[(train$digit == digits[1]) | (train$digit == digits[2]), ]
test <- test[(test$digit == digits[1]) | (test$digit == digits[2]), ]
}
train$class <- -1
test$class <- -1
train[train$digit == digits[1], ]$class <- 1
test[test$digit == digits[1], ]$class <- 1
fit <- svm(class~intensity + symmetry, data = train, cost = C, kernel = kernel, degree = degree, gamma = gamma, coef0 = coef0, scale = scale, type = type)
class_fitted <- predict(fit, train[c('intensity', 'symmetry')])
gridRange <- apply(train[c('intensity', 'symmetry')], 2, range)
x1 <- seq(from = gridRange[1, 1] - 0.025, to = gridRange[2, 1] + 0.025, length = 75)
x2 <- seq(from = gridRange[1, 2] - 0.05, to = gridRange[2, 2] + 0.05, length = 75)
grid <- expand.grid(intensity = x1, symmetry = x2)
grid$class <- predict(fit, grid)
decisionValues <- predict(fit, grid, decision.values = TRUE)
grid$z <- as.vector(attributes(decisionValues)$decision)
print(colnames(grid))
print(head(grid))
p <- ggplot(data = grid, aes(intensity, symmetry, colour = as.factor(class))) +
geom_point(size = 1.5) +
scale_fill_manual(values = c('red', 'black')) +
stat_contour(data = grid, aes(x = intensity, y = symmetry, z = z), breaks = c(0)) +
geom_point(data = train, aes(intensity, symmetry, colour = as.factor(class)), alpha = 0.7) +
scale_colour_manual(values = c('red', 'black')) + labs(colour = 'Class') +
scale_x_continuous(expand = c(0,0)) +
scale_y_continuous(expand = c(0,0))
print(p)
mean(train$class != class_fitted)
}
digits.SVM(train, test, digits = c(0), kernel = 'polynomial', degree = 2, coef0 = 1)
Моя проблема возникает при установке параметра «перерывы» в stat_contour (). Большинство значений, которые я установил, разбиваются, чтобы не вызывать никаких проблем; вот график, который получается, когда breaks = -1.
Однако правильная граница соответствует контуру, который возник бы в результате установки breaks = 0, и когда я установил breaks ближе к 0, ggplot начинает испытывать проблемы с построением контура. Он начинает обрезаться и при значении ровно 0 просто не рисует контур.
Вот пример графика с breaks = -0.05:
Как видите, граница начинает срезаться. Вот график с использованием breaks = 0:
Вырезан весь контур.
Я также получаю это сообщение об ошибке:
Предупреждающие сообщения: 1: Невозможно создать данные контура
Я относительно новичок в ggplot2 и не уверен, что stat_contour () делает в фоновом режиме. Я пытался найти его реализацию, но безуспешно. Мы будем благодарны за любую помощь и разъяснения!
Я также приветствовал бы любые предложения о лучших способах достижения этой цели.