Implementering av SVM och Kernel SVM med Pythons Scikit-Learn

Implementering av SVM och Kernel SVM med Pythons Scikit-Learn

Beskrivning

Den här guiden är den första delen av tre guider om Support Vector Machines (SVM). I den här serien kommer vi att arbeta med ett användningsfall för förfalskade sedlar, lära oss om det enkla SVM, sedan om SVM-hyperparametrar och slutligen lära oss ett koncept som kallas kärntrick och utforska andra typer av SVM.

Om du vill läsa alla guider eller se vilka som intresserar dig mest, nedan är tabellen över ämnen som tas upp i varje guide:

1. Implementera SVM och Kernel SVM med Pythons Scikit-Learn

  • Användningsfall: glöm sedlar
  • Bakgrund till SVM
  • Enkel (linjär) SVM-modell
    • Om datamängden
    • Importera datamängden
    • Utforska datasättet
  • Implementering av SVM med Scikit-Learn
    • Dela upp data i tåg/testuppsättningar
    • Träna modellen
    • Förutsäga
    • Utvärdering av modellen
    • Tolka resultat

2. Förstå SVM-hyperparametrar (kommer snart!)

  • Hyperparametern C
  • Gamma-hyperparametern

3. Implementera andra SVM-smaker med Pythons Scikit-Learn (kommer snart!)

  • SVMs allmänna idé (en sammanfattning)
  • Kärna (trick) SVM
  • Implementering av icke-linjär kärna SVM med Scikit-Learn
  • Importerar bibliotek
    • Importera datauppsättningen
    • Dela upp data i funktioner (X) och mål (y)
    • Dela upp data i tåg/testuppsättningar
    • Att träna algoritmen
  • Polynomkärna
    • Förutsäga
    • Utvärdera algoritmen
  • Gaussisk kärna
    • Förutsägelse och utvärdering
  • Sigmoidkärna
    • Förutsägelse och utvärdering
  • Jämförelse av icke-linjära kärnprestanda

Användningsfall: Förfalskade sedlar

Ibland hittar folk ett sätt att förfalska sedlar. Om det finns en person som tittar på dessa anteckningar och verifierar deras giltighet, kan det vara svårt att bli lurad av dem.

Men vad händer när det inte finns en person att titta på varje lapp? Finns det något sätt att automatiskt veta om sedlar är förfalskade eller äkta?

Det finns många sätt att svara på dessa frågor. Ett svar är att fotografera varje mottagen lapp, jämföra dess bild med en förfalskad lapps bild och sedan klassificera den som äkta eller förfalskad. När det kan vara tråkigt eller kritiskt att vänta på anteckningens validering, skulle det också vara intressant att göra den jämförelsen snabbt.

Eftersom bilder används kan de komprimeras, reduceras till gråskala och få sina mätningar extraherade eller kvantifierade. På så sätt skulle jämförelsen vara mellan bildmått, istället för varje bilds pixel.

Hittills har vi hittat ett sätt att bearbeta och jämföra sedlar, men hur kommer de att klassificeras som riktiga eller förfalskade? Vi kan använda maskininlärning för att göra den klassificeringen. Det finns en klassificeringsalgoritm som kallas Stöd Vector Machine, främst känd genom sin förkortade form: svm.

Bakgrund till SVM

SVMs introducerades initialt 1968, av Vladmir Vapnik och Alexey Chervonenkis. På den tiden var deras algoritm begränsad till klassificeringen av data som kunde separeras med bara en rak linje, eller data som var linjärt separerbara. Vi kan se hur den separationen skulle se ut:

Implementering av SVM och Kernel SVM med Pythons Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

I bilden ovan har vi en linje i mitten, till vilken vissa punkter är till vänster och andra är till höger om den linjen. Lägg märke till att båda grupperna av punkter är perfekt separerade, det finns inga punkter mellan eller ens nära linjen. Det verkar finnas en marginal mellan liknande punkter och linjen som delar dem, den marginalen kallas separationsmarginal. Separationsmarginalens funktion är att göra utrymmet mellan de liknande punkterna och linjen som delar dem större. SVM gör det genom att använda några punkter och beräknar dess vinkelräta vektorer för att stödja beslutet för linjens marginal. Det är de stödvektorer som är en del av namnet på algoritmen. Vi kommer att förstå mer om dem senare. Och den räta linjen som vi ser i mitten hittas av metoder som maximera det utrymmet mellan linjen och punkterna, eller som maximerar separationsmarginalen. Dessa metoder kommer från området Optimeringsteori.

I exemplet vi just har sett kan båda grupperna av punkter enkelt separeras, eftersom varje enskild punkt är nära varandra till sina liknande punkter, och de två grupperna är långt ifrån varandra.

Men vad händer om det inte finns ett sätt att separera data med en rak linje? Om det finns stökiga punkter som inte är på plats, eller om en kurva behövs?

För att lösa det problemet förfinades SVM senare på 1990-talet för att även kunna klassificera data som hade punkter som var långt ifrån dess centrala tendens, såsom extremvärden, eller mer komplexa problem som hade mer än två dimensioner och inte var linjärt separerbara .

Vad som är märkligt är att SVM:er först på senare år har blivit allmänt antagna, främst på grund av deras förmåga att ibland uppnå mer än 90 % av korrekta svar eller noggrannhet, för svåra problem.

SVM:er implementeras på ett unikt sätt jämfört med andra maskininlärningsalgoritmer, när de väl är baserade på statistiska förklaringar av vad inlärning är, eller på Statistisk inlärningsteori.

I den här artikeln kommer vi att se vad Support Vector Machines algoritmer är, den korta teorin bakom en stödvektormaskin och deras implementering i Pythons Scikit-Learn-bibliotek. Vi kommer då att gå mot ett annat SVM-koncept, känt som Kärna SVM, eller Kärntrick, och kommer också att implementera det med hjälp av Scikit-Learn.

Enkel (linjär) SVM-modell

Om datamängden

Efter exemplet som ges i inledningen kommer vi att använda en datauppsättning som har mått på verkliga och förfalskade sedlarbilder.

När vi tittar på två anteckningar, skannar våra ögon vanligtvis dem från vänster till höger och kontrollerar var det kan finnas likheter eller olikheter. Vi letar efter en svart prick som kommer före en grön prick, eller ett glänsande märke som är ovanför en illustration. Det betyder att det finns en ordning i vilken vi tittar på anteckningarna. Om vi ​​visste att det fanns gröna och svarta prickar, men inte om den gröna pricken kom före den svarta, eller om den svarta kom före den gröna, skulle det vara svårare att skilja mellan toner.

Det finns en liknande metod som den vi just har beskrivit som kan tillämpas på sedelbilderna. Generellt sett består denna metod i att översätta bildens pixlar till en signal och sedan ta hänsyn till den ordning i vilken varje olika signal sker i bilden genom att omvandla den till små vågor, eller vågor. Efter att ha erhållit wavelets, finns det ett sätt att veta i vilken ordning en signal inträffar före en annan, eller tid, men inte exakt vilken signal. För att veta det måste bildens frekvenser erhållas. De erhålls genom en metod som gör nedbrytningen av varje signal, kallad Fouriermetoden.

När tidsdimensionen har erhållits genom vågorna och frekvensdimensionen genom Fouriermetoden, görs en överlagring av tid och frekvens för att se när båda har en matchning, detta är veck analys. Konvolutionen får en passform som matchar vågorna med bildens frekvenser och tar reda på vilka frekvenser som är mer framträdande.

Denna metod som går ut på att hitta vågorna, deras frekvenser och sedan anpassa dem båda kallas Wavelet transform. Wavelet-transformen har koefficienter, och dessa koefficienter användes för att få de mätningar vi har i datamängden.

Importera datamängden

Sedeluppsättningen som vi kommer att använda i det här avsnittet är densamma som användes i klassificeringsdelen av handledning för beslutsträd.

Notera: Du kan ladda ner datasetet här..

Låt oss importera data till en panda dataframe struktur, och ta en titt på dess första fem rader med head() metod.

Observera att data sparas i en txt (text) filformat, separerat med kommatecken, och det är utan rubrik. Vi kan rekonstruera den som en tabell genom att läsa den som en csv, med angivande av separator som ett kommatecken och lägga till kolumnnamnen med names argument.

Låt oss följa de tre stegen samtidigt och titta sedan på de första fem raderna med data:

import pandas as pd data_link = "https://archive.ics.uci.edu/ml/machine-learning-databases/00267/data_banknote_authentication.txt"
col_names = ["variance", "skewness", "curtosis", "entropy", "class"] bankdata = pd.read_csv(data_link, names=col_names, sep=",", header=None)
bankdata.head()

Detta resulterar i:

	variance skewness curtosis entropy class
0 3.62160 8.6661 -2.8073 -0.44699 0
1 4.54590 8.1674 -2.4586 -1.46210 0
2 3.86600 -2.6383 1.9242 0.10645 0
3 3.45660 9.5228 -4.0112 -3.59440 0
4 0.32924 -4.4552 4.5718 -0.98880 0

Notera: Du kan också spara data lokalt och ersätta dem data_link för data_path, och skicka in sökvägen till din lokala fil.

Vi kan se att det finns fem kolumner i vår datauppsättning, nämligen variance, skewness, curtosis, entropyoch class. I de fem raderna är de fyra första kolumnerna fyllda med siffror som 3.62160, 8.6661, -2.8073 eller kontinuerlig värden, och det sista class kolumnen har sina första fem rader fyllda med nollor eller a diskret värde.

Eftersom vårt mål är att förutsäga om en bankvaluta är äkta eller inte, kan vi göra det baserat på sedelns fyra attribut:

  • variance av Wavelet Transformed bild. Generellt sett är variansen ett kontinuerligt värde som mäter hur mycket datapunkterna är nära eller långt från datans medelvärde. Om poängen ligger närmare datas medelvärde är fördelningen närmare en normalfördelning, vilket vanligtvis innebär att dess värden är mer välfördelade och något lättare att förutsäga. I det aktuella bildsammanhanget är detta variansen av koefficienterna som resulterar från wavelet-transformen. Ju mindre varians, desto närmare var koefficienterna att översätta den faktiska bilden.

  • skewness av Wavelet Transformed bild. Skevheten är ett kontinuerligt värde som indikerar asymmetrin i en fördelning. Om det finns fler värden till vänster om medelvärdet är fördelningen negativt skev, om det finns fler värden till höger om medelvärdet är fördelningen positivt sned, och om medelvärdet, läget och medianen är samma, är fördelningen symmetrisk. Ju mer symmetrisk en fördelning är, desto närmare är den en normalfördelning, och dess värden är också mer välfördelade. I föreliggande sammanhang är detta skevheten hos koefficienterna som resulterar från wavelet-transformen. Ju mer symmetriska, desto närmare koefficienterna vivariance, skewness, curtosis, entropyre till att översätta den faktiska bilden.

Implementering av SVM och Kernel SVM med Pythons Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

  • curtosis (eller kurtosis) av Wavelet Transformed image. Kurtosen är ett kontinuerligt värde som, liksom skevhet, också beskriver formen på en fördelning. Beroende på kurtos-koefficienten (k) kan en fördelning – jämfört med normalfördelningen vara mer eller mindre platt – eller ha mer eller mindre data i sina extremiteter eller svansar. När fördelningen är mer spridd och plattare kallas den platykurtic; när det är mindre utspritt och mer koncentrerat i mitten, mesokurtic; och när fördelningen nästan helt är koncentrerad i mitten kallas den leptokurtic. Detta är samma fall som tidigare fall med varians och skevhet, ju mer mesokurtisk fördelningen är, desto närmare var koefficienterna att översätta den faktiska bilden.

Implementering av SVM och Kernel SVM med Pythons Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

  • entropy av bilden. Entropin är också ett kontinuerligt värde, det mäter vanligtvis slumpen eller oordningen i ett system. I samband med en bild mäter entropi skillnaden mellan en pixel och dess närliggande pixlar. För vårt sammanhang, ju mer entropi koefficienterna har, desto mer förlust blev det när bilden transformerades – och ju mindre entropin desto mindre informationsförlusten.

Implementering av SVM och Kernel SVM med Pythons Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Den femte variabeln var class variabel, som förmodligen har 0 och 1 värden, som säger om sedeln var verklig eller förfalskad.

Vi kan kontrollera om den femte kolumnen innehåller nollor och ettor med Pandas' unique() metod:

bankdata['class'].unique()

Ovanstående metod returnerar:

array([0, 1]) 

Ovanstående metod returnerar en array med 0 och 1 värden. Det betyder att de enda värdena som finns i våra klassrader är nollor och ettor. Den är redo att användas som mål i vårt övervakade lärande.

  • class av bilden. Detta är ett heltalsvärde, det är 0 när bilden är förfalskad och 1 när bilden är verklig.

Eftersom vi har en kolumn med anteckningar om verkliga och glömma bilder, betyder det att vår typ av lärande är övervakas.

Råd: för att veta mer om resonemanget bakom Wavelet Transform på sedelbilderna och användningen av SVM, läs författarnas publicerade papper.

Vi kan också se hur många poster, eller bilder vi har, genom att titta på antalet rader i datan via shape fast egendom:

bankdata.shape

Denna utgångar:

(1372, 5)

Ovanstående rad betyder att det finns 1,372 5 rader med transformerade sedlarbilder och XNUMX kolumner. Det är denna data vi kommer att analysera.

Vi har importerat vår datauppsättning och gjort några kontroller. Nu kan vi utforska vår data för att förstå den bättre.

Utforska datasättet

Vi har precis sett att det bara finns nollor och ettor i klasskolumnen, men vi kan också veta i vilken proportion de är – med andra ord – om det finns fler nollor än ettor, fler ettor än nollor, eller om antalet nollor är samma som antalet ettor, vilket betyder att de är det balanserad.

För att veta proportionen kan vi räkna vart och ett av noll- och ett-värdena i datan med value_counts() metod:

bankdata['class'].value_counts()

Denna utgångar:

0 762
1 610
Name: class, dtype: int64

I resultatet ovan kan vi se att det finns 762 nollor och 610 ettor, eller 152 fler nollor än ettor. Det betyder att vi har lite mer smidda än verkliga bilder, och om den avvikelsen var större, till exempel 5500 nollor och 610 ettor, kan det påverka våra resultat negativt. När vi väl försöker använda dessa exempel i vår modell – ju fler exempel det finns betyder vanligtvis att ju mer information modellen måste välja mellan förfalskade eller riktiga sedlar – om det finns få verkliga sedlar är modellen benägen att vara misstag när man försöker känna igen dem.

Vi vet redan att det finns 152 fler förfalskade sedlar, men kan vi vara säkra på att det är tillräckligt med exempel för modellen att lära sig? Att veta hur många exempel som behövs för att lära sig är en mycket svår fråga att besvara, istället kan vi försöka förstå, procentuellt sett, hur stor skillnaden mellan klasserna är.

Det första steget är att använda pandor value_counts() metod igen, men låt oss nu se procentsatsen genom att inkludera argumentet normalize=True:

bankdata['class'].value_counts(normalize=True)

Smakämnen normalize=True beräknar procentandelen av data för varje klass. Hittills är procentandelen förfalskade (0) och verkliga data (1):

0 0.555394
1 0.444606
Name: class, dtype: float64

Detta betyder att ungefär (~) 56 % av vår datauppsättning är förfalskad och 44 % av den är verklig. Detta ger oss ett förhållande på 56%-44%, vilket är samma som en skillnad på 12%. Detta anses statistiskt sett vara en liten skillnad, eftersom det bara är lite över 10%, så uppgifterna anses vara balanserade. Om det istället för en 56:44-proportion fanns en 80:20- eller 70:30-proportion, skulle våra data anses vara obalanserade och vi skulle behöva göra någon obalansbehandling, men lyckligtvis är så inte fallet.

Vi kan också se denna skillnad visuellt genom att ta en titt på klassens eller målets fördelning med ett Pandas genomsyrat histogram, genom att använda:

bankdata['class'].plot.hist();

Detta plottar ett histogram med hjälp av dataramstrukturen direkt, i kombination med matplotlib bibliotek som finns bakom kulisserna.

Implementering av SVM och Kernel SVM med Pythons Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Genom att titta på histogrammet kan vi vara säkra på att våra målvärden är antingen 0 eller 1 och att data är balanserade.

Detta var en analys av kolumnen som vi försökte förutsäga, men vad sägs om att analysera de andra kolumnerna i vår data?

Vi kan ta en titt på de statistiska mätningarna med describe() datarammetod. Vi kan också använda .T of transpose – för att invertera kolumner och rader, vilket gör det mer direkt att jämföra mellan värden:

Kolla in vår praktiska, praktiska guide för att lära dig Git, med bästa praxis, branschaccepterade standarder och medföljande fuskblad. Sluta googla Git-kommandon och faktiskt lära Det!

bankdata.describe().T

Detta resulterar i:

 count mean std min 25% 50% 75% max
variance 1372.0 0.433735 2.842763 -7.0421 -1.773000 0.49618 2.821475 6.8248
skewness 1372.0 1.922353 5.869047 -13.7731 -1.708200 2.31965 6.814625 12.9516
curtosis 1372.0 1.397627 4.310030 -5.2861 -1.574975 0.61663 3.179250 17.9274
entropy 1372.0 -1.191657 2.101013 -8.5482 -2.413450 -0.58665 0.394810 2.4495
class 1372.0 0.444606 0.497103 0.0000 0.000000 0.00000 1.000000 1.0000

Lägg märke till att skevhet och curtoskolumner har medelvärden som ligger långt ifrån standardavvikelsevärdena, detta indikerar att de värden som ligger längre från datas centrala tendens, eller har en större variabilitet.

Vi kan också ta en titt på varje funktions distribution visuellt genom att plotta varje funktions histogram inuti en for-loop. Förutom att titta på fördelningen skulle det vara intressant att titta på hur poängen i varje klass är åtskilda för varje funktion. För att göra det kan vi rita ett spridningsdiagram som gör en kombination av funktioner mellan dem och tilldela olika färger till varje punkt med avseende på dess klass.

Låt oss börja med varje funktions fördelning och plotta histogrammet för varje datakolumn förutom class kolumn. De class kolumnen kommer inte att beaktas av dess position i arrayen för bankdatakolumner. Alla kolumner kommer att väljas utom den sista med columns[:-1]:

import matplotlib.pyplot as plt for col in bankdata.columns[:-1]: plt.title(col) bankdata[col].plot.hist() plt.show();

Efter att ha kört ovanstående kod kan vi se att båda skewness och entropy datafördelningar är negativt skeva och curtosis är positivt sned. Alla distributioner är symmetriska och variance är den enda fördelningen som är nära normal.

Vi kan nu gå vidare till den andra delen och plotta spridningsdiagrammet för varje variabel. För att göra detta kan vi också välja alla kolumner utom klassen, med columns[:-1], använd Seaborn's scatterplot() och två för loopar för att erhålla variationerna i parning för var och en av funktionerna. Vi kan också utesluta sammankopplingen av en funktion med sig själv, genom att testa om den första egenskapen är lika med den andra med en if statement.

import seaborn as sns for feature_1 in bankdata.columns[:-1]: for feature_2 in bankdata.columns[:-1]: if feature_1 != feature_2: print(feature_1, feature_2) sns.scatterplot(x=feature_1, y=feature_2, data=bankdata, hue='class') plt.show();

Lägg märke till att alla grafer har både verkliga och förfalskade datapunkter som inte är tydligt separerade från varandra, detta betyder att det finns någon form av överlagring av klasser. Eftersom en SVM-modell använder en linje för att separera mellan klasser, kan någon av dessa grupper i graferna separeras med bara en linje? Det verkar osannolikt. Så här ser de flesta riktiga data ut. Det närmaste vi kan komma en separation är i kombinationen av skewness och variance, eller entropy och variance tomter. Detta beror förmodligen på variance data som har en distributionsform som är närmare det normala.

Men att titta på alla dessa grafer i följd kan vara lite svårt. Vi har alternativet att titta på alla distributions- och spridningsdiagram tillsammans genom att använda Seaborns pairplot().

Båda tidigare slingor som vi hade gjort kan ersättas med bara denna rad:

sns.pairplot(bankdata, hue='class');

När man tittar på pardiagrammet verkar det som att curtosis och variance skulle vara den enklaste kombinationen av funktioner, så de olika klasserna kan separeras med en linje, eller linjärt separerbara.

Om de flesta data är långt ifrån linjärt separerbara kan vi försöka förbearbeta den, genom att minska dess dimensioner, och även normalisera dess värden för att försöka göra fördelningen närmare en normal.

I det här fallet, låt oss använda data som den är, utan ytterligare förbearbetning, och senare kan vi gå tillbaka ett steg, lägga till dataförbehandlingen och jämföra resultaten.

Råd: När man arbetar med data går information oftast förlorad när man transformerar den, eftersom vi gör uppskattningar istället för att samla in mer data. Att arbeta med den initiala datan först som den är, om möjligt, erbjuder en baslinje innan du provar andra förbearbetningstekniker. När du följer denna väg kan det initiala resultatet med rådata jämföras med ett annat resultat som använder förbearbetningstekniker på data.

Notera: Vanligtvis inom statistik, när man bygger modeller, är det vanligt att följa en procedur beroende på typen av data (diskret, kontinuerlig, kategorisk, numerisk), dess fördelning och modellens antaganden. Medan i datavetenskap (CS) finns det mer utrymme för försök, fel och nya iterationer. I CS är det vanligt att man har en baslinje att jämföra mot. I Scikit-learn finns det en implementering av dummy-modeller (eller dummy-estimatorer), vissa är inte bättre än att kasta ett mynt och bara svara ja (eller 1) 50 % av tiden. Det är intressant att använda dummymodeller som baslinje för den faktiska modellen när man jämför resultat. Det förväntas att de faktiska modellresultaten är bättre än en slumpmässig gissning, annars skulle det inte vara nödvändigt att använda en maskininlärningsmodell.

Implementering av SVM med Scikit-Learn

Innan vi går mer in på teorin om hur SVM fungerar kan vi bygga vår första baslinjemodell med data och Scikit-Learns Stöd Vector Classifier or SVC klass.

Vår modell kommer att ta emot wavelet-koefficienterna och försöka klassificera dem baserat på klassen. Det första steget i denna process är att separera koefficienterna eller pass från klassen eller mål. Efter det steget är det andra steget att ytterligare dela upp data i en uppsättning som ska användas för modellens inlärning eller tågset och ytterligare en som kommer att användas vid modellens utvärdering eller testuppsättning.

Notera: Nomenklaturen för test och utvärdering kan vara lite förvirrande, eftersom du också kan dela upp din data mellan tåg, utvärdering och testset. På så sätt, istället för att ha två uppsättningar, skulle du ha en mellanliggande uppsättning bara att använda och se om din modells prestanda förbättras. Detta innebär att modellen skulle tränas med tåguppsättningen, förbättras med utvärderingsuppsättningen och erhålla ett slutligt mått med testsetet.

Vissa människor säger att utvärderingen är den mellanliggande uppsättningen, andra kommer att säga att testuppsättningen är den mellanliggande uppsättningen och att utvärderingsuppsättningen är den slutliga uppsättningen. Detta är ytterligare ett sätt att försöka garantera att modellen inte ser samma exempel på något sätt, eller att någon form av dataläcka inte händer, och att det finns en modellgeneralisering genom förbättringen av de senaste mätvärdena. Om du vill följa det tillvägagångssättet kan du dela upp data ytterligare en gång till enligt beskrivningen i detta Scikit-Learns train_test_split() – Utbildnings-, testnings- och valideringsuppsättningar guide.

Dela upp data i tåg/testuppsättningar

I föregående session förstod och utforskade vi data. Nu kan vi dela upp våra data i två arrayer – en för de fyra funktionerna och den andra för den femte eller målfunktionen. Eftersom vi vill förutsäga klassen beroende på wavelets koefficienter, vår y kommer att vara den class kolumn och vår X kommer variance, skewness, curtosisoch entropy kolumner.

För att separera målet och funktionerna kan vi bara tillskriva class kolumn till y, senare släpper den från dataramen för att tillskriva de återstående kolumnerna X med .drop() metod:

y = bankdata['class']
X = bankdata.drop('class', axis=1) 

När informationen är uppdelad i attribut och etiketter kan vi dela upp den ytterligare i tåg- och testuppsättningar. Detta kan göras för hand, men model_selection biblioteket i Scikit-Learn innehåller train_test_split() metod som gör att vi slumpmässigt kan dela upp data i tåg- och testset.

För att använda det kan vi importera biblioteket, ring train_test_split() metod, gå in X och y data och definiera en test_size att passera som ett argument. I det här fallet kommer vi att definiera det som 0.20– det betyder att 20 % av uppgifterna kommer att användas för testning och de andra 80 % för träning.

Denna metod tar slumpmässigt prover som respekterar den procentandel vi har definierat, men respekterar Xy-paren, så att provtagningen inte skulle blanda ihop förhållandet totalt.

Eftersom urvalsprocessen till sin natur är slumpmässig kommer vi alltid att ha olika resultat när vi kör metoden. För att kunna få samma resultat, eller reproducerbara resultat, kan vi definiera en konstant som kallas SEED med värdet 42.

Du kan köra följande skript för att göra det:

from sklearn.model_selection import train_test_split SEED = 42 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.20, random_state = SEED)

Observera att train_test_split() metoden returnerar redan X_train, X_test, y_train, y_test sätter i denna ordning. Vi kan skriva ut antalet prover separerade för tåg och test genom att få det första (0) elementet i shape egendom returnerad tupel:

xtrain_samples = X_train.shape[0]
xtest_samples = X_test.shape[0] print(f'There are {xtrain_samples} samples for training and {xtest_samples} samples for testing.')

Detta visar att det finns 1097 prover för träning och 275 för testning.

Träna modellen

Vi har delat in data i tåg- och testset. Nu är det dags att skapa och träna en SVM-modell på tågdata. För att göra det kan vi importera Scikit-Learn's svm biblioteket tillsammans med Stöd Vector Classifier klass, eller SVC klass.

Efter att ha importerat klassen kan vi skapa en instans av den – eftersom vi skapar en enkel SVM-modell försöker vi separera våra data linjärt, så att vi kan dra en linje för att dela upp vår data – vilket är samma sak som att använda en linjär funktion – genom att definiera kernel='linear' som ett argument för klassificeraren:

from sklearn.svm import SVC
svc = SVC(kernel='linear')

På så sätt kommer klassificeraren att försöka hitta en linjär funktion som separerar våra data. Efter att ha skapat modellen, låt oss träna den, eller passa det, med tågdata, med hjälp av fit() metod och ger X_train funktioner och y_train mål som argument.

Vi kan köra följande kod för att träna modellen:

svc.fit(X_train, y_train)

Precis så är modellen tränad. Hittills har vi förstått data, delat upp dem, skapat en enkel SVM-modell och anpassat modellen till tågdata.

Nästa steg är att förstå hur väl den passade lyckades beskriva vår data. Med andra ord, för att svara på om en linjär SVM var ett adekvat val.

Förutsäga

Ett sätt att svara på om modellen lyckats beskriva datan är att beräkna och titta på någon klassificering metrik.

Med tanke på att lärandet är övervakat kan vi göra förutsägelser med X_test och jämför dessa förutsägelseresultat – som vi kan kalla y_pred – med den faktiska y_test, eller marken sanning.

För att förutsäga en del av data, modellens predict() metod kan användas. Denna metod tar emot testfunktionerna, X_test, som ett argument och returnerar en förutsägelse, antingen 0 eller 1, för var och en av X_tests rader.

Efter att ha förutspått X_test data lagras resultaten i en y_pred variabel. Så var och en av klasserna som förutspås med den enkla linjära SVM-modellen är nu i y_pred variabel.

Detta är prediktionskoden:

y_pred = svc.predict(X_test)

Med tanke på att vi har förutsägelserna kan vi nu jämföra dem med de faktiska resultaten.

Utvärdering av modellen

Det finns flera sätt att jämföra förutsägelser med faktiska resultat, och de mäter olika aspekter av en klassificering. Några mest använda klassificeringsmått är:

  1. Förvirringsmatris: när vi behöver veta hur mycket prover vi fick rätt eller fel för varje klass. De värden som var korrekta och korrekt förutsagda kallas sanna positiva, de som förutspåddes som positiva men som inte var positiva kallas falska positiva. Samma nomenklatur för verkliga negativa och falska negativ används för negativa värden;

  2. Precision: när vårt mål är att förstå vilka korrekta prediktionsvärden som ansågs vara korrekta av vår klassificerare. Precision kommer att dela de verkliga positiva värdena med de prover som förutspåddes som positiva;

$$
precision = frac{text{true positives}}{text{true positives} + text{false positives}}
$$

  1. Recall: vanligen beräknad tillsammans med precision för att förstå hur många av de sanna positiva som identifierades av vår klassificerare. Återkallelsen beräknas genom att dividera de sanna positiva med allt som borde ha förutspåtts som positivt.

$$
recall = frac{text{true positives}}{text{true positives} + text{false negatives}}
$$

  1. F1-poäng: är den balanserade eller harmoniskt medelvärde av precision och återkallelse. Det lägsta värdet är 0 och det högsta är 1. När f1-score är lika med 1 betyder det att alla klasser förutspåddes korrekt – detta är ett mycket svårt resultat att få med riktiga data (undantag finns nästan alltid).

$$
text{f1-score} = 2* frac{text{precision} * text{recall}}{text{precision} + text{recall}}
$$

Vi har redan varit bekanta med förvirringsmatris, precision, återkallelse och F1-poängmått. För att beräkna dem kan vi importera Scikit-Learn's metrics bibliotek. Detta bibliotek innehåller classification_report och confusion_matrix metoder, returnerar klassificeringsrapportmetoden precision, återkallelse och f1-poäng. Både classification_report och confusion_matrix kan lätt användas för att ta reda på värdena för alla dessa viktiga mätvärden.

För att beräkna måtten importerar vi metoderna, anropar dem och skickar som argument de förutsagda klassificeringarna, y_test, och klassificeringsetiketterna, eller y_true.

För en bättre visualisering av förvirringsmatrisen kan vi plotta den i en Seaborns heatmap tillsammans med kvantitetsanteckningar, och för klassificeringsrapporten är det bäst att skriva ut resultatet så att dess resultat formateras. Detta är följande kod:

from sklearn.metrics import classification_report, confusion_matrix cm = confusion_matrix(y_test,y_pred)
sns.heatmap(cm, annot=True, fmt='d').set_title('Confusion matrix of linear SVM') print(classification_report(y_test,y_pred))

Detta visar:

 precision recall f1-score support 0 0.99 0.99 0.99 148 1 0.98 0.98 0.98 127 accuracy 0.99 275 macro avg 0.99 0.99 0.99 275
weighted avg 0.99 0.99 0.99 275

Implementering av SVM och Kernel SVM med Pythons Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

I klassificeringsrapporten vet vi att det finns en precision på 0.99, återkallelse på 0.99 och ett f1-poäng på 0.99 för de förfalskade sedlarna, eller klass 0. Dessa mätningar erhölls med 148 prover som visas i stödkolumnen. Samtidigt, för klass 1, eller riktiga anteckningar, var resultatet en enhet under, 0.98 i precision, 0.98 för återkallelse och samma f1-poäng. Den här gången användes 127 bildmätningar för att erhålla dessa resultat.

Om vi ​​tittar på förvirringsmatrisen kan vi också se att från 148 klass 0-prover var 146 korrekt klassificerade, och det fanns 2 falskt positiva, medan det för 127 klass 1-prover fanns 2 falskt negativa och 125 sanna positiva.

Vi kan läsa klassificeringsrapporten och förvirringsmatrisen, men vad betyder de?

Tolka resultat

För att ta reda på innebörden, låt oss titta på alla mätvärden kombinerade.

Nästan alla prover för klass 1 var korrekt klassificerade, det fanns 2 misstag för vår modell vid identifiering av faktiska sedlar. Detta är samma sak som 0.98, eller 98 %, minns. Något liknande kan sägas om klass 0, endast 2 prover klassificerades felaktigt, medan 148 är sanna negativa, vilket ger en precision på 99%.

Förutom dessa resultat markerar alla andra 0.99, vilket är nästan 1, ett mycket högt mått. För det mesta, när ett så högt mått inträffar med verkliga data, kan detta indikera en modell som är överjusterad till data, eller övermonterad.

När det finns en överanpassning kan modellen fungera bra när den förutsäger data som redan är kända, men den förlorar förmågan att generalisera till ny data, vilket är viktigt i verkliga scenarier.

Ett snabbt test för att ta reda på om en överansträngning sker är också med tågdata. Om modellen i viss mån har memorerat tågdata, kommer måtten att vara mycket nära 1 eller 100 %. Kom ihåg att tågdata är större än testdata – av denna anledning – försök att titta på det proportionellt, fler prover, fler chanser att göra misstag, såvida det inte har skett någon överanpassning.

För att förutsäga med tågdata kan vi upprepa vad vi har gjort för testdata, men nu med X_train:

y_pred_train = svc.predict(X_train) cm_train = confusion_matrix(y_train,y_pred_train)
sns.heatmap(cm_train, annot=True, fmt='d').set_title('Confusion matrix of linear SVM with train data') print(classification_report(y_train,y_pred_train))

Denna utgångar:

 precision recall f1-score support 0 0.99 0.99 0.99 614 1 0.98 0.99 0.99 483 accuracy 0.99 1097 macro avg 0.99 0.99 0.99 1097
weighted avg 0.99 0.99 0.99 1097

Implementering av SVM och Kernel SVM med Pythons Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Det är lätt att se att det tycks finnas en överanvändning, när tågstatistiken är 99 % när man har 4 gånger mer data. Vad kan man göra i detta scenario?

För att återställa överanpassningen kan vi lägga till fler tågobservationer, använda en träningsmetod med olika delar av datasetet, som t.ex. korsvalidering, och även ändra standardparametrarna som redan finns före träning, när du skapar vår modell, eller hyperparametrar. För det mesta ställer Scikit-learn in vissa parametrar som standard, och detta kan ske tyst om det inte finns mycket tid avsatt för att läsa dokumentationen.

Du kan kolla den andra delen av den här guiden (kommer snart!) för att se hur man implementerar korsvalidering och utför en hyperparameterjustering.

Slutsats

I den här artikeln studerade vi den enkla linjära kärnan SVM. Vi fick intuitionen bakom SVM-algoritmen, använde en riktig datauppsättning, utforskade data och såg hur denna data kan användas tillsammans med SVM genom att implementera den med Pythons Scikit-Learn-bibliotek.

För att fortsätta öva kan du prova andra verkliga datauppsättningar tillgängliga på platser som Kaggle, UCI, Big Query offentliga datauppsättningar, universitet och myndigheters webbplatser.

Jag skulle också föreslå att du utforskar den faktiska matematiken bakom SVM-modellen. Även om du inte nödvändigtvis kommer att behöva det för att använda SVM-algoritmen, är det fortfarande väldigt praktiskt att veta vad som faktiskt pågår bakom kulisserna medan din algoritm hittar beslutsgränser.

Tidsstämpel:

Mer från Stackabuse