Definitiv guide till Random Forest Algorithm med Python och Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Definitiv guide till Random Forest Algorithm med Python och Scikit-Learn

Beskrivning

Random Forest-algoritmen är en av de mest flexibla, kraftfulla och allmänt använda algoritmerna för klassificering och regression, byggd som en ensemble av beslutsträd.

Om du inte är bekant med dessa – oroa dig inte, vi täcker alla dessa koncept.

I den här djupgående praktiska guiden bygger vi en intuition om hur beslutsträd fungerar, hur ensembling ökar enskilda klassificerare och regressorer, vad slumpmässiga skogar är och bygg en slumpmässig skogklassificerare och regressor med Python och Scikit-Learn, genom ett end-to-end miniprojekt, och svara på en forskningsfråga.

Tänk på att du för närvarande är en del av en forskargrupp som analyserar data om kvinnor. Gruppen har samlat in 100 dataposter och vill kunna organisera dessa initiala register genom att dela in kvinnorna i kategorier: att vara gravid eller inte, och att bo på landsbygden eller i tätorter. Forskarna vill förstå hur många kvinnor som skulle vara i varje kategori.

Det finns en beräkningsstruktur som gör precis det, det är träd strukturera. Genom att använda en trädstruktur kommer du att kunna representera de olika divisionerna för varje kategori.

Beslutsträd

Hur fyller man i noderna i ett träd? Det är här beslutsträd hamna i fokus.

Först kan vi dela upp journalerna efter graviditet, efter det kan vi dela upp dem genom att bo i städer eller på landsbygden. Lägg märke till att vi kunde göra detta i en annan ordning, inledningsvis dividerat med vilket område kvinnorna bor och efter deras graviditetsstatus. Av detta kan vi se att trädet har en inneboende hierarki. Förutom att organisera information, organiserar ett träd information på ett hierarkiskt sätt – ordningen som informationen visas spelar roll och leder till olika träd som ett resultat.

Nedan är ett exempel på trädet som har beskrivits:

I trädbilden finns det 7 rutor, den överst som står för totalt 100 kvinnor, denna övre ruta är kopplad till två rutor nedan, som delar upp kvinnorna baserat på deras antal av 78 inte gravida och 22 gravida, och från båda tidigare rutor finns fyra rutor; två kopplade till varje ruta ovanför som delar upp kvinnorna utifrån deras område, för de icke-gravida bor 45 i tätort, 33 på landsbygden och för de gravida bor 14 på landsbygden och 8 i tätort. Bara genom att titta på trädet är det lätt att förstå dessa indelningar och se hur varje "lager" härrör från tidigare, dessa lager är trädet nivåer, beskriver nivåerna djup av trädet:

Definitiv guide till Random Forest Algorithm med Python och Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Observera i bilden ovan att den första trädnivån är nivå 0 där det bara finns en ruta, följt av nivå 1 där det finns två rutor, och nivå 2 där det finns fyra rutor. Det här är en djup 2 träd.

I nivå 0 kallas kvadraten som kommer från trädet, den första rotnod, denna rot har två barnnoder på nivå 1, alltså föräldernoder till de fyra noderna i nivå 2. Se att de "fyrkanter" vi har nämnt hittills faktiskt kallas noder; och att varje föregående nod är en förälder till följande noder, det vill säga dess barn. De underordnade noderna för varje nivå som har samma förälder anropas syskon, som kan ses på nästa bild:

Definitiv guide till Random Forest Algorithm med Python och Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

I den föregående bilden visar vi också nivå 1 som varande inre noder, när de är mellan roten och de sista noderna, som är bladnoder. Bladknutorna är den sista delen av ett träd, om vi av de 100 initiala kvinnorna skulle säga hur många som är gravida och bor på landsbygden, skulle vi kunna göra detta genom att titta på löven. Så numret vid bladen skulle svara på den första forskningsfrågan.

Om det fanns nya uppgifter om kvinnor, och trädet som tidigare användes för att kategorisera dem, nu användes för att avgöra om en kvinna kunde eller inte kunde vara en del av forskningen, skulle det fortfarande fungera? Trädet skulle använda samma kriterier, och en kvinna skulle vara berättigad att delta om hon är gravid och bor på landsbygden.

Definitiv guide till Random Forest Algorithm med Python och Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Genom att titta på bilden ovan kan vi se att svaren på frågorna för varje trädnod – ”är hon en deltagare?”, ”är hon gravid?”, ”bor hon på landsbygden?”- är ja, ja, och ja, så det verkar som att trädet kan tänkas leda till ett beslut, i det här fallet, att kvinnan får delta i forskningen.

Detta är den väsen av beslutsträd i, gjort på ett manuellt sätt. Med hjälp av maskininlärning kan vi konstruera en modell som konstruerar detta träd automatiskt åt oss, på ett sådant sätt att maximera noggrannheten i de slutliga besluten.

Notera: det finns flera typer av träd inom datavetenskap, såsom binära träd, allmänna träd, AVL-träd, splayträd, rödsvarta träd, b-träd, etc. Här fokuserar vi på att ge en allmän uppfattning om vad som är ett beslutsträd . Om det beror på svaret av a ja or Nej fråga för varje nod och därmed har varje nod högst två barn, när de sorteras så att de "mindre" noderna är till vänster, klassificerar detta beslutsträd som binära träd.

I de föregående exemplen, observera hur trädet kunde antingen klassificera nya data som deltagare eller icke-deltagare, eller så kan frågorna också ändras till – ”hur många är deltagare?”, ”hur många är gravida?”, ”hur många bor på landsbygden?”- vilket leder till att vi hittar mängd av gravida deltagare som bor på landsbygden.

När data är sekretessbelagda betyder det att trädet utför en klassificering uppgift, och när mängden data hittas, utför trädet en regression uppgift. Det innebär att beslutsträdet kan användas för både uppgifter – klassificering och regression.

Nu när vi förstår vad ett beslutsträd är, hur kan det användas och vilken nomenklatur som används för att beskriva det, kan vi undra över dess begränsningar.

Förstå Random Forests

Vad händer med beslutet om någon deltagare lever på uppdelningen mellan stad och landsbygd? Skulle trädet lägga till detta rekord till landsbygd eller stad? Det verkar svårt att passa in denna data i den struktur vi har för närvarande, eftersom den är ganska tydlig.

Och vad händer om en kvinna som bor på en båt deltar i forskningen, skulle det anses vara landsbygd eller urban? På samma sätt som det tidigare fallet är det en utmanande datapunkt att klassificera med tanke på de tillgängliga alternativen i trädet.

Genom att tänka lite mer på exemplet på beslutsträdet kan vi se att det kan klassificera nya data korrekt med tanke på att det redan följer ett mönster som trädet redan har – men när det finns poster som skiljer sig från de initiala data som definierade trädet, trädstrukturen är för stel, vilket gör att posterna inte kan klassificeras.

Det gör att beslutsträdet kan vara strikt och begränsat i sina möjligheter. Ett idealiskt beslutsträd skulle vara mer flexibelt och kunna ta emot mer nyanserade osynliga data.

Lösning: Precis som "två par ögon ser bättre än ett", kommer två modeller vanligtvis med ett mer exakt svar än ett. Med hänsyn till mångfalden i kunskapsrepresentationer (kodade i trädstrukturen), är stelheten i de lite olika strukturerna mellan flera liknande träd inte längre lika begränsande, eftersom bristerna i ett träd kan "kompenseras för" av ett annat. Genom att kombinera många träd tillsammans får vi en skog.

När det gäller svaret på den inledande frågan vet vi redan att det kommer att kodas i trädens blad – men vad förändras när vi har många träd istället för ett?

Om träden kombineras för en klassificering kommer resultatet att definieras av majoriteten av svaren, detta kallas majoritetsomröstning; och i fallet med en regression kommer numret som ges av varje träd i skogen att vara genomsnitt.

Ensemble Learning och modellensembler

Denna metod är känd som ensembleinlärning. När du använder ensembleinlärning kan du blanda alla algoritmer, så länge du kan se till att utdata kan analyseras och kombineras med andra utdata (antingen manuellt eller med befintliga bibliotek). Vanligtvis sammanfogar du flera modeller av samma typ, till exempel flera beslutsträd, men du är inte begränsad till att bara gå med i ensembler av samma modelltyp.

Ensembling är ett praktiskt taget garanterat sätt att generalisera bättre till ett problem och att pressa ut en liten prestationshöjning. I vissa fall ger sammansättning av modeller en signifikant ökning av prediktiv kraft, och ibland bara liten. Detta beror på den datauppsättning du tränar och utvärderar på, såväl som själva modellerna.

Att sammanfoga beslutsträd ger avkastning signifikant prestandahöjningar jämfört med enskilda träd. Detta tillvägagångssätt blev populärt inom forskning och tillämpad maskininlärning och var så vanligt att ensemblen av beslutsträd i dagligt tal kallades en skog, och den vanliga typen av skog som skapades (en skog av beslutsträd på en slumpmässig delmängd av funktioner) populariserade namnet slumpmässiga skogar.

Med tanke på storskalig användning har bibliotek som Scikit-Learn implementerat omslag för RandomForestRegressors och RandomForestClassifiers, byggda ovanpå sina egna implementeringar av beslutsträd, för att tillåta forskare att undvika att bygga sina egna ensembler.

Låt oss dyka in i slumpmässiga skogar!

Hur fungerar Random Forest Algorithm?

Följande är de grundläggande stegen som är involverade när du kör den slumpmässiga skogsalgoritmen:

  1. Välj ett antal slumpmässiga poster, det kan vara vilket nummer som helst, till exempel 4, 20, 76, 150 eller till och med 2.000 XNUMX från datamängden (kallas N uppgifter). Antalet beror på datasetets bredd, ju bredare desto större N kan vara. Det är här slumpmässig del i algoritmens namn kommer från!
  2. Bygg ett beslutsträd baserat på dessa N slumpmässiga poster;
  3. Beroende på antalet träd som definierats för algoritmen, eller antalet träd i skogen, upprepa steg 1 och 2. Detta genererar fler träd från uppsättningar av slumpmässiga dataposter;
  4. Efter steg 3 kommer det sista steget, som är att förutsäga resultaten:
    • Vid klassificering: varje träd i skogen kommer att förutsäga vilken kategori det nya rekordet tillhör. Därefter tilldelas det nya rekordet den kategori som vinner majoriteten.
    • Vid regression: varje träd i skogen förutsäger ett värde för den nya posten, och det slutliga förutsägelsevärdet kommer att beräknas genom att ta ett medelvärde av alla värden som förutsägs av alla träd i skogen.

Varje träd som passar på en slumpmässig delmängd av funktioner kommer nödvändigtvis inte att ha någon kunskap om vissa andra funktioner, vilket korrigeras genom ensembling, samtidigt som beräkningskostnaden hålls lägre.

Råd: Eftersom Random Forest använder beslutsträd som bas, är det till stor hjälp att förstå hur beslutsträd fungerar och få lite övning med dem individuellt för att bygga en intuition på deras struktur. När du komponerar slumpmässiga skogar kommer du att ställa in värden som det maximala djupet på ett träd, det minsta antal prover som krävs för att vara vid en lövnod, kriterierna för att satsa på att bestämma interna splittringar, etc. för att hjälpa ensemblen att bättre passa en dataset och generalisera till nya punkter. I praktiken kommer du vanligtvis att använda Random Forests, Gradient Boosting eller Extreme Gradient Boosting eller andra trädbaserade metoder, så att ha ett bra grepp om hyperparametrarna i ett enda beslutsträd kommer att hjälpa till att bygga en stark intuition för att trimma ensembler.

Med en intuition om hur träd fungerar, och en förståelse för Random Forests – det enda som återstår är att träna på att bygga, träna och trimma dem på data!

Bygga och träna slumpmässiga skogsmodeller med Scikit-Learn

Det fanns en anledning till att exemplen som hittills använts handlar om graviditet, bostadsområde och kvinnor.

År 2020 märkte forskare från Bangladesh att dödligheten bland gravida kvinnor fortfarande var mycket hög, speciellt med tanke på de som bor på landsbygden. På grund av det använde de ett IOT-övervakningssystem för att analysera risken för mödrars hälsa. IOT-systemet samlade in data från olika sjukhus, samhällskliniker och mödrahälsovård från landsbygdsområdena i Bangladesh.

Den insamlade informationen organiserades sedan i en kommaavgränsad fil (csv) och laddades upp till UCI:s maskininlärningsförråd.

Detta är data som vi kommer att använda för att öva och försöka förstå om en gravid kvinna har en låg, Medium or hög risk för dödlighet.

Anmärkningar: du kan ladda ner datasetet här..

Använder Random Forest för klassificering

Eftersom vi vill veta om kvinnan har en låg, Medium or hög risk för dödlighet innebär detta att vi kommer att utföra en klassificering med tre klasser. När ett problem har mer än två klasser kallas det för a multiklass problem, i motsats till ett binär problem (där du vanligtvis väljer mellan två klasser 0 och 1).

I det här första exemplet kommer vi att implementera en klassificeringsmodell med flera klasser med en Random Forest-klassificerare och Pythons Scikit-Learn.

Vi kommer att följa de vanliga maskininlärningsstegen för att lösa detta problem, som laddar bibliotek, läser data, tittar på sammanfattande statistik och skapar datavisualiseringar för att bättre förstå det. Sedan förbearbetar och delar upp data följt av generering, utbildning och utvärdering av en modell.

Importerar bibliotek

Vi kommer att använda Pandas för att läsa data, Seaborn och Matplotlib för att visualisera den, och NumPy för de fantastiska verktygsmetoderna:

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
Importera datamängden

Följande kod importerar datamängden och laddar den till en python DataFrame:

dataset = pd.read_csv("../../datasets/random-forest/maternal_health_risk.csv")

För att titta på de första fem raderna av data, kör vi head() kommando:

dataset.head()

Denna utgångar:

    Age SystolicBP  DiastolicBP BS      BodyTemp    HeartRate   RiskLevel
0   25  130         80          15.0    98.0        86          high risk
1   35  140         90          13.0    98.0        70          high risk
2   29  90          70          8.0     100.0       80          high risk
3   30  140         85          7.0     98.0        70          high risk
4   35  120         60          6.1     98.0        76          low risk

Här kan vi se alla attribut som samlats in under forskningen.

  • Ålder: åldrar i år.
  • Systoliskt BP: övre värdet för blodtryck i mmHg, ett signifikant attribut under graviditet.
  • Diastoliskt BP: lägre blodtrycksvärde i mmHg, ett annat signifikant attribut under graviditeten.
  • BS: blodsockernivåer i form av en molär koncentration, mmol/L.
  • HeartRate: vilopuls i slag per minut.
  • RiskLevel: risknivå under graviditet.
  • BodyTemp: kroppstemperaturen.

Nu när vi förstår mer om vad som mäts kan vi titta på vilka typer av data med info():

dataset.info()

Detta resulterar i:


RangeIndex: 1014 entries, 0 to 1013
Data columns (total 7 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   Age          1014 non-null   int64  
 1   SystolicBP   1014 non-null   int64  
 2   DiastolicBP  1014 non-null   int64  
 3   BS           1014 non-null   float64
 4   BodyTemp     1014 non-null   float64
 5   HeartRate    1014 non-null   int64  
 6   RiskLevel    1014 non-null   object 
dtypes: float64(2), int64(4), object(1)
memory usage: 55.6+ KB

Från att titta på RangeIndex linje, kan vi se att det finns 1014 poster, och kolumnen Non-Null Count informerar om att data inte saknar några värden. Det betyder att vi inte behöver göra någon behandling för saknad data!

I Dtype kolumn kan vi se typen av varje variabel. För närvarande, float64 kolumner sådana BS och BodyTemp har numeriska värden som kan variera i alla intervall, såsom 15.0, 15.51, 15.76, 17.28, vilket gör dem numeriskt kontinuerligt (du kan alltid lägga till en 0 till ett flyttal, oändligt). Däremot kan variabler som t.ex Age, SystolicBP, DiastolicBPoch HeartRate är av typen int64, detta betyder att siffrorna bara ändras av enheten, såsom 11, 12, 13, 14 – vi kommer inte ha en puls på 77.78, det är antingen 77 eller 78 – det är numeriskt diskret värden. Och det har vi också RiskLevel med en object typ indikerar detta vanligtvis att variabeln är en text, och vi kommer förmodligen att behöva omvandla den till ett tal. Eftersom risknivån växer från låg till hög finns det en underförstådd ordning i kategorierna, vilket indikerar att det är en kategoriskt ordinal variabel.

Anmärkningar: det är viktigt att titta på typen av varje data och se om det är vettigt enligt dess sammanhang. Till exempel är det inte meningsfullt att ha hälften av en pulsenhet, så det betyder att interger-typen är tillräcklig för ett diskret värde. När det inte händer kan du ändra typen av data med Pandas' astype() egendom – df['column_name'].astype('type').

Efter att ha tittat på datatyper kan vi använda describe() för att ta en topp på viss beskrivande statistik, såsom medelvärdena för varje kolumn, standardavvikelsen, kvantiler, minimi- och maximala datavärden:

dataset.describe().T 

Ovanstående kod visar:

            count   mean        std         min     25%     50%     75%     max
Age         1014.0  29.871795   13.474386   10.0    19.0    26.0    39.0    70.0
SystolicBP  1014.0  113.198225  18.403913   70.0    100.0   120.0   120.0   160.0
DiastolicBP 1014.0  76.460552   13.885796   49.0    65.0    80.0    90.0    100.0
BS          1014.0  8.725986    3.293532    6.0     6.9     7.5     8.0     19.0
BodyTemp    1014.0  98.665089   1.371384    98.0    98.0    98.0    98.0    103.0
HeartRate   1014.0  74.301775   8.088702    7.0     70.0    76.0    80.0    90.0
RiskLevel   1014.0  0.867850    0.807353    0.0     0.0     1.0     2.0     2.0

Lägg märke till att för de flesta kolumner betyda värden är långt ifrån standardavvikelse (std) – detta indikerar att uppgifterna inte nödvändigtvis följer en väluppfostrad statistisk fördelning. Om det gjorde det, skulle det ha hjälpt modellen när den förutspådde risken. Vad som kan göras här är att förbehandla data för att göra den mer representativ som om den vore data från hela världens befolkning, eller mer normaliserad. Men, en fördel när man använder Random Forest-modeller för klassificering, är att den inneboende trädstrukturen kan hantera data som inte har normaliserats, när den väl delar den med värdet i varje trädnivå för varje variabel.

Dessutom, eftersom vi använder träd och att den resulterande klassen kommer att erhållas genom att rösta, jämför vi inte i sig mellan olika värden, bara mellan samma typer av värden, så att justera funktionerna till samma skala är inte nödvändigt i det här fallet . Detta innebär att Random Forest-klassificeringsmodellen är skala invariant, och du behöver inte utföra funktionsskalning.

I det här fallet är steget i dataförbehandlingen vi kan ta att transformera kategorin RiskLevel kolumn till en numerisk.

Visualisera data

Innan omvandling RiskLevel, låt oss också snabbt visualisera data genom att titta på kombinationerna av punkter för varje par funktioner med en Scatterplot och hur punkterna fördelas genom att visualisera histogramkurvan. För att göra det kommer vi att använda Seaborn's pairplot() som kombinerar båda tomterna. Den genererar båda plotten för varje funktionskombination och visar punkternas färgkodade enligt deras risknivå med hue fast egendom:

g = sns.pairplot(dataset, hue='RiskLevel')
g.fig.suptitle("Scatterplot and histogram of pairs of variables color coded by risk level", 
               fontsize = 14, 
               y=1.05); 

Ovanstående kod genererar:

Definitiv guide till Random Forest Algorithm med Python och Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

När man tittar på handlingen skulle den idealiska situationen vara att ha en tydlig separation mellan kurvor och punkter. Som vi kan se är de tre typerna av riskklasser mest blandade, eftersom träd internt drar linjer när de avgränsar utrymmena mellan punkter, kan vi anta att fler träd i skogen kanske kan begränsa fler utrymmen och bättre klassificera punkterna.

Med den grundläggande explorativa dataanalysen gjord kan vi förbearbeta RiskLevel kolonn.

Dataförbehandling för klassificering

För att vara säker finns det bara tre klasser av RiskLevel i vår data, och att inga andra värden har lagts till felaktigt, kan vi använda unique() för att visa kolumnens unika värden:

dataset['RiskLevel'].unique()

Denna utgångar:

array(['high risk', 'low risk', 'mid risk'], dtype=object)

Klasserna kontrolleras, nu är nästa steg att omvandla varje värde till ett tal. Eftersom det finns en ordning mellan klassificeringar kan vi använda värdena 0, 1 och 2 för att beteckna låg, Medium och hög risker. Det finns många sätt att ändra kolumnvärdena, enligt Pythons enkelt är bättre än komplext motto, vi kommer att använda .replace() metod och ersätt dem helt enkelt med deras heltalsrepresentationer:

dataset['RiskLevel'] = dataset['RiskLevel'].replace('low risk', 0).replace('mid risk', 1).replace('high risk', 2)

Efter att ha ersatt värdena kan vi dela upp data i vad som kommer att användas för att träna modellen, den pass or X, och vad vi vill förutsäga etiketter or y:

y = dataset['RiskLevel']
X = dataset.drop(['RiskLevel'], axis=1)

När X och y set är klara, vi kan använda Scikit-Learn's train_test_split() metod för att ytterligare dela upp dem i tåg- och testset:

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.2, 
                                                    random_state=SEED)

Råd: kom ihåg att använda ett slumpmässigt tillståndsfrö om du vill göra resultatet reproducerbart. Vi har använt ett slumpmässigt tillståndsfrö så att du kan återskapa samma resultat som från guiden.

Här använder vi 20 % av data för testning och 80 % för träning.

Utbilda en RandomForestClassifier

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!

Scikit-Learn implementerade ensembler under sklearn.ensemble modul. En ensemble av beslutsträd som används för klassificering, där en majoritetsomröstning tas, implementeras som RandomForestClassifier.

Med tåget och testset kan vi importera RandomForestClassifier klass och skapa modellen. Till att börja med, låt oss skapa en skog med tre träd, genom att ställa in n_estimators parameter som 3, och med varje träd som har tre nivåer, genom inställning max_depthtill 2:

from sklearn.ensemble import RandomForestClassifier

rfc = RandomForestClassifier(n_estimators=3, 
                             max_depth=2,
                             random_state=SEED)

Notera: Standardvärdet för n_estimators is 100. Detta ökar prediktiv kraft och generalisering av ensemblen, men vi skapar en mindre för att göra det lättare att visualisera och inspektera den. Med bara 3 träd – vi kan visualisera och inspektera dem manuellt att ytterligare bygga vår intuition av både de enskilda träden, och deras medberoende. Detsamma gäller för max_depth, vilket är None, vilket innebär att träden kan bli djupare och djupare för att passa data efter behov.

För att passa modellen runt data – kallar vi fit() metod, genom att lägga in träningsfunktionerna och etiketterna:


rfc.fit(X_train, y_train)

y_pred = rfc.predict(X_test)

Vi kan nu jämföra de förutsagda etiketterna mot de riktiga etiketterna för att utvärdera hur bra modellen gjorde! Innan vi utvärderar modellen, låt oss ta en titt på ensemblen.

För att titta lite djupare in i modellen kan vi visualisera vart och ett av träden och hur de delar upp data. Detta kan göras genom att använda tree modul inbyggd i Scikit-Learn, och sedan gå igenom var och en av estimatorerna i ensemblen:


from sklearn import tree

features = X.columns.values 
classes = ['0', '1', '2'] 



for estimator in rfc.estimators_:
    print(estimator)
    plt.figure(figsize=(12,6))
    tree.plot_tree(estimator,
                   feature_names=features,
                   class_names=classes,
                   fontsize=8, 
                   filled=True, 
                   rounded=True)
    plt.show()

Ovanstående kod visar trädplotterna:

Definitiv guide till Random Forest Algorithm med Python och Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.
Definitiv guide till Random Forest Algorithm med Python och Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.
Definitiv guide till Random Forest Algorithm med Python och Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Lägg märke till hur de tre träden är olika. Den första börjar med BS funktion, den andra med DiastolicBP, och den tredje med BS om igen. Även om den tredje tittar på ett annat antal prover. På den högra grenen bestämmer också de två första träden att använda Age på bladnivån, medan det tredje trädet slutar med BS funktion. Med bara tre estimatorer är det tydligt hur uppskalning ger en rik, mångsidig representation av kunskapen som framgångsrikt kan sammanföras till en mycket exakt modell.

Ju fler träd i skogen, desto mer mångsidig kan modellen vara. Det finns en poäng med att minska avkastningen, men eftersom många träd passar på en slumpmässig delmängd av funktioner, kommer det att finnas en hel del liknande träd som inte erbjuder mycket mångfald i ensemblen, och som kommer att börja ha för mycket röstkraft och snedställa ensemblen så att den blir överanpassad på träningsdatauppsättningen, vilket skadar generaliseringen till valideringsuppsättningen.

Det gjordes en hypotes tidigare om att ha fler träd och hur det skulle kunna förbättra modellresultaten. Låt oss ta en titt på resultaten, generera en ny modell och se om hipotesen håller!

Utvärdera RandomForestClassifier

Scikit-Learn gör det enkelt att skapa baslinjer genom att tillhandahålla en DummyClassifier, som ger prognoser utan att använda inmatningsfunktionerna (helt slumpmässiga utgångar). Om din modell är bättre än DummyClassifier, några lärande händer! För att maximera inlärningen – du kan testa olika hyperparametrar automatiskt genom att använda en RandomizedSearchCV or GridSearchCV. Förutom att ha en baslinje kan du utvärdera din modells prestanda från linsen av flera mätvärden.

Några traditionella klassificeringsmått som kan användas för att utvärdera algoritmen är precision, återkallelse, f1-poäng, noggrannhet och förvirringsmatris. Här är en kort förklaring om var och en av dem:

  1. 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}}
$$

  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. Noggrannhet: beskriver hur många förutsägelser vår klassificerare fick rätt. Det lägsta noggrannhetsvärdet är 0 och det högsta är 1. Det värdet multipliceras vanligtvis med 100 för att få en procentsats:

$$
precision = frac{text{antal korrekta förutsägelser}}{text{totalt antal förutsägelser}}
$$

Notera: Det är praktiskt taget omöjligt att få en 100 % noggrannhet på alla verkliga data som du skulle vilja tillämpa maskininlärning på. Om du ser en klassificerare med 100 % noggrannhet, eller till och med ett resultat på nästan 100 % – var skeptisk och utför en utvärdering. En vanlig orsak till dessa problem är dataläckage (direkt eller indirekt att en del av träningstestet läcker in i en testset). Det finns ingen konsensus om vad "en bra noggrannhet är", främst för att det beror på dina data - ibland kommer en 70% noggrannhet att vara hög! Ibland blir det väldigt låg noggrannhet. Generellt, över 70 % är tillräckligt för många modeller, men detta är upp till domänforskaren att avgöra.

Du kan köra följande skript för att importera de nödvändiga biblioteken och titta på resultaten:

from sklearn.metrics import classification_report, confusion_matrix

cm = confusion_matrix(y_test, y_pred)
sns.heatmap(cm, annot=True, fmt='d').set_title('Maternal risks confusion matrix (0 = low risk, 1 = medium risk, 2 = high risk)')

print(classification_report(y_test,y_pred))

Utgången kommer att se ut så här:

                precision    recall  f1-score   support

           0       0.53      0.89      0.66        80
           1       0.57      0.17      0.26        76
           2       0.74      0.72      0.73        47

    accuracy                           0.58       203
   macro avg       0.61      0.59      0.55       203
weighted avg       0.59      0.58      0.53       203

Definitiv guide till Random Forest Algorithm med Python och Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Observera i klassificeringsrapporten att återkallelsen är hög, 0.89 för klass 0, både precision och återkallelse är hög för klass 2, 0.74, 0.72 – och för klass 1 är de låga, speciellt återkallelsen på 0.17 och en precision på 0.57 . Förhållandet mellan återkallelse och precision för alla tre klasser individuellt fångas i F1 poäng, som är det harmoniska medelvärdet mellan återkallelse och precision – modellen gör ok för klass 0, ganska dåligt för klass 1 och hyfsat för klass 2.

Modellen har mycket svårt att identifiera fall med medelhög risk.

Noggrannheten som uppnås av vår slumpmässiga skogsklassificerare med endast 3 träd är av 0.58 (58%) – det betyder att det blir lite mer än hälften av resultaten rätt. Detta är en låg noggrannhet, och kanske skulle kunna förbättras genom att lägga till fler träd.

Genom att titta på förvirringsmatrisen kan vi se att de flesta av misstagen är när man klassificerar 52 poster med medelrisk som låg risk, vilket ger ytterligare insikt om det låga återkallandet av klass 1. Det är partiskt mot att klassificera medelriskpatienter som låg- riskpatienter.

En annan sak som kan kontrolleras för att generera ännu mer insikt är vilka funktioner som klassificeraren tar mest hänsyn till när de förutsäger. Detta är ett viktigt steg att ta för förklarliga maskininlärningssystem, och hjälper till att identifiera och mildra partiskhet i modeller.

För att se det kan vi komma åt feature_importances_ klassificerarens egendom. Detta kommer att ge oss en lista med procentsatser, så att vi också kan komma åt feature_names_in_ egenskap för att få namnet på varje funktion, organisera dem i en dataram, sortera dem från högsta till lägsta och plotta resultatet:


features_df = pd.DataFrame({'features': rfc.feature_names_in_, 'importances': rfc.feature_importances_ })


features_df_sorted = features_df.sort_values(by='importances', ascending=False)


g = sns.barplot(data=features_df_sorted, x='importances', y ='features', palette="rocket")
sns.despine(bottom = True, left = True)
g.set_title('Feature importances')
g.set(xlabel=None)
g.set(ylabel=None)
g.set(xticks=[])
for value in g.containers:
    g.bar_label(value, padding=2)

Definitiv guide till Random Forest Algorithm med Python och Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Lägg märke till hur klassificeraren mest överväger blodsocker, sedan lite av det diastoliska trycket, kroppstemperaturen och bara lite ålder för att fatta ett beslut, detta kan också ha att göra med den låga återkallelsen på klass 1, kanske har medelriskdata att göra med egenskaper som inte är mycket beaktas av modellen. Du kan försöka leka mer med funktionsviktigheter för att undersöka detta, och se om förändringar på modellen påverkar funktionerna som används, även om det finns ett signifikant samband mellan några av funktionerna och de förutsagda klasserna.

Det är äntligen dags att generera en ny modell med fler träd för att se hur det påverkar resultaten. Låt oss skapa rfc_ skog med 900 träd, 8 nivåer och samma frö. Kommer resultaten att förbättras?

rfc_ = RandomForestClassifier(n_estimators=900, 
                             max_depth=7,
                             random_state=SEED)
rfc_.fit(X_train, y_train)
y_pred = rfc_.predict(X_test)

Beräkna och visa måtten:

cm_ = confusion_matrix(y_test, y_pred)
sns.heatmap(cm_, annot=True, fmt='d').set_title('Maternal risks confusion matrix (0 = low risk, 1 = medium risk, 2 = high risk) for 900 trees with 8 levels')

print(classification_report(y_test,y_pred))

Denna utgångar:

                precision    recall  f1-score   support

           0       0.68      0.86      0.76        80
           1       0.75      0.58      0.65        76
           2       0.90      0.81      0.85        47

    accuracy                           0.74       203
   macro avg       0.78      0.75      0.75       203
weighted avg       0.76      0.74      0.74       203

Definitiv guide till Random Forest Algorithm med Python och Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Det här visar hur vi har förbättrat våra mätvärden genom att lägga till fler träd och mer specialiserade träd (högre nivåer). Vi har fortfarande en låg återkallelse för klass 1, men träffsäkerheten är nu 74%. F1-poängen vid klassificering av högriskfall är 0.85, vilket innebär att högriskfall nu är lättare att identifiera jämfört med 0.73 i den tidigare modellen!

I ett dagligt projekt kan det vara viktigare att identifiera högriskfall, till exempel med ett mått som liknar precision, vilket också kallas känslighet i statistik. Försök att justera några av modellparametrarna och observera resultaten.

Hittills har vi fått en övergripande förståelse för hur Random Forest kan användas för att klassificera data – i nästa avsnitt kan vi använda samma dataset på ett annat sätt för att se hur samma modell förutsäger värden med regression.

Använda slumpmässiga skogar för regression

I det här avsnittet kommer vi att studera hur en Random Forest-algoritm kan användas för att lösa regressionsproblem med Scikit-Learn. Stegen som följs för att implementera denna algoritm är nästan identiska med de steg som utförs för klassificering, förutom typ av modell och typ av förutsagd data – som nu kommer att vara kontinuerliga värden – det finns bara en skillnad i dataförberedelsen.

Eftersom regression görs för numeriska värden – låt oss välja ett numeriskt värde från datamängden. Vi har sett att blodsockret var viktigt i klassificeringen, så det borde vara förutsägbart baserat på andra egenskaper (eftersom om det korrelerar med någon funktion, korrelerar den funktionen också med den).

Efter vad vi har gjort för klassificering, låt oss först importera biblioteken och samma datauppsättning. Om du redan har gjort detta för klassificeringsmodellen kan du hoppa över denna del och gå direkt till att förbereda data för träning.

Importera bibliotek och data
import pandas as pd
import numpy as np
import maplotlib.pyplot as plt
import seaborn as sns

dataset = pd.read_csv("../../datasets/random-forest/maternal_health_risk.csv")
Dataförbehandling för regression

Detta är en regressionsuppgift, så istället för att förutsäga klasser kan vi förutsäga en av de numeriska kolumnerna i datamängden. I det här exemplet är BS kolumnen kommer att förutsägas. Detta betyder y data kommer att innehålla blodsockerdataoch X data kommer att innehålla alla funktioner förutom blodsocker. Efter att ha separerat X och y data kan vi dela upp tåget och testset:

from sklearn.model_selection import train_test_split

SEED = 42

y = dataset['BS']
X = dataset.drop(['BS'], axis=1) 

X_train, X_test, y_train, y_test = train_test_split(X, y, 
                                                    test_size=0.2, 
                                                    random_state=SEED)
Utbildning av en RandomForestRegressor

Nu när vi har skalat vår datauppsättning är det dags att träna vår algoritm för att lösa detta regressionsproblem, att ändra det lite – vi skapar en modell med 20 träd i skogen och var och en med 4 nivåer. För att göra det kan du köra följande kod:

from sklearn.ensemble import RandomForestRegressor

rfr = RandomForestRegressor(n_estimators=20, 
                            max_depth=3, 
                            random_state=SEED)

rfr.fit(X_train, y_train)
y_pred = rfr.predict(X_test)

Du kan hitta detaljer för alla parametrar för RandomForestRegressor i den officiella dokumentationen.

Eftersom att plotta och titta på 20 träd skulle kräva lite tid och engagemang, kan vi rita bara det första för att ta en titt på hur det skiljer sig från klassificeringsträdet:

from sklearn import tree

features = X.columns

first_tree = rfr.estimators_[0]

plt.figure(figsize=(15,6))
tree.plot_tree(first_tree,
               feature_names=features,
               fontsize=8, 
               filled=True, 
               rounded=True);

Definitiv guide till Random Forest Algorithm med Python och Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Lägg märke till att regressionsträdet redan har ett värde tilldelat data som faller på varje nod. Det är de värden som kommer att beräknas i medeltal när de 20 träden kombineras. Efter vad vi har gjort med klassificering kan du också plotta funktionsviktigheter för att se vilka variabler regressionsmodellen tar mer hänsyn till vid beräkning av värden.

Det är dags att gå vidare till det sista och sista steget när du ska lösa ett maskininlärningsproblem och utvärdera algoritmens prestanda!

Utvärdera en RandomForestRegressor

För regressionsproblem är de mätvärden som används för att utvärdera en algoritm medelvärde absolut fel (MAE), medelkvadratfel (MSE) och rotmedelkvadratfel (RMSE).

  1. Genomsnittligt absolut fel (MAE): när vi subtraherar de förutsagda värdena från de faktiska värdena, erhåller felen, summerar vi de absoluta värdena för dessa fel och får deras medelvärde. Detta mått ger en uppfattning om det totala felet för varje förutsägelse av modellen, ju mindre (närmare 0) desto bättre.

$$
mae = (frac{1}{n})sum_{i=1}^{n}vänster | Faktisk – Förutspått rätt |
$$

Notera: Du kan också stöta på y och ŷ notation i ekvationerna. De y hänvisar till de faktiska värdena och ŷ till de förutsagda värdena.

  1. Mean Squared Error (MSE): det liknar MAE-måttet, men det kvadrerar de absoluta värdena för felen. Dessutom, som med MAE, ju mindre, eller närmare 0, desto bättre. MSE-värdet är kvadratiskt för att göra stora fel ännu större. En sak att vara mycket uppmärksam på, det är att det vanligtvis är svårt att tolka på grund av storleken på dess värden och det faktum att de inte är i samma skala av data.

$$
mse = summa_{i=1}^{D}(Faktisk – förutspådd)^2
$$

  1. Root Mean Squared Error (RMSE): försöker lösa tolkningsproblemet som tagits upp med MSE genom att få kvadratroten av dess slutvärde, för att skala tillbaka det till samma enheter av data. Det är lättare att tolka och bra när vi behöver visa eller visa det faktiska värdet av datan med felet. Den visar hur mycket data kan variera, så om vi har ett RMSE på 4.35 kan vår modell göra ett fel antingen för att den lade till 4.35 till det faktiska värdet eller behövde 4.35 för att komma till det faktiska värdet. Ju närmare 0, desto bättre också.

$$
rmse = sqrt{ sum_{i=1}^{D}(Faktisk – förutspådd)^2}
$$

Vi kan använda vilken som helst av dessa tre mätvärden för att jämföra modeller (om vi behöver välja en). Vi kan också jämföra samma regressionsmodell med olika argumentvärden eller med olika data och sedan överväga utvärderingsmåtten. Detta är känt som hyperparameterinställning – justering av hyperparametrarna som påverkar en inlärningsalgoritm och observera resultaten.

När man väljer mellan modeller presterar de med de minsta felen oftast bättre. När man övervakar modeller, om mätvärdena blev sämre, var en tidigare version av modellen bättre, eller så var det någon betydande förändring i data för att modellen skulle prestera sämre än den presterade.

Du kan använda följande kod för att hitta dessa värden:

from sklearn.metrics import mean_absolute_error, mean_squared_error

print('Mean Absolute Error:', mean_absolute_error(y_test, y_pred))
print('Mean Squared Error:', mean_squared_error(y_test, y_pred))
print('Root Mean Squared Error:', np.sqrt(mean_squared_error(y_test, y_pred)))

Utgången ska vara:

Mean Absolute Error: 1.127893702896059
Mean Squared Error: 3.0802988503933326
Root Mean Squared Error: 1.755078018320933

Med 20 träd är rotmedelkvadratfelet 1.75 vilket är lågt, men trots det – genom att höja antalet träd och experimentera med de andra parametrarna kan detta fel förmodligen bli ännu mindre.

Fördelar med att använda Random Forest

Som med alla algoritmer finns det fördelar och nackdelar med att använda den. I de följande två avsnitten tar vi en titt på för- och nackdelar med att använda slumpmässig skog för klassificering och regression.

  1. Algoritmen för slumpmässig skog är inte partisk, eftersom det finns flera träd och varje träd tränas på en slumpmässig delmängd av data. I grund och botten förlitar sig den slumpmässiga skogsalgoritmen på kraften hos "massan"; därför reduceras den totala graden av bias för algoritmen.
  2. Denna algoritm är mycket stabil. Även om en ny datapunkt introduceras i datasetet påverkas inte den övergripande algoritmen särskilt mycket eftersom ny data kan påverka ett träd, men det är väldigt svårt för det att påverka alla träden.
  3. Den slumpmässiga skogsalgoritmen fungerar bra när du har både kategoriska och numeriska egenskaper.
  4. Den slumpmässiga skogsalgoritmen fungerar också bra när data saknar värden eller inte har skalats.

Nackdelar med att använda Random Forest

  1. Den största nackdelen med slumpmässiga skogar ligger i deras komplexitet. De kräver mycket mer beräkningsresurser, på grund av det stora antalet beslutsträd som är sammanfogade, när man tränar stora ensembler. Men – med modern hårdvara tar träning inte ens en stor slumpmässig skog mycket tid.

Gå vidare – Handhållet End-to-End-projekt

Din nyfikna natur gör att du vill gå längre? Vi rekommenderar att du kollar in vår Guidade projekt: “Hands-on husprisförutsägelse – maskininlärning i Python”.

Definitiv guide till Random Forest Algorithm med Python och Scikit-Learn PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

I det här guidade projektet – du lär dig hur du bygger kraftfulla traditionella maskininlärningsmodeller såväl som modeller för djupinlärning, använder Ensemble Learning och tränar meta-lärare för att förutsäga huspriser från en påse Scikit-Learn och Keras-modeller.

Med hjälp av Keras, API:et för djupinlärning byggt ovanpå Tensorflow, kommer vi att experimentera med arkitekturer, bygga en ensemble av staplade modeller och träna en meta-lärare neurala nätverk (nivå-1-modell) för att ta reda på priset på ett hus.

Djup inlärning är fantastiskt – men innan du tar till det, rekommenderas det att du också försöker lösa problemet med enklare tekniker, som med ytlig inlärning algoritmer. Vår baslinjeprestanda kommer att baseras på en Slumpmässig skogsregression algoritm. Dessutom – vi kommer att utforska att skapa ensembler av modeller genom Scikit-Learn via tekniker som t.ex säckväv och rösta.

Detta är ett projekt från slut till slut, och som alla maskininlärningsprojekt börjar vi med – med Utforskande dataanalys, Följt av Förbehandling av data och slutligen Bygga grunt och Modeller för djupinlärning för att passa de data vi har utforskat och rensat tidigare.

Tidsstämpel:

Mer från Stackabuse