作者 | Aakanksha NS
來源 | Medium
編輯 | 代碼醫生團隊
使用表格數據進行深度學習的最簡單方法是通過fast-ai庫,它可以提供非常好的結果,但是對於試圖了解幕後實際情況的人來說,它可能有點抽象。因此在本文中,介紹了如何在Pytorch中針對多類分類問題構建簡單的深度學習模型來處理表格數據。
Pytorch是一個流行的開源機器庫。它像Python一樣易於使用和學習。使用PyTorch的其他一些優勢是其多GPU支持和自定義數據加載器。
代碼
https://jovian.ml/aakanksha-ns/shelter-outcome
數據集
https://www.kaggle.com/c/shelter-animal-outcomes/data
它是一個表格數據集,由訓練集中的約26k行和10列組成。除以外的所有列DateTime都是分類的。
問題陳述
根據保護動物的某些特徵(例如年齡,性別,膚色,品種),預測其結果。
有5種可能的結果:Return_to_owner, Euthanasia, Adoption, Transfer, Died。期望找到動物的結局屬於5類中每一種的概率。
數據預處理
儘管此步驟很大程度上取決於特定的數據和問題,但仍需要遵循兩個必要的步驟:
擺脫Nan價值觀:
Nan(不是數字)表示數據集中缺少值。該模型不接受Nan值,因此必須刪除或替換它們。
對於數字列,一種常見的處理這些值的方法是使用剩餘數據的0,均值,中位數,眾數或其他某種函數來估算它們。缺失值有時可能表示數據集中的基礎特徵,因此人們經常創建一個新的二進位列,該列與具有缺失值的列相對應,以記錄數據是否缺失。
對於分類列,Nan可以將值視為自己的類別!
標籤編碼所有分類列:
由於模型只能接受數字輸入,因此將所有分類元素都轉換為數字。這意味著使用數字代替使用字符串來表示類別。選擇用來表示列中任何類別的數字並不重要,因為稍後將使用分類嵌入來進一步編碼這些類別。這是標籤編碼的一個簡單示例:
使用了LabelEncoderscikit-learn庫中的類對分類列進行編碼。可以定義一個自定義類來執行此操作並跟蹤類別標籤,因為也需要它們對測試數據進行編碼。
標籤編碼目標:
如果目標具有字符串條目,還需要對目標進行標籤編碼。另外請確保維護一個字典,將編碼映射到原始值,因為將需要它來找出模型的最終輸出。
保護成果問題特有的數據處理:
除了上述步驟,還對示例問題進行了更多處理。
刪除了該AnimalID列,因為它是唯一的,不會對訓練有所幫助。
刪除了該OutcomeSubtype列,因為它是目標的一部分,但並沒有要求對其進行預測。
已刪除DateTime列,因為輸入記錄的確切時間戳似乎不是一項重要功能。實際上,首先嘗試將其拆分為單獨的月份和年份列,但後來意識到完全刪除該列會帶來更好的結果!
已刪除Name列,因為該列中的Nan值太多(缺少10k以上)。同樣,在確定動物的結局方面,這似乎不是一個非常重要的特徵。
注意:在NoteBook中,堆疊了train和test列,然後進行了預處理以避免基於測試集上的train set標籤進行標籤編碼(因為這將涉及維護編碼標籤到實際值的字典) 。可以在此處進行堆棧和處理,因為沒有數字列(因此無需進行插補),並且每列的類別數是固定的。實際上,絕對不能這樣做,因為它可能會將某些數據從測試/驗證集中洩漏到訓練數據中,並導致模型評估不準確。例如如果數字列中缺少值,例如age 並決定使用平均值來推算該平均值,則平均值應僅在訓練集合(而不是堆疊的訓練測試有效集合)上計算,並且該值也應用於推算驗證和測試集中的缺失值。
分類嵌入
分類嵌入與NLP中常用的詞嵌入非常相似。基本思想是在列中具有每個類別的固定長度矢量表示。這與單次編碼的不同之處在於,使用嵌入而不是使用稀疏矩陣,而是為每個類別獲得了一個密集矩陣,其中相似類別的值在嵌入空間中彼此接近。因此,此過程不僅節省了內存(因為具有太多類別的列的一鍵編碼實際上會炸毀輸入矩陣,而且它是非常稀疏的矩陣),而且還揭示了分類變量的內在屬性。
例如,如果有一列顏色,並且找到了它的嵌入,則可以期望red並且pink在嵌入空間中,該距離比red和更近。blue
分類嵌入層等效於每個單編碼輸入上方的額外層:
對於保護所結果問題,只有分類列,但將考慮少於3個值的列為連續列。為了確定每一列嵌入向量的長度,從fast-ai庫中獲取了一個簡單的函數:
emb_c = {n: len(col.cat.categories) for n,col in X.items() if len(col.cat.categories) > 2}emb_cols = emb_c.keys() emb_szs = [(c, min(50, (c+1)//2)) for _,c in emb_c.items()]Pytorch數據集和DataLoader
擴展了DatasetPytorch提供的(抽象)類,以便在訓練時更輕鬆地訪問數據集並有效使用DataLoader模塊來管理批次。這涉及根據特定數據集覆蓋__len__和__getitem__方法。
由於只需要嵌入分類列,因此將輸入分為兩部分:數字部分和分類部分。
class ShelterOutcomeDataset(Dataset): def __init__(self, X, Y, emb_cols): X = X.copy() self.X1 = X.loc[:,emb_cols].copy().values.astype(np.int64) self.X2 = X.drop(columns=emb_cols).copy().values.astype(np.float32) self.y = Y def __len__(self): return len(self.y) def __getitem__(self, idx): return self.X1[idx], self.X2[idx], self.y[idx]然後,選擇批處理大小,並將其與數據集一起饋入DataLoader。深度學習通常是分批進行的。DataLoader幫助在訓練之前有效地管理這些批次並重新整理數據。
train_ds = ShelterOutcomeDataset(X_train, y_train, emb_cols)valid_ds = ShelterOutcomeDataset(X_val, y_val, emb_cols) batch_size = 1000train_dl = DataLoader(train_ds, batch_size=batch_size,shuffle=True)valid_dl = DataLoader(valid_ds, batch_size=batch_size,shuffle=True)要進行健全性檢查,可以遍歷創建的DataLoader以查看每個批次:
模型
數據分為連續的和分類的部分。首先根據先前確定的大小將分類部分轉換為嵌入向量,然後將它們與連續部分連接起來,以饋送到網絡的其餘部分。這張照片演示了使用的模型:
class ShelterOutcomeModel(nn.Module): def __init__(self, embedding_sizes, n_cont): super().__init__() self.embeddings = nn.ModuleList([nn.Embedding(categories, size) for categories,size in embedding_sizes]) n_emb = sum(e.embedding_dim for e in self.embeddings) self.n_emb, self.n_cont = n_emb, n_cont self.lin1 = nn.Linear(self.n_emb + self.n_cont, 200) self.lin2 = nn.Linear(200, 70) self.lin3 = nn.Linear(70, 5) self.bn1 = nn.BatchNorm1d(self.n_cont) self.bn2 = nn.BatchNorm1d(200) self.bn3 = nn.BatchNorm1d(70) self.emb_drop = nn.Dropout(0.6) self.drops = nn.Dropout(0.3) def forward(self, x_cat, x_cont): x = [e(x_cat[:,i]) for i,e in enumerate(self.embeddings)] x = torch.cat(x, 1) x = self.emb_drop(x) x2 = self.bn1(x_cont) x = torch.cat([x, x2], 1) x = F.relu(self.lin1(x)) x = self.drops(x) x = self.bn2(x) x = F.relu(self.lin2(x)) x = self.drops(x) x = self.bn3(x) x = self.lin3(x) return x訓練
現在在訓練集上訓練模型。使用了Adam優化器來優化交叉熵損失。訓練非常簡單:遍歷每批,進行前向遍歷,計算梯度,進行梯度下降,並根據需要重複此過程。可以看一下NoteBook以了解代碼。
https://jovian.ml/aakanksha-ns/shelter-outcome
測試輸出
由於有興趣查找測試輸入的每個類別的概率,因此在模型輸出上應用Softmax函數。還進行了Kaggle提交,以查看此模型的性能如何:
僅進行了很少的功能工程和數據探索,並使用了非常基礎的深度學習架構,但模型完成了約50%的解決方案。這表明使用神經網絡對表格數據建模的這種方法非常強大!
推薦閱讀
使用CNN和PyTorch進行面部關鍵點檢測
點擊「閱讀原文」圖書配套資源