天天看點

TabTransformer轉換器提升多層感覺機性能深度解析

TabTransformer轉換器提升多層感覺機性能深度解析

如今,轉換器(Transformers)成為大多數先進的自然語言處理(NLP)和計算機視覺(CV)體系結構中的關鍵子產品。然而,表格式資料領域仍然主要以梯度提升決策樹(GBDT)算法為主導。于是,有人試圖彌合這一差距。其中,第一篇基于轉換器的表格資料模組化論文是由Huang等人于2020年發表的論文《TabTransformer:使用上下文嵌入的表格資料模組化》。

本文旨在提供該論文内容的基本展示,同時将深入探讨TabTransformer模型的實作細節,并向您展示如何針對我們自己的資料來具體使用TabTransformer。

一、論文概述

上述論文的主要思想是,如果使用轉換器将正常的分類嵌入轉換為上下文嵌入,那麼,正常的多層感覺器(MLP)的性能将會得到顯著提高。接下來,讓我們更為深入地了解這一描述。

1.分類嵌入(Categorical Embeddings)

在深度學習模型中,使用分類特征的經典方法是訓練其嵌入性。這意味着,每個類别值都有一個唯一的密集型向量表示,并且可以傳遞給下一層。例如,由下圖您可以看到,每個分類特征都使用一個四維數組表示。然後,這些嵌入與數字特征串聯,并用作MLP的輸入。

TabTransformer轉換器提升多層感覺機性能深度解析

帶有分類嵌入的MLP

2.上下文嵌入(Contextual Embeddings)

論文作者認為,分類嵌入缺乏上下文含義,即它們并沒有對分類變量之間的任何互動和關系資訊進行編碼。為了将嵌入内容更加具體化,有人建議使用NLP領域目前所使用的轉換器來實作這一目的。

TabTransformer轉換器提升多層感覺機性能深度解析

TabTransformer轉換器中的上下文嵌入

為了以可視化方式形象地展示上述想法,我們不妨考慮下面這個訓練後得到的上下文嵌入圖像。其中,突出顯示了兩個分類特征:關系(黑色)和婚姻狀況(藍色)。這些特征是相關的;是以,“已婚(Married)”、“丈夫(Husband)”和“妻子(Wife)”的值應該在向量空間中彼此接近,即使它們來自不同的變量。

TabTransformer轉換器提升多層感覺機性能深度解析

經訓練後的TabTransformer轉換器嵌入結果示例

通過上圖中經過訓練的上下文嵌入結果,我們可以看到,“已婚(Married)”的婚姻狀況更接近“丈夫(Husband)”和“妻子(Wife)”的關系水準,而“未結婚(non-married)”的分類值則來自右側的單獨資料簇。這種類型的上下文使這樣的嵌入更加有用,而使用簡單形式的類别嵌入技術是不可能實作這種效果的。

3.TabTransformer架構

為了達到上述目的,論文作者提出了以下架構:

TabTransformer轉換器提升多層感覺機性能深度解析

TabTransformer轉換器架構示意圖(摘取自Huang等人2020年發表的論文)

我們可以将此體系結構分解為5個步驟:

  • 标準化數字特征并向前傳遞
  • 嵌入分類特征
  • 嵌入經過N次轉換器塊處理,以便獲得上下文嵌入
  • 把上下文分類嵌入與數字特征進行串聯
  • 通過MLP進行串聯獲得所需的預測

雖然模型架構非常簡單,但論文作者表示,添加轉換器層可以顯著提高計算性能。當然,所有的“魔術”發生在這些轉換器塊内部;是以,接下來讓我們更加詳細地研究一下其中的實作過程。

4.轉換器

TabTransformer轉換器提升多層感覺機性能深度解析

轉換器(Transformer)架構示意 (選自Vaswani等人于2017年發表的論文)

您可能以前見過轉換器架構,但為了快速介紹起見,請記住該轉換器是由編碼器和解碼器兩部分組成(見上圖)。對于TabTransformer,我們隻關心将輸入的嵌入内容上下文化的編碼器部分(解碼器部分将這些嵌入内容轉換為最終輸出結果)。但它到底是如何做到的呢?答案是——多頭注意力機制。

5.多頭注意力機制(Multi-head-attention)

引用我最喜歡的關于注意力機制的文章的描述,是這樣的:

“自我關注(self attention)背後的關鍵概念是,這種機制允許神經網絡學習如何在輸入序列的各個片段之間以最好的路由方案進行資訊排程。”

換句話說,自我關注(self-attention)有助于模型找出在表示某個單詞/類别時,輸入的哪些部分更重要,哪些部分相對不重要。為此,我強烈建議您閱讀一下上面引用的這篇文章,以便對自我關注為什麼如此有效有一個更為直覺的了解。

TabTransformer轉換器提升多層感覺機性能深度解析

多頭注意力機制 (選自Vaswani等人于2017年發表的論文)

注意力是通過3個學習過的矩陣來計算的——Q、K和V,它們代表查詢(Query)、鍵(Key)和值(Value)。首先,我們将矩陣Q和K相乘得到注意力矩陣。該矩陣被縮放并通過softmax層傳遞。然後,我們将其乘以V矩陣,得出最終值。為了更直覺地了解起見,請考慮下面的示意圖,它顯示了我們如何使用矩陣Q、K和V實作從輸入嵌入轉換到上下文嵌入。

TabTransformer轉換器提升多層感覺機性能深度解析

自我關注流程可視化

通過重複該過程h次(使用不同的Q、K、V矩陣),我們就能夠得到多個上下文嵌入,它們形成我們最終的多頭注意力。

6.簡短回顧

讓我們總結一下上面所介紹的内容:

  • 簡單的分類嵌入不包含上下文資訊
  • 通過轉換器編碼器傳遞分類嵌入,我們就能夠将嵌入上下文化
  • 轉換器部分能夠将嵌入上下文化,因為它使用了多頭注意力機制
  • 多頭注意力機制在編碼變量時使用矩陣Q、K和V來尋找有用的互相作用和相關性資訊
  • 在TabTransformer中,被上下文化的嵌入與數字輸入相串聯,并通過一個簡單的MLP輸出預測

雖然TabTransformer背後的想法很簡單,但您可能需要一些時間才能掌握注意力機制。是以,我強烈建議您重新閱讀以上解釋。如果您感到有些迷茫,請認真閱讀本文中所有建議的連結相關内容。我保證,做到這些後,您就不難搞明白注意力機制的原理了。

7.試驗結果展示

TabTransformer轉換器提升多層感覺機性能深度解析

結果資料(選自Huang等人2020年發表的論文)

根據報告的結果,TabTransformer轉換器優于所有其他深度學習表格模型,此外,它接近GBDT的性能水準,這非常令人鼓舞。該模型對缺失資料和噪聲資料也相對穩健,并且在半監督環境下優于其他模型。然而,這些資料集顯然不是詳盡無遺的,正如以後發表的一些相關論文所證明的那樣,仍有很大的改進空間。

二、建構我們自己的示例程式

現在,讓我們最終來确定一下如何将模型應用于我們自己的資料。接下來的示例資料取自著名的Tabular Playground Kaggle比賽。為了友善使用TabTransformer轉換器,我建立了一個tabtransformertf包。它可以使用如下pip指令進行安裝:

pip install tabtransformertf1.           

并允許我們使用該模型,而無需進行大量預處理。

1.資料預處理

第一步是設定适當的資料類型,并将我們的訓練和驗證資料轉換為TF資料集。其中,前面安裝的軟體包中就提供了一個很好的實用程式可以做到這一點。

from tabtransformertf.utils.preprocessing import df_to_dataset, build_categorical_prep

# 設定資料類型
train_data[CATEGORICAL_FEATURES] = train_data[CATEGORICAL_FEATURES].astype(str)
val_data[CATEGORICAL_FEATURES] = val_data[CATEGORICAL_FEATURES].astype(str)

train_data[NUMERIC_FEATURES] = train_data[NUMERIC_FEATURES].astype(float)
val_data[NUMERIC_FEATURES] = val_data[NUMERIC_FEATURES].astype(float)

# 轉換成TF資料集
train_dataset = df_to_dataset(train_data[FEATURES + [LABEL]], LABEL, batch_size=1024)
val_dataset = df_to_dataset(val_data[FEATURES + [LABEL]], LABEL, shuffle=False, batch_size=1024)1.2.3.4.5.6.7.8.9.10.11.12.           

下一步是為分類資料準備預處理層。該分類資料稍後将被傳遞給我們的主模型。

from tabtransformertf.utils.preprocessing import build_categorical_prep

category_prep_layers = build_categorical_prep(train_data, CATEGORICAL_FEATURES)

# 輸出結果是一個字典結構,其中鍵部分是特征名稱,值部分是StringLookup層
# category_prep_layers ->
# {'product_code': <keras.layers.preprocessing.string_lookup.StringLookup at 0x7f05d28ee4e0>,
#  'attribute_0': <keras.layers.preprocessing.string_lookup.StringLookup at 0x7f05ca4fb908>,
#  'attribute_1': <keras.layers.preprocessing.string_lookup.StringLookup at 0x7f05ca4da5f8>}1.2.3.4.5.6.7.8.9.           

這就是預處理!現在,我們可以開始構模組化型了。

2.建構TabTransformer模型

初始化模型很容易。其中,有幾個參數需要指定,但最重要的幾個參數是:embeding_dim、depth和heads。所有參數都是在超參數調整後選擇的。

from tabtransformertf.models.tabtransformer import TabTransformer

tabtransformer = TabTransformer(
numerical_features = NUMERIC_FEATURES,  # 帶有數字特征名稱的清單
categorical_features = CATEGORICAL_FEATURES, # 帶有分類特征名稱的清單
categorical_lookup=category_prep_layers,   # 帶StringLookup層的Dict
numerical_discretisers=None,  # None代表我們隻是簡單地傳遞數字特征
embedding_dim=32,  # 嵌入維數
out_dim=1,  # Dimensionality of output (binary task)
out_activatinotallow='sigmoid',  # 輸出層激活
depth=4,  # 轉換器塊層的個數
heads=8,  # 轉換器塊中注意力頭的個數
attn_dropout=0.1,  # 在轉換器塊中的丢棄率
ff_dropout=0.1,  # 在最後MLP中的丢棄率
mlp_hidden_factors=[2, 4],  # 我們為每一層劃分最終嵌入的因子
use_column_embedding=True,  #如果我們想使用列嵌入,設定此項為真
)

# 模型運作中摘要輸出:
# 總參數個數: 1,778,884
# 可訓練的參數個數: 1,774,064
# 不可訓練的參數個數: 4,8201.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.           

模型初始化後,我們可以像任何其他Keras模型一樣安裝它。訓練參數也可以調整,是以可以随意調整學習速度和提前停止。

LEARNING_RATE = 0.0001
WEIGHT_DECAY = 0.0001
NUM_EPOCHS = 1000

optimizer = tfa.optimizers.AdamW(
learning_rate=LEARNING_RATE, weight_decay=WEIGHT_DECAY
)

tabtransformer.compile(
optimizer = optimizer,
loss = tf.keras.losses.BinaryCrossentropy(),
metrics= [tf.keras.metrics.AUC(name="PR AUC", curve='PR')],
)

out_file = './tabTransformerBasic'
checkpoint = ModelCheckpoint(
out_file, mnotallow="val_loss", verbose=1, save_best_notallow=True, mode="min"
)
early = EarlyStopping(mnotallow="val_loss", mode="min", patience=10, restore_best_weights=True)
callback_list = [checkpoint, early]

history = tabtransformer.fit(
train_dataset,
epochs=NUM_EPOCHS,
validation_data=val_dataset,
callbacks=callback_list
)1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.           

3.評價

競賽中最關鍵的名額是ROC AUC。是以,讓我們将其與PR AUC名額一起輸出來評估一下模型的性能。

val_preds = tabtransformer.predict(val_dataset)

print(f"PR AUC: {average_precision_score(val_data['isFraud'], val_preds.ravel())}")
print(f"ROC AUC: {roc_auc_score(val_data['isFraud'], val_preds.ravel())}")

# PR AUC: 0.26
# ROC AUC: 0.581.2.3.4.5.6.7.           

您也可以自己給測試集評分,然後将結果值送出給Kaggle官方。我現在選擇的這個解決方案使我跻身前35%,這并不壞,但也不太好。那麼,為什麼TabTransfromer在上述方案中表現不佳呢?可能有以下幾個原因:

  • 資料集太小,而深度學習模型以需要大量資料著稱
  • TabTransformer很容易在表格式資料示例領域出現過拟合
  • 沒有足夠的分類特征使模型有用

三、結論

本文探讨了TabTransformer背後的主要思想,并展示了如何使用Tabtransformertf包來具體應用此轉換器。

歸納起來看,TabTransformer的确是一種有趣的體系結構,它在當時的表現明顯優于大多數深度表格模型。它的主要優點是将分類嵌入語境化,進而增強其表達能力。它使用在分類特征上的多頭注意力機制來實作這一點,而這是在表格資料領域使用轉換器的第一個應用執行個體。

TabTransformer體系結構的一個明顯缺點是,數字特征被簡單地傳遞到最終的MLP層。是以,它們沒有語境化,它們的價值也沒有在分類嵌入中得到解釋。在下一篇文章中,我将探讨如何修複此缺陷并進一步提高性能。

譯者介紹

朱先忠,51CTO社群編輯,51CTO專家部落格、講師,濰坊一所高校計算機教師,自由程式設計界老兵一枚。

原文連結:https://towardsdatascience.com/transformers-for-tabular-data-tabtransformer-deep-dive-5fb2438da820?source=collection_home---------4----------------------------

來源: 51CTO技術棧

繼續閱讀