Support Vector Machines
Erik Kanebrant, erika625
Inledning
Support Vector Machines (SVM) är en teknik för maskininlärning. Principen bygger på att
man tränar upp systemet med data från en befintlig databas innehållande värden observerade i
världen. Genom att låta inlärningsalgoritmen gå igenom data tränar man upp systemet att
sedan förutsäga och kategorisera ännu okänd data. SVMs bygger alltså på statistisk inlärning
så detta kommer kort att gås igenom för att lägga grunden.
Statistisk inlärning
Svm bygger på statistisk inlärning av en datamängd, att genom statistisk analysering av redan
kända fall kunna förutsäga kategorisering av ny data. Man vill alltså kunna estimera utfallet
av en särskild input. Detta för att slippa hantera stora datamängder manuellt, finna nya utfall i
en datamängd eller rent av kunna dra slutsatser ur en datastruktur som är för komplex att
hanteras manuellt. Ett exempel på tillämpning kan vara att tilldela handskrivna bokstäver rätt
ASCII-kod för att översätta dessa till digitala bokstäver. Man börjar då alltså med att i den
tränande datamängden sätta korrekta relationer mellan bokstäver och ASCII. Från denna
begränsade mängd relationer är målet alltså att systemet sedan ska kunna relatera tidigare
okända varianter av en handskriven bokstav till rätt ASCII-kod. Detta är dock inte hela
poängen då det kan argumenteras för att man kan bygga en komplett datastruktur som redan
hanterar alla fall av relationer. Målet med systemet är inte bara den att det i samtliga fall ska
tilldela rätt värden utan att finna en regel för att förutsäga vilka värden som ska tilldelas
hittills okänd data. De matematiska principer detta grundar sig på ser ut på följande sätt:
Alla värden x, där x är en vektor, finns i en känd mängd X som beskriver format och
räckvidd. Anta en känd mängd Y som beskriver de klasser som x kan tilldelas, t ex. {-1,+1}
som alltså säger att x kan få antingen klassen -1 eller +1 vilket är fallet i den enklaste formen
av en svm. Detta bildar sekvensen D ((x1,y1),...,(xn,yn)) som innehåller alla möjliga tolkningar
av f : X -> Y så at f(x) är en estimering av responsen y till godtyckligt x, f(x) är alltså
funktionen vi tränar för att sedan klassificera ny data. för att funktionen ska fungera så måste
även datamängden, D, ha något gemensamt med ny data.
Detta försäkras genom att anta att alla par (x,y), redan kända som okända, har samma
sannolikhetsfördelning P X * Y. Alltså så genereras först värdet på x genom fördelningen P x,
sedan genereras y enligt P av y givet värdet på x. Detta medför att eftersom vi inte har
kontroll över sannolikheten av x så antar vi att vi inte har någon kontroll över hur värden har
observerats och kommer till att observeras. Nästa steg, och även det som gör att data kan
användas i ett inlärande syfte, är att ge responsen på f(x) ett kvalitetsmått, alltså de par (x,y)
som genereras enligt tidigare formel. Måttet representeras av ett positivt reellt tal, L, som är
mindre när responsen är god. Formeln ser ut på följande sätt: L(x,y,f(x)), funktionen kallas
”loss function” och representerar alltså förlorad säkerhet vilket förklarar varför ett lägre L visar på en godare respons av f(x). I exemplet med enbart två möjliga klasser skulle alltså L
bli 1 när klassen inte är en matchning och 0 när den är det och på så sätt möjliggöra en korrekt
klasstilldelning av x. I exempel med fler klasser än bara sant och falskt skulle värdet på L ge
ett mått på med hur stor säkerhet x har tilldelats korrekt klass.
Grundprincipen för SVM
För att till en början enkelt beskriva hur en svm fungerar kommer vi att utgå från ett exempel
med data som är linjärt separabel och kan delas in i två klasser, x för data och y för klass. x är
då en vektor innehållande data och y bestämmer vilken klass x tillhör, i detta exempel väljs y
ur mängden {1, -1}. Eftersom denna data är linjärt separabel kan den delas med ett hyperplan.
I tillägg till detta ritas ett nytt hyperplan upp på vardera sida om det första för att få en buffert
mellan klassindelningen. Det ursprungliga hyperplanet beskrivs med formeln w * x + b = 0
där w är hyperplanets normalriktning, x är samma som tidigare och b är avståndet från origo, *
betyder i det här fallet skalärprodukten. De resterande hyperplanen får värdena 1 och -1 från
samma formel, w * x + b = 1 och w * x + b = -1. Vi tillåter sedan endast värden att ligga
utanför de yttre hyperplanen och således så har vi klassificerat alla x till antingen 1 eller -1.
De vektorer som angränsas dessa hyperplan, alltså 1 eller -1 kallas för support vectors
eftersom de ”håller upp” planet. Nya värden som förs in klassificeras alltså utefter deras
förhållande till dessa vektorer.
Figur 1. Figuren visar de tre hyperplanen och deras ekvationer, support vectors som angränsar
planet samt svarta prickar och ringar som är klassindelade data, x.
Icke-linjärt separabel data och kerneltricket
I de flesta tillämpningsfallen så vill man kunna hantera data som ej går att separera linjärt i ett
två-dimensionellt plan. Lösningen blir då att införa en så kallad kärna, kernel, som låter
vektorerna beräknas i en högre dimension, i det här fallet kallat för feature space (se
Hilbertrum, ett abstrakt vektorrum som utökar vektoralgebra till oändligt antal dimensioner.).
I detta feature space beräknas den inre skalärprodukten av vektorn. Anledningen till att man
väljer detta tillvägagångssätt är för att en SVM är byggd för att skilja data linjärt och på så sätt
definiera den och genom att beräkna den inre skalärprodukten hos vektorerna i ett högre
feature space så kan man få data att bli linjärt separabel även om den inte är det från början.
Det finns ingen begränsning på antalet dimensioner man kan införa, med vissa specifika
undantag så kan all data fås separabel genom att införa N-1 dimensioner för N datavärden.
Figur 2. Då data inte kan separeras linjärt, som tydligt ses att så är fallet i den första bilden så
inför man en ny dimension, så kallat feature space där det nya hyperplanet separerar data
linjärt.
Rummet X som data ursprungligen representeras i kartläggs istället i ett feature space H, Φ: X -> H. Vilket ger mängden ((Φ(x1),(y1),...,(Φ(xn),(yn) istället för den tidigare mängden
((x1,y1),...,(xn,yn)). Φ används alltså för att visa att mängden nu hör till ett feature space och att det är den inre skalärprodukten som beräknas. Enskilda skalärprodukter (x * y) skrivs om till
(Φ(x) * Φ(y)) som alltså är den inre skalärprodukten i ett feature space.
Det är nu kerneltricket blir användbart. Genom att införa kärnan K så kan man skriva om
(Φ(x)*Φ(y)) till K(x,y) vilket leder till att vi kan beräkna den inre skalärprodukten utan att behöva konvertera all data till ett feature space, beräkna den där och sedan återinföra den i en
form som är linjärt separabel. Vi håller oss till att införa en tredje dimension för att kunna
använda figur 2 för att illustrera exemplet. Kärnan vi inför är K(x, y) = (x * y)2, detta härleds
från (x12, x22, √2 x1 x2) * (y12, y22, √2 y1 y2) = (Φ(x) * Φ(y)) som visar hur vi får fram de inre
skalärprodukterna från ursprungliga skalärprodukter. Skalärprodukterna kvadreras alltså
vilket leder till att ringarna i figur 2 kommer att kunna separeras från kryssen då x12 + x22
alltid är mindre för ringarna än för kryssen. Hade man satt en skala på figur2 hade man kunnat
skriva det som x12 + x22 <= 1 och på så sätt tydliggjort klassindelningen.
Hantering av data med fler än två klasser, Sequential Minimal Optimization
Hittills har vi endast titta på fall där data kan bestämmas tillhöra två olika klasser, så vad gör
man då med data där fler klasser finns? En teknik för detta är Sequential Minimal
Optimization, SMO. Grundprincipen för SMO är att dela in datamängden i subgrupper där
endast två klasser finns som sedan används för att träna upp den övergripande målfunktionen.
Optimiseringsalgoritmen använder sig av Lagrangemultiplikatorer, α, som hittar lokala maxoch min-värden för en funktion f(x) längs en kurva C samt heurestiker för att optimera
körningen av programmet. Denna algoritm körs tills Karush-Kuhn-Tucker-villkoret ,KKT, är
uppfyllt för alla α. Detta villkor kan i det här fallet sammanfattas till:
αi = 0 ⇒ yi f(x) >= 1
0 < αi < C ⇒ yi f(x) = 1
αi = C ⇒ yi f(x) <= 1
Vilket kan förklaras på följande sätt, x är vår vanliga datapunkt:
α är 0 om x har korrekt klass och ligger utanför marginalen.
α är C om x har tilldelats fel klass eller ligger i marginalen mellan hyperplanen
α är mellan 0 och C innebär att x ligger precis på marginalen och således är en support vector
Implementation av SMO i WEKA
WEKA är en mjukvara skriven i Java utvecklad för maskininlärning genom statistiskt lärande
system. I detta open source-program finns Support Vector Machines i form av SMO
implementerat, men även andra strategier som sökträd. För att enkelt kunna visa på hur en
implementation av en SVM kan se ut har jag använt mig av en klassisk databas över
växtsläktet irisar där databasen ser ut på följande sätt. En datapunkt består av fyra attribut
samt en klass, det finns totalt tre klasser vilket leder till att det är relevant att använda SMO
om än på dess enklaste nivå. Databasen är av formatet ARFF och är en textfil med
formateringen:
5.3,3.7,1.5,0.2,Iris-setosa
6.4,3.2,4.5,1.5,Iris-versicolor
6.3,3.3,6.0,2.5,Iris-virginica
De fyra första talen är i ordning; längden på foderbladen, bredden på foderbladen, längden på
blombladen, bredden på blombladen samt vilken art av iris växten är. I databasen finns 50
observerade exemplar av varje art.
Först tränar man målfunktionen med en viss andel av datamängden, i det här fallet 66 %, i en
korsvalidering av 10 gånger. Man använder sedan resterande data för att testa målfunktionen.
Den ska alltså baserat på de fyra attributen hos en datapunkt kunna tilldela den rätt klass.
Resultat
Hela resultatet finns som appendix i slutet av dokumentet. Det första som är värt att lägga
märke till är att den i början väljer en kärna, i detta fallet K(x,y) = (x,y). Kärna väljs efter
analys av datas natur. Vidare ser man hur den jämför två klasser i taget som tidigare beskrevs.
I fråga om presterande ser vi i slutet att den satte korrekt klass på 96 % av testdata. Jämför
man detta resultat med beslutsträdet J48(en Javaimplementation av C4.5) så hamnar båda på
nivån 96% korrekt och nästintill samma modelleringstid. Beslutsträd kommer inte att
förklaras utan detta är endast som en jämförelse med en annan teknik med samma
användningsområde. Tar man däremot en större databas, i det här fallet en databas över olika
varianter av sojabönor med 683 instanser med 35 attribut vardera fördelade mellan 19 klasser,
så blir skillnaden mellan de båda teknikerna större. Samma fördelning av tränings- och testdata användes som tidigare. I detta fall sätter SVM korrekt klass i 94% av fallen och modellen
tar 0,92 sekunder att bygga. Samma siffror för J48 är 91.5 % och 0.02 sekunder. Anledningen
till att en SVM med SMO-algoritmen ökar i modelleringstid i det här fallet är att till skillnad
från ett beslutsträd så får man en exponent som ökar med antalet klasser i datan då alla dessa
testas parvis. Den ökade nivån av korrekt klassificering följer med en bekostnad av en
exponentiell tillväxt i modelleringen, som till viss del begränsas av heurestiken i SMOalgoritmen.
Sammanfattning
SVM har en stor potential av användningsområden och används redan frekvent i t ex.
mönsterigenkänning så som tolkning av handskriven text till ASCII eller i helt andra områden
som kemi där förslag på nya läkemedel tas fram med hjälp av SVM. Det finns egentligen
ingen begränsning i användningsområden då det är ett verktyg som går att applicera på en
godtycklig databas. Styrkan i en SVM ligger i dess förmåga att finna komplexa samband i
data med låg felmarginal och med relativt låg minnesanvändning genom kernel-tricket.
Referenser
Steinwart, Ingo, Support vector machines, Springer, 2008
Schölkopf, Bernhard and Smola, Alexander J. Learning With Kernels, The MIT Press, 2002
Russel, Stuart and Peter, Norvig, Artificial Intelligence, A Modern Approach 3rd edition,
Pearson Education,2010
Figur 1 Wikipedia
http://en.wikipedia.org/wiki/File:Svm_max_sep_hyperplane_with_margin.png
Figur 2 hämtad från Learning With Kernels
Appendix
Resultat från träning av SVM i WEKA
=== Run information ===
Scheme:weka.classifiers.functions.SMO -C 1.0 -L 0.0010 -P 1.0E-12 -N 0 -V -1 -W 1 -K
"weka.classifiers.functions.supportVector.PolyKernel -C 250007 -E 1.0"
Relation: iris
Instances: 150
Attributes: 5
sepallength
sepalwidth
petallength
petalwidth
class
Test mode:10-fold cross-validation
=== Classifier model (full training set) ===
SMO
Kernel used:
Linear Kernel: K(x,y) = <x,y>
Classifier for classes: Iris-setosa, Iris-versicolor
BinarySMO
Machine linear: showing attribute weights, not support vectors.
+
+
+
-
0.6829 * (normalized) sepallength
-1.523 * (normalized) sepalwidth
2.2034 * (normalized) petallength
1.9272 * (normalized) petalwidth
0.7091
Number of kernel evaluations: 352 (70.32% cached)
Classifier for classes: Iris-setosa, Iris-virginica
BinarySMO
Machine linear: showing attribute weights, not support vectors.
+
+
+
-
0.5886 * (normalized) sepallength
-0.5782 * (normalized) sepalwidth
1.6429 * (normalized) petallength
1.4777 * (normalized) petalwidth
1.1668
Number of kernel evaluations: 284 (68.996% cached)
Classifier for classes: Iris-versicolor, Iris-virginica
BinarySMO
Machine linear: showing attribute weights, not support vectors.
+
+
+
-
0.3176 * (normalized) sepallength
-0.863 * (normalized) sepalwidth
3.0543 * (normalized) petallength
4.0815 * (normalized) petalwidth
4.5924
Number of kernel evaluations: 453 (61.381% cached)
Time taken to build model: 0.01 seconds
=== Stratified cross-validation ===
=== Summary ===
Correctly Classified Instances
144
Incorrectly Classified Instances
6
Kappa statistic
0.94
Mean absolute error
0.2311
Root mean squared error
0.288
Relative absolute error
52 %
Root relative squared error
61.101 %
Total Number of Instances
150
96 %
4 %
=== Detailed Accuracy By Class ===
TP Rate FP Rate Precision Recall F-Measure ROC Area Class
1
0
1
1
1
1
Iris-setosa
0.98 0.05
0.907 0.98 0.942 0.965 Iris-versicolor
0.9
0.01
0.978 0.9
0.938 0.97 Iris-virginica
Weighted Avg. 0.96 0.02
0.962 0.96
0.96
0.978
=== Confusion Matrix ===
a b c <-- classified as
50 0 0 | a = Iris-setosa
0 49 1 | b = Iris-versicolor
0 5 45 | c = Iris-virginica