Machine learning met Spark MLlib

1. Overzicht

In deze zelfstudie zullen we begrijpen hoe u Apache Spark MLlib kunt gebruiken om machine learning-producten te ontwikkelen. We zullen een eenvoudig machine learning-product ontwikkelen met Spark MLlib om de kernconcepten te demonstreren.

2. Een korte introductie tot machine learning

Machine Learning is onderdeel van een bredere paraplu die bekend staat als kunstmatige intelligentie. Machine learning verwijst naar het studie van statistische modellen om specifieke problemen op te lossen met patronen en gevolgtrekkingen. Deze modellen worden voor het specifieke probleem “getraind” door middel van trainingsgegevens uit de probleemruimte.

We zullen zien wat deze definitie precies inhoudt als we ons voorbeeld nemen.

2.1. Categorieën voor machine learning

We kunnen in grote lijnen categoriseer machine learning in supervised en unsupervised categorieën op basis van de aanpak. Er zijn ook andere categorieën, maar we houden ons aan deze twee:

  • Leren onder toezicht werkt met een set gegevens die zowel de invoer als de gewenste uitvoer bevat - bijvoorbeeld een dataset met daarin verschillende kenmerken van een woning en de verwachte huuropbrengsten. Begeleid leren is verder onderverdeeld in twee brede subcategorieën die classificatie en regressie worden genoemd:
    • Classificatie-algoritmen zijn gerelateerd aan categorische output, zoals of een woning al dan niet bezet is
    • Regressie-algoritmen zijn gerelateerd aan een continu uitvoerbereik, zoals de waarde van een eigenschap
  • Ongecontroleerd leren, aan de andere kant, werkt met een set gegevens die alleen invoerwaarden hebben. Het werkt door te proberen de inherente structuur in de invoergegevens te identificeren. Bijvoorbeeld door verschillende soorten consumenten te vinden aan de hand van een dataset van hun consumptiegedrag.

2.2. Workflow voor machine learning

Machine learning is echt een interdisciplinair studiegebied. Het vereist kennis van het zakelijke domein, statistiek, waarschijnlijkheid, lineaire algebra en programmeren. Omdat dit duidelijk overweldigend kan worden, je kunt dit het beste op een ordelijke manier aanpakken, wat we doorgaans een machine learning-workflow noemen:

Zoals we kunnen zien, moet elk machine learning-project beginnen met een duidelijk gedefinieerde probleemstelling. Dit moet worden gevolgd door een reeks stappen met betrekking tot gegevens die mogelijk het probleem kunnen oplossen.

Vervolgens selecteren we meestal een model waarbij we kijken naar de aard van het probleem. Dit wordt gevolgd door een reeks modeltraining en -validatie, die bekend staat als modelafstemming. Ten slotte testen we het model op voorheen ongeziene gegevens en zetten we het in voor productie als dit bevredigend is.

3. Wat is Spark MLlib?

Spark MLlib is een module bovenop Spark Core die primitieven voor machine learning biedt als API's. Machine learning heeft doorgaans te maken met een grote hoeveelheid gegevens voor modeltraining.

Het basiscomputerframework van Spark is een enorm voordeel. Bovendien biedt MLlib de meeste populaire machine learning en statistische algoritmen. Dit vereenvoudigt de taak van het werken aan een grootschalig machine learning-project aanzienlijk.

4. Machine learning met MLlib

We hebben nu genoeg context over machine learning en hoe MLlib hierbij kan helpen. Laten we beginnen met ons basisvoorbeeld van het implementeren van een machine learning-project met Spark MLlib.

Als we ons herinneren uit onze discussie over de workflow van machine learning, moeten we beginnen met een probleemstelling en dan verder gaan met gegevens. Gelukkig voor ons kiezen we voor de "hallo wereld" van machine learning, Iris Dataset. Dit is een multivariate gelabelde dataset, bestaande uit lengte en breedte van kelkblaadjes en bloembladen van verschillende soorten irissen.

Dit geeft ons probleemdoel: kunnen we de soort van een iris voorspellen op basis van de lengte en breedte van zijn kelkblad en bloemblad?

4.1. Afhankelijkheden instellen

Eerst moeten we de volgende afhankelijkheid in Maven definiëren om de relevante bibliotheken op te halen:

 org.apache.spark spark-mllib_2.11 2.4.3 verstrekt 

En we moeten de SparkContext initialiseren om met Spark API's te werken:

SparkConf conf = nieuwe SparkConf () .setAppName ("Main") .setMaster ("local [2]"); JavaSparkContext sc = nieuwe JavaSparkContext (conf);

4.2. Het laden van de gegevens

Allereerst moeten we de gegevens downloaden, die beschikbaar zijn als een tekstbestand in CSV-indeling. Dan moeten we deze gegevens in Spark laden:

String dataFile = "data \ iris.data"; JavaRDD data = sc.textFile (dataFile);

Spark MLlib biedt verschillende gegevenstypen, zowel lokaal als gedistribueerd, om de invoergegevens en bijbehorende labels weer te geven. De eenvoudigste gegevenstypen zijn Vector:

JavaRDD inputData = data .map (line -> {String [] parts = line.split (","); double [] v = new double [parts.length - 1]; for (int i = 0; i <parts .length - 1; i ++) {v [i] = Double.parseDouble (parts [i]);} return Vectors.dense (v);});

Merk op dat we hier alleen de invoerfuncties hebben opgenomen, meestal om statistische analyse uit te voeren.

Een trainingsvoorbeeld bestaat doorgaans uit meerdere invoerfuncties en een label, vertegenwoordigd door de klas Gelabeld punt:

Map map = nieuwe HashMap (); map.put ("Iris-setosa", 0); map.put ("Iris-versicolor", 1); map.put ("Iris-virginica", 2); JavaRDD labelData = data .map (line -> {String [] parts = line.split (","); double [] v = new double [parts.length - 1]; for (int i = 0; i <parts .length - 1; i ++) {v [i] = Double.parseDouble (parts [i]);} retourneer nieuwe LabeledPoint (map.get (parts [parts.length - 1]), Vectors.dense (v)); });

Ons outputlabel in de dataset is tekstueel en geeft de soort iris aan. Om dit in een machine learning-model in te voeren, moeten we dit omzetten in numerieke waarden.

4.3. Verkennende gegevensanalyse

Bij verkennende data-analyse worden de beschikbare data geanalyseerd. Nu, algoritmen voor machine learning zijn gevoelig voor datakwaliteitDaarom hebben gegevens van hogere kwaliteit betere vooruitzichten voor het leveren van het gewenste resultaat.

Typische analysedoelstellingen zijn onder meer het verwijderen van anomalieën en het detecteren van patronen. Dit draagt ​​zelfs bij aan de kritieke stappen van feature-engineering om uit de beschikbare data tot bruikbare features te komen.

Onze dataset is in dit voorbeeld klein en goed gevormd. Daarom hoeven we ons niet over te geven aan veel data-analyse. Spark MLlib is echter uitgerust met API's om behoorlijk wat inzicht te bieden.

Laten we beginnen met een eenvoudige statistische analyse:

MultivariateStatisticalSummary samenvatting = Statistics.colStats (inputData.rdd ()); System.out.println ("Samenvatting gemiddelde:"); System.out.println (summary.mean ()); System.out.println ("Summary Variance:"); System.out.println (summary.variance ()); System.out.println ("Samenvatting niet-nul:"); System.out.println (summary.numNonzeros ());

Hier observeren we het gemiddelde en de variantie van de functies die we hebben. Dit is handig om te bepalen of we functies moeten normaliseren. Haar handig om alle functies op dezelfde schaal te hebben. We nemen ook nota van waarden die niet gelijk zijn aan nul, wat een negatieve invloed kan hebben op de prestaties van het model.

Hier is de uitvoer voor onze invoergegevens:

Samenvattend gemiddelde: [5.843333333333332,3.0540000000000003,3.7586666666666666,1.198666666666666668] Samenvatting Variantie: [0.6856935123042509,0.18800402684563744,3.113179418344516,0.58241431767337.08350.0 Samenvatting Niet-nul]: [

Een andere belangrijke metriek om te analyseren is de correlatie tussen kenmerken in de invoergegevens:

Matrix correlMatrix = Statistics.corr (inputData.rdd (), "pearson"); System.out.println ("Correlatiematrix:"); System.out.println (correlMatrix.toString ());

EEN een hoge correlatie tussen twee willekeurige kenmerken suggereert dat ze geen incrementele waarde toevoegen en een van hen kan worden verwijderd. Hier is hoe onze functies met elkaar in verband staan:

Correlatiematrix: 1,0 -0,10936924995064387 0,8717541573048727 0,8179536333691672 -0,10936924995064387 1,0 -0,4205160964011671 -0,3565440896138163 0,8717541573048727 -0,420516096401170671 1,0 -0,4205160964011671 -0,3565440896138163 0,8717541573048727 -0,420516096401170671 0,920516096401170671 1,07250964011671

4.4. De gegevens splitsen

Als we ons onze bespreking van machine learning-workflow herinneren, gaat het om verschillende iteraties van modeltraining en validatie, gevolgd door eindtests.

Om dit te laten gebeuren, we moeten onze trainingsgegevens opsplitsen in trainings-, validatie- en testsets. Om het simpel te houden, slaan we het validatiegedeelte over. Laten we onze gegevens dus opsplitsen in trainings- en testsets:

JavaRDD [] splits = parsedData.randomSplit (nieuwe dubbele [] {0.8, 0.2}, 11L); JavaRDD trainingData = splitst [0]; JavaRDD testData = splitst [1];

4.5. Modeltraining

We hebben dus een stadium bereikt waarin we onze dataset hebben geanalyseerd en voorbereid. Het enige dat overblijft is om dit in een model te voeren en de magie te starten! Makkelijker gezegd dan gedaan. We moeten een geschikt algoritme kiezen voor ons probleem - denk aan de verschillende categorieën machine learning waar we eerder over spraken.

Dat is niet moeilijk te begrijpen ons probleem past in classificatie binnen de categorie onder toezicht. Nu zijn er nogal wat algoritmen beschikbaar voor gebruik in deze categorie.

De eenvoudigste is Logistische Regressie (laat het woord regressie ons niet verwarren; het is tenslotte een classificatie-algoritme):

LogisticRegressionModel-model = nieuw LogisticRegressionWithLBFGS () .setNumClasses (3) .run (trainingData.rdd ());

Hier gebruiken we een op drie klassen gebaseerde classificatie op basis van Limited Memory BFGS. De details van dit algoritme vallen buiten het bestek van deze tutorial, maar dit is een van de meest gebruikte.

4.6. Modelevaluatie

Onthoud dat modeltraining meerdere iteraties omvat, maar voor de eenvoud hebben we hier slechts één doorgang gebruikt. Nu we ons model hebben getraind, is het tijd om dit te testen op de testdataset:

JavaPairRDD predictionAndLabels = testData .mapToPair (p -> nieuwe Tuple2 (model.predict (p.features ()), p.label ())); MulticlassMetrics metrics = nieuwe MulticlassMetrics (predictionAndLabels.rdd ()); dubbele nauwkeurigheid = metrics.accuracy (); System.out.println ("Modelnauwkeurigheid op testgegevens:" + nauwkeurigheid);

Nu, hoe meten we de effectiviteit van een model? Er zijn verschillende statistieken die we kunnen gebruiken, maar een van de eenvoudigste is nauwkeurigheid. Simpel gezegd, nauwkeurigheid is een verhouding tussen het juiste aantal voorspellingen en het totale aantal voorspellingen. Dit is wat we kunnen bereiken in een enkele uitvoering van ons model:

Modelnauwkeurigheid op testgegevens: 0.9310344827586207

Merk op dat dit van run tot run enigszins zal variëren vanwege de stochastische aard van het algoritme.

In sommige probleemdomeinen is nauwkeurigheid echter geen erg effectieve maatstaf. Andere meer geavanceerde statistieken zijn Precision and Recall (F1 Score), ROC Curve en Confusion Matrix.

4.7. Het model opslaan en laden

Ten slotte moeten we het getrainde model vaak opslaan in het bestandssysteem en het laden voor voorspelling op productiegegevens. Dit is triviaal in Spark:

model.save (sc, "model \ logistic-regressie"); LogisticRegressionModel sameModel = LogisticRegressionModel .load (sc, "model \ logistic-regressie"); Vector newData = Vectors.dense (nieuwe dubbele [] {1,1,1,1}); dubbele voorspelling = sameModel.predict (newData); System.out.println ("Modelvoorspelling op nieuwe gegevens =" ​​+ voorspelling);

Dus we slaan het model op in het bestandssysteem en laden het weer terug. Na het laden kan het model direct worden gebruikt om output op nieuwe data te voorspellen. Hier is een voorbeeld van een voorspelling van willekeurige nieuwe gegevens:

Modelvoorspelling op nieuwe gegevens = 2.0

5. Voorbij het primitieve voorbeeld

Hoewel het voorbeeld dat we hebben doorgenomen de workflow van een machine learning-project in grote lijnen omvat, laat het veel subtiele en belangrijke punten over. Hoewel het niet mogelijk is om ze hier in detail te bespreken, kunnen we zeker enkele van de belangrijke bespreken.

Spark MLlib heeft via zijn API's uitgebreide ondersteuning op al deze gebieden.

5.1. Model selectie

Modelkeuze is vaak een van de complexe en kritieke taken. Het trainen van een model is een ingewikkeld proces en het is veel beter om het te doen op een model waarvan we zeker weten dat het de gewenste resultaten zal opleveren.

Hoewel de aard van het probleem ons kan helpen bij het identificeren van de categorie van machine learning-algoritmen waaruit we kunnen kiezen, is het niet een volledige klus. Binnen een categorie zoals classificatie, zoals we eerder zagen, er zijn vaak veel verschillende algoritmen en hun variaties om uit te kiezen.

Vaak de beste manier van handelen is snel prototypen op een veel kleinere set gegevens. Een bibliotheek als Spark MLlib maakt het werk van snelle prototypes veel gemakkelijker.

5.2. Model Hyper-Parameter Tuning

Een typisch model bestaat uit kenmerken, parameters en hyperparameters. Functies zijn wat we in het model invoeren als invoergegevens. Modelparameters zijn variabelen die het model leert tijdens het trainingsproces. Afhankelijk van het model er zijn bepaalde aanvullende parameters die we op basis van ervaring moeten instellen en iteratief moeten aanpassen. Dit worden modelhyperparameters genoemd.

De leersnelheid is bijvoorbeeld een typische hyperparameter in op gradiënt-afdaling gebaseerde algoritmen. De leerfrequentie bepaalt hoe snel parameters worden aangepast tijdens trainingscycli. Dit moet passend worden ingesteld om het model effectief en in een redelijk tempo te laten leren.

Hoewel we kunnen beginnen met een initiële waarde van dergelijke hyperparameters op basis van ervaring, moeten we modelvalidatie uitvoeren en deze handmatig iteratief afstemmen.

5.3. Modelprestaties

Een statistisch model, terwijl het wordt getraind, is vatbaar voor overfitting en underfitting, die beide leiden tot slechte modelprestaties. Underfitting verwijst naar het geval waarin het model de algemene details niet voldoende uit de gegevens haalt. Aan de andere kant treedt overfitting op wanneer het model ook ruis uit de gegevens begint op te pikken.

Er zijn verschillende methoden om de problemen van onder- en overfitting te voorkomen, die vaak in combinatie worden toegepast. Bijvoorbeeld, Om overfitting tegen te gaan, zijn de meest gebruikte technieken kruisvalidatie en regularisatie. Evenzo kunnen we, om de ondermaatse pasvorm te verbeteren, de complexiteit van het model vergroten en de trainingstijd verlengen.

Spark MLlib heeft fantastische ondersteuning voor de meeste van deze technieken, zoals regularisatie en kruisvalidatie. In feite hebben de meeste algoritmen hiervoor standaardondersteuning.

6. Spark MLlib in vergelijking

Hoewel Spark MLlib een behoorlijk krachtige bibliotheek is voor machine learning-projecten, is het zeker niet de enige die hiervoor geschikt is. Er zijn nogal wat bibliotheken beschikbaar in verschillende programmeertalen met wisselende ondersteuning. We zullen hier enkele van de populaire bespreken.

6.1. Tensorflow / Keras

Tensorflow is een open-source bibliotheek voor dataflow en differentieerbare programmering, veel gebruikt voor machine learning-toepassingen. Samen met zijn abstractie op hoog niveau, Keras, is het een hulpmiddel bij uitstek voor machine learning. Ze zijn voornamelijk geschreven in Python en C ++ en worden voornamelijk gebruikt in Python. In tegenstelling tot Spark MLlib heeft het geen polyglot aanwezigheid.

6.2. Theano

Theano is een andere op Python gebaseerde open-source bibliotheek voor het manipuleren en evalueren van wiskundige uitdrukkingen - bijvoorbeeld matrixgebaseerde uitdrukkingen, die vaak worden gebruikt in algoritmen voor machine learning. In tegenstelling tot Spark MLlib, wordt Theano opnieuw voornamelijk gebruikt in Python. Keras kan echter samen met een Theano-backend worden gebruikt.

6.3. CNTK

Microsoft Cognitive Toolkit (CNTK) is een diepgaand leerkader geschreven in C ++ dat computationele stappen beschrijft via een gerichte grafiek. Het kan worden gebruikt in zowel Python- als C ++ -programma's en wordt voornamelijk gebruikt bij het ontwikkelen van neurale netwerken. Er is een Keras-back-end op basis van CNTK beschikbaar voor gebruik die de vertrouwde intuïtieve abstractie biedt.

7. Conclusie

Kortom, in deze tutorial hebben we de basisprincipes van machine learning doorgenomen, inclusief verschillende categorieën en workflow. We hebben de basisprincipes van Spark MLlib doorgenomen als een machine learning-bibliotheek die voor ons beschikbaar is.

Verder hebben we op basis van de beschikbare dataset een simpele machine learning applicatie ontwikkeld. We hebben in ons voorbeeld enkele van de meest voorkomende stappen in de machine learning-workflow geïmplementeerd.

We hebben ook enkele van de geavanceerde stappen in een typisch machine learning-project doorlopen en hoe Spark MLlib daarbij kan helpen. Ten slotte hebben we enkele van de alternatieve machine learning-bibliotheken gezien die we kunnen gebruiken.

Zoals altijd is de code te vinden op GitHub.


$config[zx-auto] not found$config[zx-overlay] not found