Если вы подумаете о том, как машина опорных векторов может «использовать» матрицу ядра, вы увидите, что вы не можете сделать это так, как пытаетесь (как вы видели: -)
Я на самом деле немного боролся с этим, когда впервые использовал Kernlab + матрицу ядра ... по совпадению, это было также и для графовых ядер!
В любом случае, давайте сначала поймем, что, поскольку SVM не знает, как рассчитать вашу функцию ядра, ему необходимо рассчитать эти значения уже между вашими новыми (тестирующими) примерами и примерами, которые он выбирает в качестве векторов поддержки во время шаг тренировки.
Итак, вам нужно вычислить матрицу ядра для всех ваших примеров вместе. Позже вы будете тренироваться на некоторых и тестировать на других, удаляя строки + столбцы из матрицы ядра, когда это уместно. Позвольте мне показать вам код.
Мы можем использовать пример кода в документации ksvm
для загрузки нашего рабочего пространства некоторыми данными:
library(kernlab)
example(ksvm)
Вам нужно будет нажать return несколько раз (2), чтобы графики прорисовывались, и пример заканчивался, но теперь у вас должна быть матрица ядра в вашем рабочем пространстве с именем K
. Нам нужно восстановить вектор y
, который он должен использовать для своих меток (так как он был растоптан другим кодом в примере):
y <- matrix(c(rep(1,60),rep(-1,60)))
Теперь выберите набор примеров для тестирования
holdout <- sample(1:ncol(K), 10)
С этого момента я собираюсь:
- Создайте обучающую матрицу ядра с именем
trainK
из исходной K
матрицы ядра.
- Создание модели SVM из моего тренировочного набора
trainK
- Использование векторов поддержки, найденных в модели, для создания тестовой матрицы ядра
testK
... это странная часть. Если вы посмотрите на код в kernlab
, чтобы увидеть, как он использует индексы опорных векторов, вы поймете, почему это делается именно так. Возможно, это можно сделать иным способом, но я не видел документации / примеров по , предсказывающим с матрицей ядра, поэтому я делаю это "трудным путем" здесь.
- Использование SVM для прогнозирования этих функций и точности отчетов
Вот код:
trainK <- as.kernelMatrix(K[-holdout,-holdout]) # 1
m <- ksvm(trainK, y[-holdout], kernel='matrix') # 2
testK <- as.kernelMatrix(K[holdout, -holdout][,SVindex(m), drop=F]) # 3
preds <- predict(m, testK) # 4
sum(sign(preds) == sign(y[holdout])) / length(holdout) # == 1 (perfect!)
Это должно вот-вот сделать. Удачи!
Ответы на комментарии ниже
что означает K [-holdout, -holdout]? (что означает "-"?)
Представьте, что у вас есть вектор x
, и вы хотите извлечь из него элементы 1, 3 и 5, вам нужно сделать:
x.sub <- x[c(1,3,5)]
Если вы хотите извлечь все из x
, кроме элементов 1, 3 и 5, вам нужно сделать:
x.sub <- x[-c(1,3,5)]
Итак, K[-holdout,-holdout]
возвращает все строки и столбцы K
, кроме для строк, которые мы хотим удержать.
Каковы аргументы вашего as.kernelMatrix - особенно аргумент [, SVindex (m), drop = F] (что особенно странно, поскольку похоже, что вся скобка представляет собой матричный индекс K?)
Да, я встроил две команды в одну:
testK <- as.kernelMatrix(K[holdout, -holdout][,SVindex(m), drop=F])
Теперь, когда вы обучили модель, вы хотите дать ей новую матрицу ядра с вашими примерами тестирования. K[holdout,]
даст вам только строки, которые соответствуют обучающим примерам в K
, и все столбцы K
.
SVindex(m)
дает вам индексы ваших векторов поддержки из вашей оригинальной матрицы обучения - помните, у этих строк / столбцов удалено holdout
. Поэтому, чтобы эти индексы столбцов были правильными (т. Е. Ссылаются на правильный столбец sv), я должен сначала удалить столбцы holdout
.
Во всяком случае, возможно, это более ясно:
testK <- K[holdout, -holdout]
testK <- testK[,SVindex(m), drop=FALSE]
Теперь testK
содержит только строки наших примеров тестирования и столбцы, которые соответствуют опорным векторам. testK[1,1]
будет иметь значение функции ядра, вычисленное между вашим первым примером тестирования и первым опорным вектором. testK[1,2]
будет иметь значение функции ядра между вашим первым примером тестирования и вторым вектором поддержки и т. Д.
Обновление (2014-01-30) для ответа на комментарий от @ wrahool
Прошло много времени с тех пор, как я поиграл с этим, поэтому подробности kernlab::ksvm
немного ржавые, но в принципе это должно быть правильно :-) ... вот так:
в чем смысл testK <- K[holdout, -holdout]
- разве вы не удаляете столбцы, которые соответствуют тестовому набору?
Да. Краткий ответ: если вы хотите predict
использовать матрицу ядра, вы должны предоставить матрицу, имеющую размерность rows
, на support vectors
. Для каждой строки матрицы (новый пример, который вы хотите предсказать) значения в столбцах являются просто значением матрицы ядра, вычисленной между этим примером и опорным вектором.
Вызов SVindex(m)
возвращает индекс векторов поддержки, заданных в измерении оригинальных обучающих данных.
Итак, сначала выполнение testK <- K[holdout, -holdout]
дает мне матрицу testK
со строками примеров, которые я хочу предсказать, и столбцы взяты из тех же примеров (измерений), на которых обучалась модель.
Далее я подставлю столбцы testK
на SVindex(m)
, чтобы получить только те столбцы, которые (сейчас) соответствуют моим опорным векторам. Если бы я не сделал первый выбор [, -holdout]
, индексы, возвращаемые SVindex(m)
, могут не соответствовать правильным примерам (если только все N
ваших тестовых примеров не являются последними N
столбцами вашей матрицы).
Кроме того, что именно делает условие drop = FALSE?
Это немного защитное кодирование, чтобы гарантировать, что после выполнения операции индексации возвращаемый объект будет того же типа, что и индексированный объект.
В R, если вы индексируете только одно измерение 2D (или более высокого (?)) Объекта, вам возвращается объект более низкого измерения. Я не хочу передавать numeric
вектор в predict
, потому что он хочет иметь matrix
Например
x <- matrix(rnorm(50), nrow=10)
class(x)
[1] "matrix"
dim(x)
[1] 10 5
y <- x[, 1]
class(y)
[1] "numeric"
dim(y)
NULL
То же самое произойдет с data.frame
с и т. Д.