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