Помогите использовать предикат () для SVM Kernlab в R?

Я пытаюсь использовать kernlab Пакет R для поддержки опорных векторов (SVM). Для моего очень простого примера у меня есть две части обучающих данных. А и Б.

(А и В имеют тип matrix - это матрицы смежности для графов.)

Поэтому я написал функцию, которая принимает A+B и генерирует матрицу ядра.

> km
         [,1]     [,2]
[1,] 14.33333 18.47368
[2,] 18.47368 38.96053

Сейчас пользуюсь kernlab"s ksvm функция для генерации моей прогнозной модели. Прямо сейчас я просто пытаюсь заставить эту чертову вещь работать - я не беспокоюсь об ошибке обучения и т.д.

Итак, вопрос 1: правильно ли я генерирую свою модель? Разумно?

# y are my classes. In this case, A is in class "1" and B is in class "-1"
> y
[1]  1 -1

> model2 =  ksvm(km, y, type="C-svc", kernel = "matrix");
> model2
Support Vector Machine object of class "ksvm" 

SV type: C-svc  (classification) 
 parameter : cost C = 1 

[1] " Kernel matrix used as input."

Number of Support Vectors : 2 

Objective Function Value : -0.1224 
Training error : 0 

Все идет нормально. Мы создали нашу собственную матрицу ядра, а затем мы создали модель ksvm, используя эту матрицу. У нас есть наши тренировочные данные, помеченные как "1" и "-1".

Теперь, чтобы предсказать:

> A
     [,1] [,2] [,3]
[1,]    0    1    1
[2,]    1    0    1
[3,]    0    0    0

> predict(model2, A)
Error in as.matrix(Z) : object 'Z' not found

Ой-ой. Это нормально. Вид ожидаемого, правда. "Predict" хочет какой-то вектор, а не матрицу.

Итак, давайте попробуем несколько вещей:

> predict(model2, c(1))
Error in as.matrix(Z) : object 'Z' not found
> predict(model2, c(1,1))
Error in as.matrix(Z) : object 'Z' not found
> predict(model2, c(1,1,1))
Error in as.matrix(Z) : object 'Z' not found
> predict(model2, c(1,1,1,1))
Error in as.matrix(Z) : object 'Z' not found
> predict(model2, km)
Error in as.matrix(Z) : object 'Z' not found

Некоторые из вышеперечисленных тестов бессмысленны, но это моя точка зрения: независимо от того, что я делаю, я просто не могу заставить функцию предсказания () просмотреть мои данные и сделать прогноз. Скаляры не работают, векторы не работают. Матрица 2х2 не работает и матрица 3х3 не работает.

Что я здесь не так делаю?

(Как только я выясню, чего хочет ksvm, я смогу убедиться, что мои тестовые данные могут соответствовать этому формату разумным / разумным / математически обоснованным способом.)

4 ответа

Решение

Если вы подумаете о том, как машина опорных векторов может "использовать" матрицу ядра, вы увидите, что вы не можете сделать это так, как пытаетесь (как вы видели:-)

Я на самом деле немного боролся с этим, когда впервые использовал 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)

С этого момента я собираюсь:

  1. Создать обучающую матрицу ядра с именем trainK из оригинала K матрица ядра.
  2. Создать модель SVM из моего тренировочного набора trainK
  3. Используйте векторы поддержки, найденные в модели, для создания тестовой матрицы ядра testK... это странная часть. Если вы посмотрите на код в kernlab чтобы увидеть, как он использует индексы опорных векторов, вы поймете, почему это делается именно так. Возможно, это можно сделать по-другому, но я не видел документации / примеров по прогнозированию с помощью матрицы ядра, поэтому я делаю это "трудным путем" здесь.
  4. Используйте 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с и т. д.

Во-первых, я не использовал Kernlab много. Но, просто глядя на документы, я вижу рабочие примеры для predict.ksvm() метод. Копирование, вставка и пропуск печати на экран:

 ## example using the promotergene data set
 data(promotergene)

 ## create test and training set
 ind <- sample(1:dim(promotergene)[1],20)
 genetrain <- promotergene[-ind, ]
 genetest <- promotergene[ind, ]

 ## train a support vector machine
 gene <-  ksvm(Class~.,data=genetrain,kernel="rbfdot",\
               kpar=list(sigma=0.015),C=70,cross=4,prob.model=TRUE)

 ## predict gene type probabilities on the test set
 genetype <- predict(gene,genetest,type="probabilities")

Это кажется довольно прямолинейным: используйте случайную выборку, чтобы создать тренировочный набор genetrain и его дополнение genetest, тогда примерка через ksvm и вызов predict() метод с использованием подгонки и новые данные в соответствующем формате. Это очень стандартно.

Вам может пригодиться пакет карет Макса Куна. Он предоставляет общую структуру оценки и тестирования для различных методов и пакетов регрессии, классификации и машинного обучения, включая kernlab, и содержит несколько виньеток плюс документ JSS.

Стив Лианоглу прав.

В kernlab он немного запутан, и при прогнозировании требуется матрица входного ядра между каждым тестовым примером и векторами поддержки. Вам нужно найти эту матрицу самостоятельно.

Например, тестовая матрица [n x m], где n - количество тестовых выборок, а m - количество опорных векторов в изученной модели (упорядочено в последовательности SVindex(модель)).

Пример кода

trmat <- as.kernelMatrix(kernels[trainidx,trainidx])
tsmat <- as.kernelMatrix(kernels[testidx,trainidx])

#training
model = ksvm(x=trmat, y=trlabels, type = "C-svc", C = 1)

#testing
thistsmat = as.kernelMatrix(tsmat[,SVindex(model)])
tsprediction = predict(model, thistsmat, type = "decision")

kernels - это входная матрица ядра. trainidx и testidx - это идентификаторы для обучения и тестирования.

Создайте ярлыки самостоятельно из элементов решения. Используйте этот альтернативный метод предиктора, который использует модель ksvm (m) и данные в оригинальном формате обучения (d)

predict.alt <- function(m, d){
  sign(d[, m@SVindex] %*% m@coef[[1]] - m@b)
}

К является kernelMatrix для тренировки. Ради проверки, если вы запустите predict.alt на обучающих данных вы заметите, что альтернативный метод предиктора переключает значения вместе с подобранными значениями, возвращаемыми ksvm. Родной предиктор ведет себя неожиданным образом:

aux <- data.frame(fit=kout@fitted, native=predict(kout, K), alt=predict.alt(m=kout, d=as.matrix(K))) 
sample_n(aux, 10)
    fit  native alt
1     0       0  -1
100   1       0   1
218   1       0   1
200   1       0   1
182   1       0   1
87    0       0  -1
183   1       0   1
174   1       0   1
94    1       0   1
165   1       0   1
Другие вопросы по тегам