Mam zestaw danych z dwiema nakładającymi się klasami, po siedem punktów w każdej klasie, punkty są w przestrzeni dwuwymiarowej. W R i biegnę svm
z e1071
pakietu, aby zbudować oddzielną hiperpłaszczyznę dla tych klas. Używam następującego polecenia:
svm(x, y, scale = FALSE, type = 'C-classification', kernel = 'linear', cost = 50000)
gdzie x
zawiera moje punkty danych i y
ich etykiety. Polecenie zwraca obiekt svm, którego używam do obliczenia parametrów (wektor normalny) (przecięcie) hiperpłaszczyzny oddzielającej.b
Rysunek (a) poniżej pokazuje moje punkty i hiperpłaszczyznę zwróconą przez svm
polecenie (nazwijmy tę hiperpłaszczyznę optymalną). Niebieski punkt z symbolem O pokazuje początek przestrzeni, linie przerywane pokazują margines, kółka to punkty, które mają niezerowe (zmienne luzu).
Rysunek (b) pokazuje inną hiperpłaszczyznę, która jest równoległą translacją optymalnej o 5 (b_new = b_optimal - 5). Nietrudno zauważyć, że dla tej hiperpłaszczyzny funkcja celu (która jest zminimalizowana przez klasyfikację C svm) będzie miała niższą wartość niż dla optymalnej hiperpłaszczyzny pokazanej na rysunku ( za). Czy to wygląda na problem z tą funkcją? A może gdzieś popełniłem błąd?
svm
Poniżej znajduje się kod R, którego użyłem w tym eksperymencie.
library(e1071)
get_obj_func_info <- function(w, b, c_par, x, y) {
xi <- rep(0, nrow(x))
for (i in 1:nrow(x)) {
xi[i] <- 1 - as.numeric(as.character(y[i]))*(sum(w*x[i,]) + b)
if (xi[i] < 0) xi[i] <- 0
}
return(list(obj_func_value = 0.5*sqrt(sum(w * w)) + c_par*sum(xi),
sum_xi = sum(xi), xi = xi))
}
x <- structure(c(41.8226593092589, 56.1773406907411, 63.3546813814822,
66.4912298720281, 72.1002963174962, 77.649309469458, 29.0963054665561,
38.6260575252066, 44.2351239706747, 53.7648760293253, 31.5087701279719,
24.3314294372308, 21.9189647758150, 68.9036945334439, 26.2543850639859,
43.7456149360141, 52.4912298720281, 20.6453186185178, 45.313889181287,
29.7830021158501, 33.0396571934088, 17.9008386892901, 42.5694092520593,
27.4305907479407, 49.3546813814822, 40.6090664454681, 24.2940422573947,
36.9603428065912), .Dim = c(14L, 2L))
y <- structure(c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L,
1L), .Label = c("-1", "1"), class = "factor")
a <- svm(x, y, scale = FALSE, type = 'C-classification', kernel = 'linear', cost = 50000)
w <- t(a$coefs) %*% a$SV;
b <- -a$rho;
obj_func_str1 <- get_obj_func_info(w, b, 50000, x, y)
obj_func_str2 <- get_obj_func_info(w, b - 5, 50000, x, y)
Odpowiedzi:
W libsvm FAQ jest wspomniane, że etykiety używane „wewnątrz” algorytmu mogą się różnić od twoich. Czasami odwróci to znak „cewek” modelu.
Zobacz pytanie „Dlaczego znak przewidywanych etykiet i wartości decyzji jest czasami odwracany?” Tutaj .
źródło
Ten sam problem wystąpił przy użyciu LIBSVM w MATLAB. Aby to przetestować, stworzyłem bardzo prosty, dwuwymiarowy, liniowo rozdzielany zestaw danych, który został przetłumaczony wzdłuż jednej osi na około -100. Trening liniowego svm przy użyciu LIBSVM wytworzył hiperpłaszczyznę, której przechwytywanie wciąż znajdowało się dokładnie wokół zera (a więc wskaźnik błędów wynosił oczywiście 50%). Ujednolicenie danych (odjęcie średniej) pomogło, choć wynikowy svm nadal nie działał idealnie ... zakłopotany. Wygląda na to, że LIBSVM obraca hiperpłaszczyznę wokół osi bez jej translacji. Być może powinieneś spróbować odjąć średnią z danych, ale wydaje się dziwne, że LIBSVM zachowałby się w ten sposób. Być może czegoś nam brakuje.
Za to, co jest warte, wbudowana funkcja MATLAB
svmtrain
stworzyła klasyfikator ze 100% dokładnością, bez standaryzacji.źródło