Waldbrandvorhersage mittels maschinellem Lernen

Quellknoten: 1194873

Was beinhaltet dieser Artikel?

Wald-, Busch- oder Pflanzenbrände können als jede unkontrollierte und nicht vorgeschriebene Verbrennung oder Verbrennung von Pflanzen in einer natürlichen Umgebung wie einem Wald, einer Wiese usw. beschrieben werden. In diesem Artikel ermitteln wir nicht, ob es zu einem Waldbrand kommt oder nicht, wir prognostizieren die Wahrscheinlichkeit des Waldbrandes anhand einiger Attribute.

Waldbrandvorhersage mit ML
Bild 1

Warum brauchen wir ein Waldbrandvorhersagemodell?

Nun stellt sich zunächst die Frage: Warum brauchen wir überhaupt maschinelles Lernen, um Waldbrände in diesem bestimmten Gebiet vorherzusagen? Also, ja, die Frage ist berechtigt: Obwohl es erfahrene Forstbehörden gibt, die sich seit langem mit diesen Problemen befassen, warum es einen Bedarf für ML gibt, ist die Antwort recht einfach, und die erfahrene Forstbehörde kann anhand von drei Punkten überprüfen: 3 Parameter aus ihrem menschlichen Verstand, aber ML hingegen kann mit den zahlreichen Parametern umgehen, sei es Breitengrad, Längengrad, Satellit, Version und so weiter, und so mit dieser Mehrfachbeziehung eines Parameters umgehen, der für den Waldbrand verantwortlich ist Wir brauchen auf jeden Fall ML!

Inhaltsverzeichnis

  1. Notwendige Bibliotheken importieren
  2. Explorative Datenanalyse
  3. Datenreinigung
  4. Modellentwicklung (RandomForestRegressor)
  5. Optimieren des Modells (RandomSearchCV)
  6. bz2-Modul (großer Bonus)

Bibliotheken importieren

Datum/Uhrzeit als dt importieren, Pandas als pd importieren
numpy als np importieren
Seaborn als SNS importieren
matplotlib.pyplot als plt importieren
%matplotlib inline aus sklearn.model_selection import train_test_split
aus sklearn.metrics Import Accuracy_Score, Classification_Report
aus sklearn.ensemble RandomForestRegressor importieren

Lesen des Waldbrandexplorationsdatensatzes (.csv)

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

Werfen wir einen Blick auf unseren Datensatz (2.7+ MB)

Forest.head()

Ausgang:

Lesen des Datensatzes zur Waldbrandvorhersage

Datenexploration

Waldform

Ausgang:

(36011, 15)

Hier können wir sehen, dass wir es getan haben 36011 Zahnreihen und 15 Spalten In unserem Datensatz müssen wir natürlich viel Datenbereinigung durchführen, aber zuerst

Lassen Sie uns diesen Datensatz genauer untersuchen

Forest.columns

Ausgang:

Index(['latitude', 'longitude', 'brightness', 'scan', 'track', 'acq_date', 'acq_time', 'satellite', 'instrument', 'confidence', 'version', 'bright_t31' , 'frp', 'daynight', 'type'], dtype='object')

Überprüfung auf Nullwerte im Datensatz zur Waldbrandvorhersage

Forest.isnull().sum()

Ausgang:

Breitengrad 0
Längengrad 0
Helligkeit 0
scannen 0
Spur 0
acq_date 0
acq_time 0
Satellit 0
Instrument 0
Vertrauen 0
Version 0
Bright_t31 0
frp 0
TagNacht 0
Geben Sie 0 ein
dtype: int64

Glücklicherweise haben wir in diesem Datensatz keine Nullwerte

Forest.describe()

Ausgang:

Beschreiben des Datensatzes
plt.figure(figsize=(10, 10)) sns.heatmap(forest.corr(),annot=True,cmap='viridis',linewidths=.5)

Ausgang:

Heatmap für den Datensatz

Datenreinigung

Forest = Forest.drop(['track'], Achse = 1)

Hier streichen wir die Gleisspalte

Hinweis: Aus dem Datensatz können wir übrigens nicht herausfinden, ob der Waldbrand stattfindet oder nicht, sondern wir versuchen, die Wahrscheinlichkeit zu ermitteln, dass der Waldbrand stattfindet. Sie scheinen zwar dasselbe zu sein, aber es gibt einen sehr kleinen Unterschied zwischen ihnen. Versuchen Sie, das herauszufinden 🙂

Kategoriale Daten finden

print("Die Scan-Spalte")
print(forest['scan'].value_counts())
drucken()
print("Die aqc_time-Spalte")
print(forest['acq_time'].value_counts())
drucken()
print("Die Satellitenspalte")
print(forest['satellite'].value_counts())
drucken()
print("Die Instrumentenspalte")
print(forest['instrument'].value_counts())
drucken()
print("Die Versionsspalte")
print(forest['version'].value_counts())
drucken()
print("Die Tag-Nacht-Spalte")
print(forest['daynight'].value_counts())
drucken()

Ausgang:

Die Scan-Spalte
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
Name: scan, dtype: int64 Die aqc_time-Spalte
506 851
454 631
122 612
423 574
448 563 ... 1558 1
635 1
1153 1
302 1
1519 1
Name: acq_time, Länge: 662, dtype: int64 Die Satellitenspalte
Aqua 20541
Terra 15470
Name: Satellit, dtype: int64 Die Instrumentenspalte
MODIS 36011
Name: instrument, dtype: int64 Die Versionsspalte
6.3 36011
Name: Version, Dtype: int64 Die Tag-Nacht-Spalte
D 28203
N 7808
Name: daynight, dtype: int64

Aus den obigen Daten können wir ersehen, dass einige Spalten gerade vorhanden sind ein Wert, der in ihnen wiederkehrt, was bedeutet, dass sie für uns nicht wertvoll sind
Deshalb werden wir sie ganz fallen lassen.
Also nur Satellit und Tag Nacht Spalten sind die einzigen kategorialer Typ.

Allerdings können wir sogar das verwenden Scan Spalte, um es in eine umzustrukturieren kategorialer Datentyp Spalte. Was wir gleich tun werden.

Forest = Forest.drop(['instrument', 'version'], axis = 1)
Forest.head()

Ausgang:

Schauen Sie sich den Kopf der Daten für die Waldbrandvorhersage an
daynight_map = {"D": 1, "N": 0}
satellite_map = {"Terra": 1, "Aqua": 0} Forest['daynight'] = Forest['daynight'].map(daynight_map)
Forest['Satellite'] = Forest['Satellite'].map(Satellite_map)
Forest.head()

Ausgang:

Anzeigen der ersten Zeilen des Datensatzes

Schauen Sie sich den Typ einer anderen Spalte an

Wald['Typ'].value_counts()

Ausgang:

0 35666
2 335
3 10
Name: Typ, Dtyp: int64

Verketten von Gesamtstruktur- und Typendatenrahmen

Typen = pd.get_dummies(forest['type'])
Wald = pd.concat([Wald, Typen], Achse=1)
Wald = Wald.drop(['Typ'], Achse = 1)
Forest.head()

Ausgang:

Anzeigen der Daten nach der Verkettung von Gesamtstruktur und Datenrahmentypen

Spalten zum besseren Verständnis umbenennen

Forest = Forest.rename(columns={0: 'type_0', 2: 'type_2', 3: 'type_3'})

Binning-Methode

  • Jetzt habe ich erwähnt, dass wir die Scan-Spalte in einen kategorialen Typ konvertieren werden. Wir werden dies mit dem tun Binning-Methode.
  • Der Bereich für diese Spalten lag zwischen 1 und 4.8
Behälter = [0, 1, 2, 3, 4, 5]
Etiketten = [1,2,3,4,5]
Forest['scan_binned'] = pd.cut(forest['scan'], bins=bins, labels=labels)
Forest.head()

Ausgang:

Anwenden der Binning-Methode

Konvertieren des Datentyps in einen Datumstyp von string oder NumPy.

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

Jetzt werden wir das fallen lassen Scan Säule und Griff Datumstyp Daten – wir können aus diesen Datentypen nützliche Informationen extrahieren, genau wie wir es mit tun kategoriale Daten.

Forest = Forest.drop(['scan'], Achse = 1)

Erstellen einer neuen Spalte „Jahr“ mit Hilfe der Spalte „acq_date“.

Wald['Jahr'] = Wald['acq_date'].dt.Jahr
Forest.head()

Ausgang:

Erstellen einer neuen Spalte

Da wir die Jahresspalte auf ähnliche Weise hinzugefügt haben, werden wir sie hinzufügen der Monat und Tag Überblick

Wald['Monat'] = Wald['acq_date'].dt.Monat
Forest['day'] = Forest['acq_date'].dt.day

Überprüfen Sie erneut die Form des Datensatzes

Waldform

Ausgang:

(36011, 17)

Wie wir nun sehen können, wurden zwei weitere Spalten hinzugefügt, die eine Aufschlüsselung der Datumsspalten darstellen

Trennen unserer Zielvariablen

y = Wald['Vertrauen']
fin = Forest.drop(['confidence', 'acq_date', 'acq_time', 'bright_t31', 'type_0'], axis = 1)

Noch einmal auf Korrelation prüfen

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

Ausgang:

Auf Korrelation prüfen
Bild vom Autor

Sehen wir uns jetzt unseren bereinigten und sortierten Datensatz an

fin.head()

Ausgang:

Anzeigen bereinigter und sortierter Daten

Aufteilen der sauberen Daten in Trainings- und Testdatensätze

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

Modellbau

Verwendung von RandomForestRegressor für die Modellerstellung

random_model = RandomForestRegressor(n_estimators=300, random_state = 42, n_jobs = -1)
#Fit
random_model.fit(Xtrain, ytrain) y_pred = random_model.predict(Xtest) #Prüfung der Genauigkeit
random_model_accuracy = Round(random_model.score(Xtrain, ytrain)*100,2)
print(round(random_model_accuracy, 2), '%')

Ausgang:

95.32%

Überprüfung der Genauigkeit

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

Ausgang:

65.32%

Speichern des Modells durch Pickle-Modul im serialisierten Format

import pickle saving_model = pickle.dump(random_model, open('ForestModelOld.pickle','wb'))

Modelltuning

  • Die Genauigkeit ist nicht so hoch, außerdem ist das Modell überangepasst
  • Also verwenden wir RandomCV

Alle Parameter aus dem Modell abrufen

random_model.get_params()

Ausgang:

{'bootstrap': True, 'ccp_alpha': 0.0, 'criterion': 'mse', 'max_ Depth': None, 'max_features': 'auto', 'max_leaf_nodes': None, 'max_samples': None, 'min_impurity_decrease' : 0.0, 'min_impurity_split': Keine, '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, 'verbose': 0, 'warm_start': False}

RadomizedSearchCV in die Tat umsetzen!

„““
n_estimators = Anzahl der Bäume im Wald
max_features = maximale Anzahl von Features, die für die Aufteilung eines Knotens berücksichtigt werden
max_ Depth = maximale Anzahl von Ebenen in jedem Entscheidungsbaum
min_samples_split = Mindestanzahl der in einem Knoten platzierten Datenpunkte, bevor der Knoten geteilt wird
min_samples_leaf = Mindestanzahl zulässiger Datenpunkte in einem Blattknoten
Bootstrap = Methode zum Abtasten von Datenpunkten (mit oder ohne Ersatz) „““
aus sklearn.model_selection import RandomizedSearchCV
Anzahl der Bäume in einem zufälligen Wald
n_estimators = [int(x) für x in np.linspace(start = 300, stop = 500, num = 20)]
Anzahl der bei jeder Aufteilung zu berücksichtigenden Funktionen
max_features = ['auto', 'sqrt']
Maximale Anzahl von Ebenen im Baum
max_ Depth = [int(x) für x in np.linspace(15, 35, num = 7)]
max_length.append(Keine)
Mindestanzahl von Stichproben, die zum Teilen eines Knotens erforderlich sind
min_samples_split = [2, 3, 5]
Mindestanzahl an Proben, die an jedem Blattknoten erforderlich sind
min_samples_leaf = [1, 2, 4]
Erstellen Sie das Zufallsraster
random_grid = {'n_estimators': n_estimators, 'max_features': max_features, 'max_ Depth': max_ Depth, 'min_samples_split': min_samples_split, 'min_samples_leaf': min_samples_leaf, }
print(random_grid)

Ausgang:

{'n_estimators': [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_ Depth': [15, 18, 21, 25, 28, 31, 35, None], 'min_samples_split': [2, 3, 5], 'min_samples_leaf': [ 1, 2, 4]}
  • Eine zufällige Suche nach Parametern unter Verwendung einer dreifachen Kreuzvalidierung, Suche über 3 verschiedene Kombinationen und Nutzung aller verfügbaren Kerne
  • n_iter, der die Anzahl der verschiedenen auszuprobierenden Kombinationen steuert, und cv, der die Anzahl der für die Kreuzvalidierung zu verwendenden Faltungen angibt
rf_random = RandomizedSearchCV(estimator = random_model, param_distributions = random_grid, n_iter = 50, cv = 3, verbose=2, random_state=42)
# Passen Sie das Zufallssuchmodell an
rf_random.fit(Xtrain, ytrain)

Ausgang:

Ausgabe unseres Modells zur Waldbrandvorhersage

Genau wie dieser Ausschnitt wird es einen geben zahlreiche Falten in diesem RandomizedSearchCV

Den besten Parameter herausholen

rf_random.best_params_

Ausgang:

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

Erstellen eines neuen Modells mit abgestimmten Parametern

random_new = RandomForestRegressor(n_estimators = 394, min_samples_split = 2, min_samples_leaf = 1, max_features = 'sqrt', max_ Depth = 25, Bootstrap = True)
#Fit random_new.fit(Xtrain, ytrain)
y_pred1 = random_new.predict(Xtest)
#Prüfung der Genauigkeit
random_model_accuracy1 = Round(random_new.score(Xtrain, ytrain)*100,2)
print(round(random_model_accuracy1, 2), '%')

Ausgang:

95.31%

Überprüfung der Genauigkeit

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

Ausgang:

67.39%

Speichern des abgestimmten Modells durch das Pickle-Modul im serialisierten Format

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

Laden des abgestimmten eingelegten Modells

reg_from_pickle = pickle.load(saved_model)

bz2file

Hier kommt das Sahnehäubchen (Bonus dieses Artikels). Lassen Sie uns verstehen, worum es bei diesem bz2file-Modul geht. Lass uns anfangen!

Was ist bz2file

bz2file ist eines der Module in Python, die für die Komprimierung und Dekomprimierung von Dateien verantwortlich sind. Daher kann es dabei helfen, die serialisierte oder deserialisierte Datei auf eine kleinere Größe zu verkleinern, was auf lange Sicht bei großen Datenmengen sehr hilfreich sein wird

Wie hilfreich ist bz2file hier?

Da wir wissen, dass unser Datensatz mehr als 2.7 MB groß ist und unser Random-Forest-Modell mehr als 700 MB groß ist, müssen wir ihn komprimieren, damit dieses Modell nicht zu einer hektischen Speichersituation führt.

Wie installiere ich bz2file?

  • Jupyter-Notizbuch: !pip bz2file installieren
  • Anaconda-Eingabeaufforderung/CMD: pip installiere bz2file

Daher habe ich bz2file installiert, das zum Komprimieren von Daten verwendet wird. Dies ist ein lebensrettendes Paket für diejenigen, die wenig Speicherplatz auf ihrer Festplatte haben, aber große Datensätze speichern oder verwenden möchten. Jetzt war die eingelegte Feile vorbei 700 MB in der Größe, die bei Verwendung von bz2 in eine Datei der Größe komprimiert wird 93 MB oder weniger.

bz2-Kompressionsstufe importieren = 9
source_file = 'ForestModel.pickle' # Diese Datei kann in einem anderen Format vorliegen, z. B. .csv oder einem anderen ...
Destination_file = 'ForestModel.bz2' mit open(source_file, 'rb') als Daten: tarbz2contents = bz2.compress(data.read(), compressLevel) fh = open(destination_file, "wb")
fh.write(tarbz2contents)
fh.close()

Dieser Code unterdrückt die Größe des abgestimmten Pickle-Modells.

Okay, das ist ein Fazit von meiner Seite!

Endnoten

Vielen Dank, dass Sie meinen Artikel gelesen haben 🙂

Ich hoffe, dass euch diese Schritt-für-Schritt-Anleitung gefällt Waldbrandvorhersage durch maschinelles Lernen. Eine letzte Sache, die ich erwähnen möchte, ist, dass ich mir der Tatsache sehr wohl bewusst bin, dass die Genauigkeit des Modells nicht so gut ist, aber das Ziel des Artikels ist ziemlich ausgewogen, sodass Sie verschiedene Ml-Algorithmen ausprobieren können, um nach einer besseren Genauigkeit zu suchen .

Hier ist das Repo Link zu diesem Artikel.

Hier können Sie auf meine anderen Artikel zugreifen, die im Rahmen des Blogathons auf Analytics Vidhya veröffentlicht wurden (Link)

Wenn Sie Fragen haben, können Sie sich über LinkedIn mit mir in Verbindung setzen Link

Über mich

Grüße an alle, ich arbeite gerade in TCS und davor habe ich als Data Science Associate Analyst gearbeitet in Zorba Consulting Indien. Neben meiner Vollzeitbeschäftigung interessiere ich mich sehr für denselben Bereich, d. h. Data Science und seine anderen Teilbereiche der künstlichen Intelligenz wie Computer Vision, maschinelles Lernen und Deep Learning. Sie können gerne bei jedem Projekt mit mir zusammenarbeiten auf den oben genannten Domains ( LinkedIn).

Bildquelle-

  1. Bild 1 – https://www.theleader.info/wp-content/uploads/2017/08/forest-fire.jpg

Die in diesem Artikel zur Waldbrandvorhersage gezeigten Medien sind nicht Eigentum von Analytics Vidhya und werden nach Ermessen des Autors verwendet.

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

Zeitstempel:

Mehr von Analytics-Vidhya