Bosbrandvoorspelling met behulp van Machine Learning

Bronknooppunt: 1194873

Wat houdt dit artikel in?

Bos-, struik- of vegetarische brand kan worden omschreven als elke ongecontroleerde en niet-voorgeschreven verbranding of verbranding van planten in een natuurlijke omgeving zoals een bos, grasland, enz. In dit artikel bepalen we niet of er een bosbrand zal plaatsvinden. Of niet, we voorspellen de zekerheid van een bosbrand op basis van enkele kenmerken.

Bosbrandvoorspelling met behulp van ML
Afbeelding 1

Waarom hebben we een bosbrandvoorspellingsmodel nodig?

De eerste vraag rijst: waarom hebben we eigenlijk machinaal leren nodig om bosbranden in dat specifieke gebied te voorspellen? Dus ja, de vraag is geldig, ondanks dat er een ervaren bosafdeling is die zich al heel lang met deze problemen bezighoudt, waarom is er dan behoefte aan ML? Dat gezegd zijnde is het antwoord vrij eenvoudig dat de ervaren bosafdeling kan controleren op 3- 4 parameters uit hun menselijke geest, maar ML kan daarentegen de talrijke parameters verwerken, of het nu breedtegraad, lengtegraad, satelliet, versie en wat dan ook kan zijn, dus omgaan met deze multi-relatie van een parameter die verantwoordelijk is voor de brand in het bos we hebben zeker ML nodig!

Inhoudsopgave

  1. Benodigde bibliotheken importeren
  2. Verkennende gegevensanalyse
  3. Gegevens opschonen
  4. Modelontwikkeling (RandomForestRegressor)
  5. Het model afstemmen (RandomSearchCV)
  6. bz2-module (grote bonus)

Bibliotheken importeren

importeer datetime als dt importeer panda's als pd
importeer numpy als np
import zeegeboren als sns
importeer matplotlib.pyplot als plt
%matplotlib inline uit sklearn.model_selection import train_test_split
van sklearn.metrics importeer nauwkeurigheid_score, classificatie_rapport
van sklearn.ensemble importeer RandomForestRegressor

Gegevensset voor onderzoek naar bosbranden lezen (.csv)

bos = pd.read_csv('fire_archive.csv')

Laten we eens kijken naar onze dataset (2.7+ MB)

bos.head()

Output:

De dataset voor bosbrandvoorspelling lezen

Gegevensverkenning

bosvorm

Output:

(36011, 15)

Hier kunnen we zien dat we dat hebben gedaan 36011 rijen en 15 kolommen in onze dataset moeten we uiteraard veel gegevens opschonen, maar eerst

Laten we deze dataset verder verkennen

bos.kolommen

Output:

Index(['breedtegraad', 'lengtegraad', 'helderheid', 'scan', 'track', 'acq_date', 'acq_time', 'satelliet', 'instrument', 'vertrouwen', 'versie', 'bright_t31' , 'frp', 'dagnacht', 'type'], dtype='object')

Controleren op nulwaarden in de gegevensset voor bosbrandvoorspellingen

bos.isnull().sum()

Output:

breedtegraad 0
lengtegraad 0
helderheid 0
scannen 0
spoor 0
acq_date 0
acq_tijd 0
satelliet 0
instrument 0
vertrouwen 0
versie 0
bright_t31 0
frp 0
dagnacht 0
typ 0
dtype: int64

Gelukkig hebben we geen nulwaarden in deze dataset

bos.describe()

Output:

De gegevensset beschrijven
plt.figure(figsize=(10, 10)) sns.heatmap(forest.corr(),annot=True,cmap='viridis',linewidths=.5)

Output:

Heatmap voor de gegevensset

Gegevens opschonen

bos = bos.drop(['spoor'], as = 1)

Hier laten we de trackkolom vallen

Opmerking: Uit de dataset kunnen we overigens niet opmaken of de bosbrand wel of niet plaatsvindt; we proberen het vertrouwen te achterhalen dat de bosbrand zal plaatsvinden. Ze lijken misschien hetzelfde, maar er is een heel klein verschil tussen hen, probeer dat te vinden ๐Ÿ™‚

Categorische gegevens vinden

print("De scankolom")
print(forest['scan'].value_counts())
afdrukken()
print("De aqc_time kolom")
print(forest['acq_time'].value_counts())
afdrukken()
print("De satellietkolom")
print(forest['satelliet'].value_counts())
afdrukken()
print("De instrumentenkolom")
print(bos['instrument'].value_counts())
afdrukken()
print("De versiekolom")
print(forest['versie'].value_counts())
afdrukken()
print("De dagnachtkolom")
print(bos['dagnacht'].value_counts())
afdrukken()

Output:

De scankolom
1.0 8284
1.1 6000
1.2 3021
1.3 2412
1.4 1848
1.5 1610
1.6 1451
1.7 1281
1.8 1041
1.9 847
2.0 707
2.2 691
2.1 649
2.3 608
2.5 468
2.4 433
2.8 422
3.0 402
2.7 366
2.9 361
2.6 347
3.1 259
3.2 244
3.6 219
3.4 203
3.3 203
3.8 189
3.9 156
4.7 149
4.3 137
3.5 134
3.7 134
4.1 120
4.6 118
4.5 116
4.2 108
4.0 103
4.4 100
4.8 70
Naam: scan, dtype: int64 De kolom aqc_time
506 851
454 631
122 612
423 574
448 563 ... 1558 1
635 1
1153 1
302 1
1519 1
Naam: acq_time, lengte: 662, dtype: int64 De satellietkolom
Aqua20541
Terra 15470
Naam: satelliet, dtype: int64 De instrumentenkolom
MODIS36011
Naam: instrument, dtype: int64 De versiekolom
6.3 36011
Naam: versie, dtype: int64 De dagnachtkolom
D28203
N 7808
Naam: dagnacht, dtype: int64

Uit de bovenstaande gegevens kunnen we zien dat sommige kolommen net รฉรฉn waarde die daarin terugkeert, wat betekent dat ze niet waardevol voor ons zijn
We laten ze dus helemaal vallen.
Alleen dus satelliet en dag nacht kolommen zijn de enige categorisch soort.

Dat gezegd hebbende, kunnen we zelfs de aftasten kolom om deze te herstructureren in een categorisch gegevenstype kolom. Wat we over een tijdje gaan doen.

forest = forest.drop(['instrument', 'versie'], as = 1)
bos.head()

Output:

Kijkend naar de kop van de gegevens voor het voorspellen van bosbranden
daynight_map = {"D": 1, "N": 0}
satelliet_map = {"Terra": 1, "Aqua": 0} bos['dagnacht'] = bos['dagnacht'].map(dagnacht_kaart)
bos['satelliet'] = bos['satelliet'].map(satelliet_kaart)
bos.head()

Output:

De eerste rijen van de gegevensset bekijken

Kijken naar het type van een andere kolom

bos['type'].value_counts()

Output:

0 35666
2 335
3 10
Naam: type, dtype: int64

Aaneengeschakeld bos en gegevensframe van typen

types = pd.get_dummies(forest['type'])
bos = pd.concat([bos, typen], as=1)
bos = bos.drop(['type'], as = 1)
bos.head()

Output:

De gegevens bekijken na het aaneenschakelen van forest en dataframetypen

De naam van kolommen wijzigen voor een beter begrip

forest = bos.hernoemen(columns={0: 'type_0', 2: 'type_2', 3: 'type_3'})

Binning-methode

  • Nu heb ik gezegd dat we de scankolom naar het categorische type zullen converteren, we zullen dit doen met behulp van de binning methode.
  • Het bereik voor deze kolommen was 1 tot 4.8
bakken = [0, 1, 2, 3, 4, 5]
labels = [1,2,3,4,5]
forest['scan_binned'] = pd.cut(forest['scan'], bins=bins, labels=labels)
bos.head()

Output:

Binning-methode toepassen

Het gegevenstype converteren naar datumtype van tekenreeks of NumPy.

bos['acq_date'] = pd.to_datetime(forest['acq_date'])

Nu laten we de aftasten kolom en handvat datumtype data โ€“ we kunnen nuttige informatie uit deze datatypen halen, net zoals we dat doen categorische data.

bos = bos.drop(['scan'], as = 1)

Een nieuw kolomjaar aanmaken met behulp van de kolom acq_date

bos['jaar'] = bos['acq_date'].dt.jaar
bos.head()

Output:

Een nieuwe kolom maken

Omdat we de jaarkolom op dezelfde manier hebben toegevoegd, zullen we deze toevoegen de maand en dag kolom

bos['maand'] = bos['acq_date'].dt.maand
bos['dag'] = bos['acq_date'].dt.dag

De vorm van de dataset opnieuw controleren

bosvorm

Output:

(36011, 17)

Zoals we nu kunnen zien, zijn er nog twee kolommen toegevoegd, die een uitsplitsing zijn van de datumkolommen

Onze doelvariabele scheiden

y = bos['vertrouwen']
fin = forest.drop(['vertrouwen', 'acq_date', 'acq_time', 'bright_t31', 'type_0'], as = 1)

Nog een keer gekeken naar correlatie

plt.figure(figsize=(10, 10)) sns.heatmap(fin.corr(),annot=True,cmap='viridis',linewidths=.5)

Output:

Controleren op correlatie
Afbeelding door auteur

Laten we nu onze opgeschoonde en gesorteerde dataset bekijken

fin.head()

Output:

Opgeschoonde en gesorteerde gegevens bekijken

Het opsplitsen van de schone gegevens in een trainings- en testdataset

Xtrain, Xtest, ytrain, ytest = train_test_split(fin.iloc[:, :500], y, test_size=0.2)

Model gebouw

RandomForestRegressor gebruiken voor het bouwen van modellen

random_model = RandomForestRegressor(n_estimators=300, willekeurige_status = 42, n_jobs = -1)
#Fit
random_model.fit(Xtrain, ytrain) y_pred = random_model.predict(Xtest) #De nauwkeurigheid controleren
willekeurige_model_nauwkeurigheid = round(random_model.score(Xtrain, ytrain)*100,2)
print(round(random_model_accuracy, 2), '%')

Output:

95.32%

De nauwkeurigheid controleren

random_model_accuracy1 = round(random_model.score(Xtest, ytest)*100,2) print(round(random_model_accuracy1, 2), '%')

Output:

65.32%

Het model opslaan per pickle-module met behulp van het geserialiseerde formaat

importeer augurk opgeslagen_model = pickle.dump(random_model, open('ForestModelOld.pickle','wb'))

Modelafstemming

  • De nauwkeurigheid is niet zo groot, en het model is overfitting
  • Daarom gebruiken we RandomCV

Alle parameters uit het model ophalen

willekeurig_model.get_params()

Output:

{'bootstrap': True, 'ccp_alpha': 0.0, 'criterion': 'mse', 'max_ Depth': Geen, 'max_features': 'auto', 'max_leaf_nodes': Geen, 'max_samples': Geen, 'min_impurity_decrease' : 0.0, 'min_impurity_split': Geen, 'min_samples_leaf': 1, 'min_samples_split': 2, 'min_weight_fraction_leaf': 0.0, 'n_estimators': 300, 'n_jobs': -1, 'oob_score': False, 'random_state': 42, 'uitgebreid': 0, 'warme_start': False}

RadomizedSearchCV in actie zetten!

"""
n_estimators = aantal bomen in het bos
max_features = maximaal aantal functies dat in aanmerking wordt genomen voor het splitsen van een knooppunt
max_diepte = maximaal aantal niveaus in elke beslissingsboom
min_samples_split = minimaal aantal gegevenspunten dat in een knooppunt is geplaatst voordat het knooppunt wordt gesplitst
min_samples_leaf = minimaal aantal toegestane gegevenspunten in een leaf-knooppunt
bootstrap = methode voor het bemonsteren van gegevenspunten (met of zonder vervanging) """
van sklearn.model_selection import RandomizedSearchCV
Aantal bomen in willekeurig bos
n_estimators = [int(x) voor x in np.linspace(start = 300, stop = 500, num = 20)]
Aantal functies waarmee u bij elke splitsing rekening moet houden
max_features = ['auto', 'sqrt']
Maximaal aantal niveaus in de boom
max_diepte = [int(x) voor x in np.linspace(15, 35, num = 7)]
max_diepte.append(Geen)
Minimumaantal monsters dat nodig is om een โ€‹โ€‹knooppunt te splitsen
min_samples_split = [2, 3, 5]
Minimaal aantal monsters vereist bij elk bladknooppunt
min_samples_leaf = [1, 2, 4]
Maak het willekeurige raster
random_grid = {'n_estimators': n_estimators, 'max_features': max_features, 'max_diepte': max_diepte, 'min_samples_split': min_samples_split, 'min_samples_leaf': min_samples_leaf, }
afdrukken(willekeurig_raster)

Output:

{'n_schatters': [300, 310, 321, 331, 342, 352, 363, 373, 384, 394, 405, 415, 426, 436, 447, 457, 468, 478, 489, 500], 'max_features' : ['auto', 'sqrt'], 'max_diepte': [15, 18, 21, 25, 28, 31, 35, Geen], 'min_samples_split': [2, 3, 5], 'min_samples_leaf': [ 1, 2, 4]}
  • Een willekeurige zoektocht naar parameters, met behulp van drievoudige kruisvalidatie, zoeken in 3 verschillende combinaties en gebruik van alle beschikbare kernen
  • n_iter, dat het aantal verschillende combinaties bepaalt dat moet worden geprobeerd, en cv, dat het aantal vouwen is dat moet worden gebruikt voor kruisvalidatie
rf_random = RandomizedSearchCV(schatter = willekeurig_model, param_distributies = willekeurig_raster, n_iter = 50, cv = 3, uitgebreid=2, willekeurige_status=42)
# Pas het willekeurige zoekmodel aan
rf_random.fit(Xtrain, ytrain)

Output:

Resultaten van ons model voor bosbrandvoorspelling

Net als dit fragment zal dat er zijn talrijke vouwen in dit RandomizedSearchCV

Haal er de beste parameter uit

rf_random.best_params_

Output:

{'n_estimators': 394, 'min_samples_split': 2, 'min_samples_leaf': 1, 'max_features': 'sqrt', 'max_diepte': 25}

Een nieuw model maken met afgestemde parameters

random_new = RandomForestRegressor(n_estimators = 394, min_samples_split = 2, min_samples_leaf = 1, max_features = 'sqrt', max_diepte = 25, bootstrap = True)
#Fit
willekeurige_nieuwe.fit(Xtrain, ytrain)
y_pred1 = willekeurig_nieuw.predict(Xtest)
#De nauwkeurigheid controleren
random_model_accuracy1 = round(random_new.score(Xtrain, ytrain)*100,2)
print(round(random_model_accuracy1, 2), '%')

Output:

95.31%

De nauwkeurigheid controleren

random_model_accuracy2 = round(random_new.score(Xtest, ytest)*100,2) print(round(random_model_accuracy2, 2), '%')

Output:

67.39%

Het afgestemde model opslaan via de pickle-module met behulp van het geserialiseerde formaat

opgeslagen_model = pickle.dump(random_new, open('ForestModel.pickle','wb'))

Het getunede ingelegde model laden

reg_from_pickle = augurk.load(saved_model)

bz2bestand

Hier komt de kers op de taart (bonus van dit artikel). Laten we begrijpen waar deze bz2file-module over gaat. Laten we beginnen!

Wat is bz2bestand

bz2file is een van de modules in Python die verantwoordelijk zijn voor de compressie en decompressie van bestanden, en kan daarom helpen bij het verkleinen van het geserialiseerde of gedeserialiseerde bestand naar een kleiner formaat, wat op de lange termijn zeer nuttig zal zijn als we grote datasets hebben

Hoe bz2file hier nuttig is?

Omdat we weten dat onze dataset 2.7+ MB is en ons Random forest-model maar liefst 700+ MB bedraagt, moeten we dat comprimeren zodat dat model niet leidend zal zijn als een hectische situatie voor opslag.

Hoe bz2file installeren?

  • Jupyter-notitieboekje: !pip installeer bz2bestand
  • Anaconda-prompt/CMD: pip installeer bz2bestand

Daarom heb ik bz2file geรฏnstalleerd, dat wordt gebruikt om gegevens te comprimeren. Dit is een levensreddend pakket voor degenen die weinig ruimte op hun schijf hebben, maar grote datasets willen opslaan of gebruiken. Nu was het ingelegde dossier voorbij 700 MB in grootte die bij gebruik bz2 comprimeerde tot een bestand van grootte 93 MB of minder.

importeer bz2 compressieniveau = 9
source_file = 'ForestModel.pickle' # dit bestand kan een ander formaat hebben, zoals .csv of andere...
Destination_file = 'ForestModel.bz2' met open(source_file, 'rb') als gegevens: tarbz2contents = bz2.compress(data.read(), compressieniveau) fh = open(destination_file, "wb")
fh.write(tarbz2inhoud)
fh.close()

Deze code onderdrukt de grootte van het afgestemde augurkmodel.

Okรฉ, dus dat is een omslag van mijn kant!

eindnoten

Bedankt voor het lezen van mijn artikel ๐Ÿ™‚

Ik hoop dat jullie dit stap-voor-stap leren leuk zullen vinden bosbrandvoorspelling met behulp van machine learning. Een laatste ding dat ik wil vermelden is dat ik me heel goed bewust ben van het feit dat de nauwkeurigheid van het model niet zo goed is, maar het doel van het artikel is redelijk evenwichtig, dus jullie kunnen verschillende Ml-algoritmen uitproberen om te zoeken naar een betere nauwkeurigheid .

Hier is de repo link bij dit artikel.

Hier heeft u toegang tot mijn andere artikelen die zijn gepubliceerd op Analytics Vidhya als onderdeel van de Blogathon (link)

Als u vragen heeft, kunt u contact met mij opnemen op LinkedIn, raadpleeg dit link

Over mij

Groeten aan iedereen, ik ben momenteel aan het werk in TCS en voorheen werkte ik als Data Science Associate Analyst in Zorba Consulting India. Naast mijn fulltime werk heb ik een enorme interesse in hetzelfde vakgebied, dat wil zeggen Data Science samen met de andere subsets van kunstmatige intelligentie, zoals Computer Vision, Machine Learning en Deep Learning. Voel je vrij om met mij samen te werken aan elk project op de bovengenoemde domeinen (LinkedIn).

Afbeeldingsbron-

  1. Afbeelding 1 โ€“ https://www.theleader.info/wp-content/uploads/2017/08/forest-fire.jpg

De in dit artikel getoonde media over het voorspellen van bosbranden zijn geen eigendom van Analytics Vidhya en worden naar goeddunken van de auteur gebruikt.

Bron: https://www.analyticsvidhya.com/blog/2021/10/forest-fire-prediction-using-machine-learning/

Tijdstempel:

Meer van Analytics Vidhya