חיזוי שריפת יער באמצעות Machine Learning

צומת המקור: 1194873

מה כולל המאמר הזה?

יער, שיח או שריפה צמחונית, ניתן לתאר ככל שריפה או שריפה בלתי מבוקרת ולא קבועה של צמחים בסביבה טבעית כגון יער, שטח עשב וכו'. במאמר זה איננו קובעים אם תתרחש שריפת יער. או לא, אנחנו חוזים את הביטחון של שריפת היער על סמך כמה תכונות.

חיזוי שריפות יער באמצעות ML
תמונה 1

למה אנחנו צריכים מודל חיזוי שריפות יער?

ובכן, נשאלת השאלה הראשונה כי למה אנחנו בכלל צריכים למידת מכונה כדי לחזות שריפות יער באזור המסוים הזה? אז, כן, השאלה נכונה שלמרות שיש מחלקת היערות המנוסה שעוסקת בנושאים אלו כבר זמן רב מדוע יש צורך ב-ML, לאחר שאמרתי שהתשובה היא די פשוטה שמחלקת היערות המנוסה יכולה לבדוק ב-3- 4 פרמטרים מהמוח האנושי שלהם אבל ML מצד שני יכול להתמודד עם הפרמטרים הרבים בין אם זה יכול להיות קו רוחב, קו אורך, לוויין, גרסה ומה לא, אז התמודדות עם הקשר הרב הזה של פרמטר שאחראי לשריפה ביער אנחנו צריכים ML בוודאות!

תוכן ענינים

  1. ייבוא ​​ספריות נחוצות
  2. ניתוח נתוני חקר
  3. ניקוי נתונים
  4. פיתוח מודלים (RandomForestRegressor)
  5. כוונון הדגם (RandomSearchCV)
  6. מודול bz2 (בונוס גדול)

ייבוא ​​ספריות

ייבוא ​​תאריך ושעה כ-dt ייבוא ​​פנדות כ-pd ייבוא ​​numpy כ-np ייבוא ​​seaborn כ-sns ייבוא ​​matplotlib.pyplot כ-plt %matplotlib בשורה מ-sklearn.model_selection ייבוא ​​train_test_split מ-sklearn.metrics ייבוא ​​מדויק_ציון, classification_report מ-sklearn.forestRegressor ייבוא ​​אקראי

קריאת מערך נתונים של חיפוש שריפות יער (.csv)

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

בואו נסתכל על מערך הנתונים שלנו (2.7+ MB)

forest.head()

פלט:

קריאת מערך הנתונים לחיזוי שריפות יער

חקר נתונים

יער.צורה

פלט:

(36011, 15)

כאן אנחנו יכולים לראות שיש לנו שורות 36011 ו עמודות 15 במערך הנתונים שלנו כמובן, אנחנו צריכים לעשות הרבה ניקוי נתונים אבל קודם

בואו לחקור את מערך הנתונים הזה יותר

יער.עמודות

פלט:

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

בודק את ערכי האפס במערך החיזוי של שריפות יער

forest.isnull().sum()

פלט:

קו רוחב 0 קו אורך 0 בהירות 0 סריקה 0 רצועה 0 acq_date 0 acq_time 0 לוויין 0 מכשיר 0 ביטחון 0 גרסה 0 bright_t31 0 frp 0 daynight 0 סוג 0 dtype: int64

למרבה המזל, אין לנו ערכי null במערך הנתונים הזה

forest.describe()

פלט:

תיאור מערך הנתונים
plt.figure(figsize=(10, 10)) sns.heatmap(forest.corr(),annot=True,cmap='viridis',linewidths=.5)

פלט:

מפת חום עבור מערך הנתונים

ניקוי נתונים

forest = forest.drop(['track'], axis = 1)

כאן אנו שומטים את עמודת המסלול

הערה: אגב ממאגר הנתונים אנחנו לא מוצאים אם שריפת היער מתרחשת או לא, אנחנו מנסים למצוא את הביטחון של שריפת היער מתרחשת. אולי נראה שהם אותו הדבר אבל יש הבדל קטן מאוד ביניהם, נסו למצוא את זה 🙂

מציאת נתונים קטגוריים

print("עמודת הסריקה") print(forest['scan'].value_counts()) print() print("עמודת aqc_time") print(forest['acq_time'].value_counts()) print() print( "עמודת הלוויין") print(forest['satellite'].value_counts()) print() print("עמודת המכשיר") print(forest['instrument'].value_counts()) print() print("The version column") print(forest['version'].value_counts()) print() print("עמודת הלילה") print(forest['daynight'].value_counts()) print()

פלט:

עמודת הסריקה 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 שם: scan, dtype: int4.2 העמודה aqc_time 108 4.0 103 4.4 100 4.8 70 64 506 851 ... 454 631 122 612 423 574 448 563 1558 1 שם: acq_time, אורך: 635, dtype: int1 עמודת הלוויין Aqua 1153 Terra 1 שם: לוויין, dtype: int302 עמודת המכשיר, MOD1type: 1519 המכשיר1type: int662 עמודת הגרסה 64 20541 שם: גרסה, dtype: int15470 עמודת הלילה D 64 N 36011 שם: daynight, dtype: int64

מהנתונים לעיל, אנו יכולים לראות שבעמודות מסוימות יש רק ערך אחד שחוזר בהם, כלומר הם אינם בעלי ערך עבורנו
אז נוריד אותם לגמרי.
כך בלבד הלוויין ו יום לילה עמודות הן היחידות סוג קטגורי.

אחרי שאמרנו את זה, אנחנו אפילו יכולים להשתמש ב- סריקה עמודה כדי לבנות אותו מחדש ל-a סוג נתונים קטגורי עמודה. מה שנעשה בעוד זמן מה.

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

פלט:

מסתכל על ראש הנתונים עבור חיזוי שריפות יער
daynight_map = {"D": 1, "N": 0} satellite_map = {"Terra": 1, "Aqua": 0} יער['daynight'] = יער['daynight'].map(daynight_map) forest[ 'satellite'] = יער['satellite'].map(satellite_map)
forest.head()

פלט:

הצגת השורות הראשוניות של מערך הנתונים

מסתכלים על סוג עמודה אחרת

forest['type'].value_counts()

פלט:

0 35666 2 335 3 10 שם: סוג, dtype: int64

שרשור מסגרת נתונים של יער וסוגים

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

פלט:

הצגת הנתונים לאחר שרשור מסגרת נתונים של יער וסוגים

שינוי שמות של עמודות להבנה טובה יותר

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

שיטת בנינג

  • עכשיו ציינתי שנמיר את עמודת הסריקה לסוג קטגורי, נעשה זאת באמצעות שיטת binning.
  • הטווח עבור עמודות אלו היה 1 עד 4.8
bins = [0, 1, 2, 3, 4, 5] תוויות = [1,2,3,4,5] יער['scan_binned'] = pd.cut(forest['scan'], bins=bins, תוויות=תוויות)
forest.head()

פלט:

יישום שיטת Binning

המרת סוג הנתונים ל-datetype מ מחרוזת או NumPy.

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

עכשיו נשאיר את סריקה עמוד וידית סוג תאריך נתונים - אנחנו יכולים לחלץ מידע שימושי מסוגי נתונים אלה בדיוק כמו שאנחנו עושים איתם נתונים קטגוריים.

forest = forest.drop(['scan'], axis = 1)

יצירת שנת עמודה חדשה בעזרת עמודת acq_date

forest['year'] = forest['acq_date'].dt.year forest.head()

פלט:

יצירת עמודה חדשה

כפי שהוספנו את עמודת השנה באופן דומה נוסיף החודש ו יְוֹם סקירה

forest['month'] = יער['acq_date'].dt.month forest['day'] = יער['acq_date'].dt.day

בודק שוב את צורת מערך הנתונים

יער.צורה

פלט:

(36011, 17)

כעת, כפי שאנו יכולים לראות שנוספו שתי עמודות נוספות שהן פירוט של עמודות תאריך

הפרדת משתנה היעד שלנו

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

בודק מתאם פעם נוספת

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

פלט:

בודק מתאם
תמונה מאת המחבר

בוא נראה את מערך הנתונים המנוקים והממוינים שלנו עכשיו

fin.head()

פלט:

צפייה בנתונים מנוקים וממוינים

פיצול הנתונים הנקיים למערך נתונים של הדרכה ובדיקה

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

בניית דגם

שימוש ב-RandomForestRegressor לבניית מודלים

random_model = RandomForestRegressor(n_estimators=300, random_state = 42, n_jobs = -1)
#Fit random_model.fit(Xtrain, ytrain) y_pred = random_model.predict(Xtest) #בדיקת הדיוק random_model_accuracy = round(random_model.score(Xtrain, ytrain)*100,2) print(round(random_model_accuracy, 2), '% ')

פלט:

95.32%

בודקים את הדיוק

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

פלט:

65.32%

שמירת הדגם על ידי מודול מלפפון חמוץ באמצעות הפורמט המסודר

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

כוונון דגם

  • הדיוק לא כל כך גדול, בנוסף הדגם מתאים יותר מדי
  • אז אנחנו משתמשים ב-RandomCV

קבלת כל הפרמטרים מהמודל

random_model.get_params()

פלט:

{'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': None, 'min_samples_leaf': 1, 'min_samples_split': 2, 'min_weight_fraction_leaf': 0.0, 'n_estimators': 300, 'n_jobs': -1, 'oob_random_score:' 42, 'verbose': 0, 'warm_start': False}

הפעלת RadomizedSearchCV!

""" n_estimators = מספר עצים ביער max_features = מספר מקסימלי של תכונות שנלקחו בחשבון לפיצול צומת max_depth = מספר רמות מקסימלי בכל עץ החלטות min_samples_split = מספר מינימלי של נקודות נתונים הממוקמות בצומת לפני פיצול הצומת min_samples_leaf = מספר מינימלי של נקודות נתונים מותרות ב-bootstrap של צומת עלים = שיטה לדגימת נקודות נתונים (עם או בלי החלפה) """
מאת sklearn.model_selection ייבוא ​​RandomizedSearchCV
מספר העצים ביער אקראי
n_estimators = [int(x) עבור x ב-np.linspace(start = 300, stop = 500, num = 20)]
מספר תכונות שיש לקחת בחשבון בכל פיצול
max_features = ['auto', 'sqrt']
מספר מרבי של רמות בעץ
max_depth = [int(x) עבור x ב-np.linspace(15, 35, num = 7)] max_depth.append(None)
מספר מינימלי של דגימות הנדרש לפיצול צומת
min_samples_split = [2, 3, 5]
מספר מינימלי של דגימות הנדרש בכל צומת עלה
min_samples_leaf = [1, 2, 4]
צור את הרשת האקראית
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)(

פלט:

{'n_estimators': [300, 310, 321, 331, 342, 352, 363, 373, 384, 394, 405, 415, 426, 436, 447, 457, 468, 478'ס, 489_max, 500', : ['auto', 'sqrt'], 'max_depth': [15, 18, 21, 25, 28, 31, 35, None], 'min_samples_split': [2, 3, 5], 'min_samples_leaf': [ 1, 2, 4]}
  • חיפוש אקראי של פרמטרים, באמצעות אימות צולב פי 3, חפש ב-100 שילובים שונים והשתמש בכל הליבות הזמינות
  • n_iter, ששולט במספר השילובים השונים שיש לנסות, ו-cv שהוא מספר הקיפולים לשימוש לצורך אימות צולב
rf_random = RandomizedSearchCV(estimator = random_model, param_distributions = random_grid, n_iter = 50, cv = 3, verbose=2, random_state=42) # התאם למודל החיפוש האקראי rf_random.fit(Xtrain, ytrain)

פלט:

פלט של המודל שלנו לחיזוי שריפות יער

בדיוק כמו הקטע הזה, יהיו קפלים רבים ב-RandomizedSearchCV זה

להוציא מזה את הפרמטר הטוב ביותר

rf_random.best_params_

פלט:

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

יצירת דגם חדש עם פרמטרים מכוונים

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, yttrain)
y_pred1 = random_new.predict(Xtest)
#בדיקת הדיוק random_model_accuracy1 = round(random_new.score(Xtrain, ytrain)*100,2) print(round(random_model_accuracy1, 2), '%')

פלט:

95.31%

בודקים את הדיוק

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

פלט:

67.39%

שמירת הדגם המכוונן על ידי מודול מלפפון חמוץ באמצעות הפורמט הסדרתי

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

טוען את הדגם הכבוש המכוון

reg_from_pickle = pickle.load(saved_model)

bz2file

הנה מגיע החלק הדובדבן על העוגה (בונוס של מאמר זה). בואו נבין על מה מודול bz2file זה. בואו נתחיל!

מה זה bz2file

bz2file הוא אחד המודולים ב-python שאחראים על דחיסה ופירוק של קבצים, ומכאן שהוא יכול לעזור בהקטנת הקובץ המסודר או הדה-סריאלי לגודל קטן יותר מה שיעזור מאוד בטווח הארוך כשיש לנו מערכי נתונים גדולים

איך bz2file מועיל כאן?

מכיוון שאנו יודעים כי מערך הנתונים שלנו הוא 2.7+ MB ומודל היער האקראי שלנו הוא 700+ MB, אז אנחנו צריכים לדחוס את זה כדי שהמודל הזה לא יוביל כמצב קדחתני לאחסון.

כיצד להתקין bz2file?

  • מחברת Jupyter: !pip התקן את bz2file
  • הודעת אנקונדה/CMD: pip להתקין bz2file

לפיכך התקנתי את bz2file, המשמש לדחיסת נתונים. זוהי חבילה מצילת חיים עבור אלה שיש להם שטחים מועטים בדיסק שלהם אך רוצים לאחסן או להשתמש בערכות נתונים גדולות. עכשיו נגמר הקובץ הכבוש 700 MB בגודל שבשימוש bz2 נדחס לקובץ בגודל 93 מגה בייט או פחות.

import bz2 compressionLevel = 9 source_file = 'ForestModel.pickle' # קובץ זה יכול להיות בפורמט אחר, כמו .csv או אחרים... destination_file = 'ForestModel.bz2' עם open(source_file, 'rb') כנתונים: tarbz2contents = bz2.compress(data.read(), compressionLevel) fh = open(destination_file, "wb") fh.write(tarbz2contents) fh.close()

קוד זה ידכא את הגודל של דגם החמוצים המכוונים.

אוקיי אז זה עטיפה מהצד שלי!

הערות סיום

תודה שקראת את המאמר שלי 🙂

אני מקווה שתאהבו את הלמידה המפורטת הזו של חיזוי שריפות יער באמצעות למידת מכונה. דבר אחרון שאני רוצה להזכיר הוא שאני מודע היטב לעובדה שהדיוק של המודל לא כל כך טוב אבל מטרת המאמר די מאוזנת אז אתם יכולים לנסות אלגוריתמים שונים של Ml כדי לחפש דיוק טוב יותר .

הנה המאגר קישור למאמר זה.

כאן אתה יכול לגשת למאמרים האחרים שלי שמתפרסמים ב-Analytics Vidhya כחלק מהבלוגאתון (קישור)

אם יש לך שאילתות אתה יכול ליצור איתי קשר בלינקדאין, עיין בזה קישור

עליי

שלום לכולם, אני כרגע עובד in TCS ובעבר עבדתי כאנליסט עמית למדעי נתונים in זורבה ייעוץ בהודו. יחד עם עבודה במשרה מלאה, יש לי עניין עצום באותו תחום, כלומר Data Science יחד עם תת-הקבוצות האחרות של בינה מלאכותית כגון, ראיית מחשב, למידת מכונה ולמידה עמוקה, אל תהסס לשתף איתי פעולה בכל פרויקט בדומיינים הנ"ל (לינקדין).

מקור תמונה-

  1. תמונה 1 – https://www.theleader.info/wp-content/uploads/2017/08/forest-fire.jpg

המדיה המוצגת במאמר זה בנושא חיזוי שריפות יער אינה בבעלות Analytics Vidhya ונעשה בהם שימוש לפי שיקול דעתו של המחבר.

מקור: https://www.analyticsvidhya.com/blog/2021/10/forest-fire-prediction-using-machine-learning/

בול זמן:

עוד מ אנליטיקה וידיה