聯合國在實現其可持續發展目標方面面臨的主要障礙之一是與自然災害作鬥爭,而造成巨大破壞的首要障礙是野火。
在讀到最近在美國科羅拉多州和澳大利亞各地發生的野火之後,我們想知道是否有一種方法可以提前預測這些災難,以便採取一些保護措施。
我們在Kaggle上找到了這個數據集,它包含了美國188萬場野火,我們使用PyTorch Lightning建立一個模型。閱讀後面的內容,一起來看看如何使用這個數據集建立一個可以預測野火強度的模型吧。
氣候變化與野火
聯合國可持續發展目標的重點是到2030年實現具體目標,其中涉及教育、貧困、氣候變化和海洋生物等問題。聯合國環境規劃署負責協調聯合國的環境活動,並協助發展中國家制定有利於環境的政策。
我們有10年時間來實現聯合國可持續發展倡議的目標。
一個繁榮的環境直接影響到聯合國制定的17個可持續發展目標,因此保護環境免受自然和人為災害是聯合國的主要議程之一。根據聯合國的各種報告,野火確實影響了氣候變化。隨著全球氣溫的升高,野火發生的可能性越來越大,它們對氣候變化產生了重大影響。
2019年,澳大利亞遭遇了歷史上最嚴重的火災之一,由於極端高溫季節,燒毀了約1800萬公頃的土地(相比之下,相當於加州一半的土地)。日益升高的溫度在森林和草原上造成了高度易燃的環境。同樣,亞馬遜森林在2019年也發生火災,導致2240000英畝的燒毀面積。最近加州的野火燒毀了4359517英畝的土地。
野火產生大量的二氧化碳和溫室氣體,這反過來又提高了全球溫度。火災的微粒被遠距離攜帶,造成空氣汙染。這些粒子也會沉積在雪上,導致對陽光的更高吸收。這種現象被稱為氣候反饋迴路,它會逐漸惡化氣候條件。
用PyTorch Lightning預報野火
不同行業做出了多種努力,利用歷史野火數據,並考察它們與天氣、旅遊等替代數據源的依賴性,建立預測火災發生和強度的模型。在這個文章中,我使用PyTorch Lightning構建了一個機器學習模型。火災強度的預測可以通過事先採取正確的補救措施來對抗火災的影響。
步驟1:連接到數據
從Kaggle下載數據後,我將其攝取到我的python環境中,並將其連接到jupyter筆記本界面。
conn = sqlite3.connect("FPA_FOD_20170508.sqlite")在閱讀了數據之後,我需要執行一些探索性的分析,以了解數據的特徵及其分布,如下所示。
步驟2:一些探索性的數據分析
了解野火在美國不同州的蔓延情況,我們可以看到全美五大野火規模。
df = pd.read_sql_query("SELECT SUM(FIRE_SIZE) AS SUM_FIRE_SIZE, State FROM Fires GROUP BY State;", conn)df = df.set_index("STATE")df[:5]
可視化野火統計數據。它也有助於可視化數據,了解每個州的野火數量。我們可以用圖形化的方式繪製數據,看看受影響最大的州。
不同州的野火規模
df["SUM_FIRE_SIZE"].sort_values(ascending=False)[:15].plot(kind="bar")
我們從中得知,AK的人數比其他受到嚴重影響的州高出一倍多。
我們可以試著分析過去幾年野火的數量是如何變化的。
不同年份的野火規模
df = pd.read_sql_query("SELECT SUM(FIRE_SIZE) AS SUM_FIRE_SIZE, FIRE_YEAR FROM Fires GROUP BY FIRE_YEAR;", conn)df.set_index("FIRE_YEAR").plot.bar()
我們看到在過去十年裡,野火的強度顯著增加。
在了解了數據所包含的內容之後,我們對火大小的異常值進行簡單的過濾。可以對異常值進行處理或縮放以對所有數據進行建模。為了簡單起見,我們只研究發生最多的野火類別。
步驟3:數據處理和訓練測試分割
根據火力大小對數據集進行劃分。
我們只考慮野火規模在2000到10000個單位之間的情況。
analyze_df = analyze_df[analyze_df.FIRE_SIZE > 2000]analyze_df = analyze_df[analyze_df.FIRE_SIZE < 10000]將數據集拆分。
首先,我們對數值和離散類變量進行數據轉換。對數值特徵進行數據縮放,同時對離散特徵進行標籤編碼。然後合併兩個特徵子集。
X = analyze_df.drop(columns=["FIRE_SIZE"])y = analyze_df["FIRE_SIZE"]X_numerical = X.select_dtypes(include=["float", "int"])fill_nan = lambda col: col.fillna(col.mean())X_numerical = X_numerical.apply(fill_nan)sc = StandardScaler()num_cols = X_numerical.columnsX_numerical = pd.DataFrame(sc.fit_transform(X_numerical), columns=num_cols)for col in X_categorical.columns: le = LabelEncoder() X_categorical[col] = le.fit_transform(X_categorical[col])X_numerical.reset_index(drop=True, inplace=True)X_categorical.reset_index(drop=True, inplace=True)X = pd.concat([X_numerical, X_categorical], axis=1)訓練測試集分割
現在我們將數據分成80%的train+val和20%的測試集。然後我們進一步將train+val分成80%的訓練和20%的驗證數據集。
X_train_val, X_test, y_train_val, y_test = train_test_split(X, y, test_size=0.2, random_state=42)X_train, X_val, y_train, y_val = train_test_split(X_train_val, y_train_val, test_size=0.2, random_state=42)步驟4:使用PyTorch Lightning構建模型(這裡只顯示了一個片段,請按照下面的連結獲取完整代碼)
在本節中,我們開始使用PyTorch Lightning構建一個簡單的回歸神經網絡模型。[2]
我從一個有17個輸入特徵的簡單體系結構開始,第一個隱藏層有64個神經元,第二個隱藏層有32個神經元,最後一個是回歸節點。PyTorch Lightning代碼分為不同的部分:模型、數據加載器、優化器和訓練驗證測試步驟。
class Regression(pl.LightningModule):### 模型 ### def __init__(self): super(Regression, self).__init__() self.fc1 = nn.Linear(17, 64) self.fc2 = nn.Linear(64, 32) self.fc3 = nn.Linear(32, 8) self.fc4= nn.Linear(8, 1) self.dropout=torch.nn.Dropout(0.2) self.training_losses = [] def forward(self, x): x = torch.sigmoid(self.fc1(x)) x = self.dropout(x) x = torch.sigmoid(self.fc2(x)) x = self.dropout(x) x = torch.sigmoid(self.fc3(x)) x = self.dropout(x) x = self.fc4(x) return x ### 訓練 ### # 問:訓練步驟應該是什麼樣的 # 定義訓練步驟 def training_step(self, batch, batch_idx): x, y = batch logits = self.forward(x) train_loss = mse_loss(logits, y) self.training_losses.append(train_loss) # 添加 return {'loss': train_loss}### 驗證 ### # 問:驗證步驟應該是什麼樣的 # 定義驗證步驟 def validation_step(self, batch, batch_idx): x, y = batch logits = self.forward(x) loss = mse_loss(logits, y) return {'val_loss': loss} # 定義validation_epoch_end def validation_epoch_end(self, outputs): avg_loss = torch.stack([x['val_loss'] for x in outputs]).mean() return {'avg_val_loss': avg_loss}### 測試 ### # 問:測試步驟應該是什麼樣的 # 定義測試步驟 def test_step(self, batch, batch_idx): x, y = batch logits = self.forward(x) loss = mse_loss(logits, y) predictions_pred.append(logits) predictions_actual.append(y) return {'test_loss': loss, 'logits': logits} # 定義test_epoch_end def test_epoch_end(self, outputs): avg_loss = torch.stack([x['test_loss'] for x in outputs]).mean() logs = {'test_loss': avg_loss} return {'avg_test_loss': avg_loss, 'log': logs, 'progress_bar': logs } ### The 優化器 ### # 問:我將使用什麼優化器? # 定義優化器函數:這裡我們使用隨機梯度下降 def configure_optimizers(self): return optim.SGD(self.parameters(), lr=l_rate)如果你有不同形狀的數據,或者你希望創建一個不同的模型體系結構,你只需在上面的函數中更改模型參數。你可以在上面的configure_optimizers函數中更改模型中使用的優化器。
### 數據加載器 ### class WildfireDataLoader(pl.LightningDataModule): # 問題:你希望如何將數據加載到模型中? # 為數據加載定義函數:訓練/驗證/測試 def train_dataloader(self): train_dataset = TensorDataset(torch.tensor(X_train.values).float(), torch.tensor(y_train.values).float()) train_loader = DataLoader(dataset = train_dataset, batch_size = 512) return train_loader def val_dataloader(self): validation_dataset = TensorDataset(torch.tensor(X_val.values).float(), torch.tensor(y_val.values).float()) validation_loader = DataLoader(dataset = validation_dataset, batch_size = 512) return validation_loader def test_dataloader(self): test_dataset = TensorDataset(torch.tensor(X_test.values).float(), torch.tensor(y_test.values).float()) test_loader = DataLoader(dataset = test_dataset, batch_size = 512) return test_loader步驟5:運行模型
在這裡,我們使用數據加載模塊運行Lightning模型,並根據數據擬合。
data_loader_module = WildfireDataLoader()model = Regression()trainer = Trainer(max_epochs = 200,data_loader_module ) trainer.fit(model, datamodule= data_loader_module)步驟6:模型的最終結果
我們發現,模型的均方誤差損失為0.2048,與Logistic回歸(blog中未包含的代碼)相比,這稍微好一些。
火災數據似乎有很大的偏差,大部分數據點的火災規模小於10個單位,其他數據點高達5萬個單位以上。數據的這種偏斜使得回歸問題很難解決。此外,數據集包含非常有限的變量。通過合併更多的特徵變量和其他數據源(如天氣數據),可以提高模型的性能。
其目的是演示使用Lightning框架構建高級機器學習模型的方法,因此並不代表最佳模型性能,而是提出一種採用數據驅動方法預測野火的方法。
參考文獻:
[1]https://towardsdatascience.com/predicting-california-wildfire-size-with-neural-networks-building-a-machine-learning-project-from-db0e57dce4c9
[2]https://github.com/shotleft/how-to-python/blob/master/How%20it%20works%20-%20Bike%20Share%20Regression%20PyTorch%20Lightning.ipynb
[3]https://www.techrepublic.com/article/fighting-fire-with-ai-using-deep-learning-to-help-predict-wildfires-in-the-us/