TensorFlow 決策樹森林 (TF-DF) 是 TensorFlow 中可用的決策樹森林 (DF) 演算法集合。決策樹森林的運作方式與神經網路 (NN) 不同:決策樹森林通常不使用反向傳播或迷你批次進行訓練。因此,TF-DF 管線與其他 TensorFlow 管線有一些差異。
本文檔列出了這些差異,並提供將 TF 管線更新為使用 TF-DF 的指南
本文檔假設您已熟悉初學者 Colab。
資料集和特徵
驗證資料集
與標準神經網路訓練範例不同,TF-DF 模型不需要驗證資料集來監控過度擬合或提前停止訓練。如果您已經有訓練/驗證/測試分割,並且您將驗證用於其中一個原因,則將 TF-DF 訓練於訓練+驗證是安全的 (除非驗證分割也用於其他用途,例如超參數調整)。
- model.fit(train_ds, validation_data=val_ds)
+ model.fit(train_ds.concatenate(val_ds))
# Or just don't create a validation dataset
理由: TF-DF 框架由多個演算法組成。其中一些演算法不使用驗證資料集 (例如,隨機森林),而另一些演算法則使用 (例如,梯度提升樹)。需要驗證資料集的演算法可能會受益於不同類型和大小的驗證資料集。因此,如果需要驗證資料集,它將自動從訓練資料集中提取。
資料集 I/O
精確訓練 1 個 epoch
# Number of epochs in Keras
- model.fit(train_ds, num_epochs=5)
# Number of epochs in the dataset
- train_ds = train_ds.repeat(5)
- model.fit(train_ds)
+ model.fit(train_ds)
理由: 神經網路使用者通常會訓練模型 N 步 (可能涉及迴圈遍歷資料集 > 1 次),因為 SGD 的性質。TF-DF 的訓練方式是讀取整個資料集,然後在最後執行訓練。需要 1 個 epoch 來讀取完整資料集,任何額外步驟都會導致不必要的資料 I/O,以及較慢的訓練速度。
請勿隨機排序資料集
資料集不需要隨機排序 (除非 input_fn 僅讀取資料集的樣本)。
- train_ds = train_ds.shuffle(5)
- model.fit(train_ds)
+ model.fit(train_ds)
理由: TF-DF 在將完整資料集讀取到記憶體後,會在內部隨機排序資料的存取。TF-DF 演算法是確定性的 (如果使用者未變更隨機種子)。啟用隨機排序只會使演算法變成非確定性。如果輸入資料集是有序的,並且 input_fn 僅會讀取其樣本 (樣本應為隨機),則隨機排序才有意義。但是,這會使訓練程序變成非確定性。
請勿調整批次大小
批次大小不會影響模型品質
- train_ds = train_ds.batch(hyper_parameter_batch_size())
- model.fit(train_ds)
# The batch size does not matter.
+ train_ds = train_ds.batch(64)
+ model.fit(train_ds)
理由: 由於 TF-DF 始終在讀取後的完整資料集上進行訓練,因此模型品質不會根據批次大小而變化 (與迷你批次訓練演算法 (例如 SGD,其中學習率等參數需要聯合調整) 不同)。因此,應將其從超參數掃描中移除。批次大小只會影響資料集 I/O 的速度。
大型資料集
與神經網路可以無限迴圈遍歷大型資料集的迷你批次不同,決策樹森林需要適合記憶體的有限資料集才能進行訓練程序。資料集的大小會對效能和記憶體產生影響。
增加資料集大小的回報會遞減,而且決策樹森林演算法可能需要比大型 NN 模型更少的範例才能收斂。您可以嘗試縮放資料量,而不是縮放訓練步驟的數量 (如在 NN 中),以查看運算權衡在哪裡有意義。因此,最好先嘗試在資料集的小型子集上進行訓練。
替代解決方案是使用分散式訓練。如果有多部機器可用,分散式訓練是增加資料集大小的好方法。雖然所有分散式演算法都可用於分散運算,但並非所有演算法都能分散 RAM 使用量。請查看文件以取得更多詳細資訊。
要使用多少範例
它應適合模型訓練所在機器的記憶體:
請注意,這與磁碟上範例的大小不同。
根據經驗法則,一個數值或類別值使用 4 個位元組的記憶體。因此,具有 100 個特徵和 2500 萬個範例的資料集將佔用約 10GB (= 100 * 25 * 10^6 * 4 個位元組) 的記憶體。
類別集合特徵 (例如,已符號化的文字) 佔用更多記憶體 (每個符號 4 個位元組 + 每個特徵 12 個位元組)。
考量您的訓練時間預算
雖然通常比小型資料集 (例如,<10 萬個範例) 的 NN 更快,但決策樹森林訓練演算法不會隨著資料集大小線性擴充;而是在大多數情況下約為 ~O(特徵 x 範例數 x log(範例數))。
訓練時間取決於超參數。最具影響力的參數為:(1) 樹狀結構的數量 (
num_trees
)、(2) 範例取樣率 (subsample
(適用於 GBT)),以及 (3) 屬性取樣率 (num_candidate_attributes_ratio
)類別集合特徵比其他特徵更昂貴。成本由
categorical_set_split_greedy_sampling
參數控制。稀疏傾斜特徵 (預設為停用) 提供良好的結果,但運算成本很高。
擴充資料的經驗法則
我們建議從少量資料切片 (<1 萬個範例) 開始,在大多數情況下,這應該讓您在幾秒鐘或幾分鐘內訓練 TF-DF 模型。然後,您可以以固定的速率增加資料 (例如,每次增加 40%),當驗證集效能沒有改善或資料集不再適合記憶體時停止。
特徵正規化/預先處理
請勿使用特徵欄轉換資料
TF-DF 模型不需要明確提供特徵語意和轉換。根據預設,資料集中的所有特徵 (標籤除外) 都將被模型偵測和使用。特徵語意將會自動偵測,並且可以在需要時手動覆寫。
# Estimator code
- feature_columns = [
- tf.feature_column.numeric_column(feature_1),
- tf.feature_column.categorical_column_with_vocabulary_list(feature_2, ['First', 'Second', 'Third'])
- ]
- model = tf.estimator.LinearClassifier(feature_columns=feature_columnes)
# Use all the available features. Detect the type automatically.
+ model = tfdf.keras.GradientBoostedTreesModel()
您也可以指定輸入特徵的子集
+ features = [
+ tfdf.keras.FeatureUsage(name="feature_1"),
+ tfdf.keras.FeatureUsage(name="feature_2")
+ ]
+ model = tfdf.keras.GradientBoostedTreesModel(features=features, exclude_non_specified_features=True)
如有必要,您可以強制執行特徵的語意。
+ forced_features = [
+ tfdf.keras.FeatureUsage(name="feature_1", semantic=tfdf.keras.FeatureSemantic.CATEGORICAL),
+ ]
+ model = tfdf.keras.GradientBoostedTreesModel(features=features)
理由: 雖然某些模型 (如神經網路) 需要標準化的輸入層 (例如,從不同特徵類型到嵌入的對應),但 TF-DF 模型可以原生取用類別和數值特徵,以及根據資料自動偵測特徵的語意類型。
請勿預先處理特徵
決策樹演算法不會受益於用於神經網路的一些傳統特徵預先處理。以下明確列出了一些更常見的特徵處理策略,但安全的起點是移除所有旨在協助神經網路訓練的預先處理。
請勿正規化數值特徵
- def zscore(value):
- return (value-mean) / sd
- feature_columns = [tf.feature_column.numeric_column("feature_1",normalizer_fn=zscore)]
理由: 決策樹森林演算法原生支援非正規化的數值特徵,因為分割演算法不會對輸入進行任何數值轉換。某些類型的正規化 (例如,z 分數正規化) 無助於訓練程序的數值穩定性,而某些正規化 (例如,離群值裁剪) 可能會損害最終模型的表現力。
請勿編碼類別特徵 (例如,雜湊、單熱編碼或嵌入)
- integerized_column = tf.feature_column.categorical_column_with_hash_bucket("feature_1",hash_bucket_size=100)
- feature_columns = [tf.feature_column.indicator_column(integerized_column)]
- integerized_column = tf.feature_column.categorical_column_with_vocabulary_list('feature_1', ['bob', 'george', 'wanda'])
- feature_columns = [tf.feature_column.indicator_column(integerized_column)]
理由: TF-DF 原生支援類別特徵,並將「轉換」詞彙項目視為其內部詞彙中的另一個項目 (可以透過模型超參數進行設定)。某些轉換 (如雜湊) 可能會有損耗。除非嵌入是預先訓練的,否則不支援嵌入,因為決策樹森林模型不可微分 (請參閱中級 Colab)。請注意,領域特定的詞彙策略 (例如,停用詞移除、文字正規化) 可能仍然有幫助。
如何處理文字特徵
TF-DF 原生支援類別集合特徵。因此,可以原生取用已符號化的 n-gram 包。
或者,也可以透過預先訓練的嵌入來取用文字。
類別集合在小型資料集上具有範例效率,但在大型資料集上訓練成本很高。結合類別集合和預先訓練的嵌入通常可以產生比單獨使用任何一個更好的結果。
請勿用魔術值取代遺失的特徵
理由: TF-DF 原生支援遺失值。與神經網路不同,如果輸入中有 NaN,神經網路可能會將 NaN 傳播到梯度,如果演算法看到遺失值和哨兵值之間的差異,TF-DF 將以最佳方式訓練。
- feature_columns = [
- tf.feature_column.numeric_column("feature_1", default_value=0),
- tf.feature_column.numeric_column("feature_1_is_missing"),
- ]
處理影像和時間序列
在決策樹森林中沒有用於取用影像或時間序列特徵的標準演算法,因此需要額外的工作才能使用它們。
理由: 卷積、LSTM、注意力和其他序列處理演算法是神經網路特定的架構。
可以使用以下策略處理這些特徵
特徵工程
影像:在某些時候,將影像與隨機森林一起使用很流行 (例如
Microsoft Kinect ,但今天,神經網路是最先進的技術。
時間序列:[移動統計] 對於範例相對較少的時間序列資料 (例如,醫療領域的生命徵象) 可能效果出奇地好。
嵌入模組:神經網路嵌入模組可以為決策樹森林演算法提供豐富的特徵。中級 Colab 顯示如何結合 tf-hub 嵌入和 TF-DF 模型。
訓練管線
請勿使用硬體加速器,例如 GPU、TPU
TF-DF 訓練 (尚未) 支援硬體加速器。所有訓練和推論都在 CPU 上完成 (有時使用 SIMD)。
請注意,CPU 上的 TF-DF 推論 (尤其是在使用 Yggdrasil C++ 程式庫提供服務時) 可能非常快速 (每個 CPU 核心每個範例的次微秒)。
請勿使用檢查點或訓練中途掛鉤
TF-DF (目前) 不支援模型檢查點,這表示期望模型在訓練完成前可用的掛鉤在很大程度上不受支援。模型僅在訓練要求的樹狀結構數量 (或提前停止) 後才可用。
依賴訓練步驟的 Keras 掛鉤也無法運作 – 由於 TF-DF 訓練的性質,模型會在第一個 epoch 結束時進行訓練,並在該 epoch 之後保持不變。步驟僅對應於資料集 I/O。
模型確定性
TF-DF 訓練演算法是確定性的,也就是說,在相同的資料集上訓練兩次將會產生完全相同的模型。這與使用 TensorFlow 訓練的神經網路不同。為了保留這種確定性,使用者應確保資料集讀取也是確定性的。
訓練組態
指定任務 (例如,分類、排名) 而不是損失 (例如,二元交叉熵)
- model = tf_keras.Sequential()
- model.add(Dense(64, activation=relu))
- model.add(Dense(1)) # One output for binary classification
- model.compile(loss=tf_keras.losses.BinaryCrossentropy(from_logits=True),
- optimizer='adam',
- metrics=['accuracy'])
# The loss is automatically determined from the task.
+ model = tfdf.keras.GradientBoostedTreesModel(task=tf_keras.Task.CLASSIFICATION)
# Optional if you want to report the accuracy.
+ model.compile(metrics=['accuracy'])
理由: 並非所有 TF-DF 學習演算法都使用損失。對於使用損失的演算法,損失會從任務中自動偵測並在模型摘要中列印。您也可以使用損失超參數覆寫它。
超參數在語意上是穩定的
所有超參數都有預設值。這些值是合理的首選候選值。預設超參數值保證永遠不會變更。因此,預設情況下會停用新的超參數或演算法改進。
希望使用最新演算法但不想要自行最佳化超參數的使用者可以使用 TF-DF 提供的「超參數範本」。新的超參數範本將隨著套件的更新而發布。
# Model with default hyper-parameters.
model = tfdf.keras.GradientBoostedTreesModel()
# List the hyper-parameters (with default value) and hyper-parameters templates of the GBT learning algorithm (in colab)
?tfdf.keras.GradientBoostedTreesModel
# Use a hyper-parameter template.
model = tfdf.keras.GradientBoostedTreesModel(hp_template="winner_1")
# Change one of the hyper-parameters.
model = tfdf.keras.GradientBoostedTreesModel(num_trees=500)
# List all the learning algorithms available
tfdf.keras.get_all_models()
模型偵錯
本節介紹一些您可以查看/偵錯/解譯模型的方法。初學者 Colab 包含端對端範例。
簡單模型摘要
# Text description of the model, training logs, feature importances, etc.
model.summary()
訓練記錄和 TensorBoard
# List of metrics
logs = model.make_inspector().training_logs()
print(logs)
或使用 TensorBoard
% load_ext
tensorboard
model.make_inspector().export_to_tensorboard("/tmp/tensorboard_logs")
% tensorboard - -logdir
"/tmp/tensorboard_logs"
特徵重要性
model.make_inspector().variable_importances()
繪製樹狀結構圖
tfdf.model_plotter.plot_model_in_colab(model, tree_idx=0)
存取樹狀結構
tree = model.make_inspector().extract_tree(tree_idx=0)
print(tree)
(請參閱進階 Colab)
請勿使用 TensorFlow 分散策略
TF-DF 尚不支援 TF 分散策略。多工作站設定將被忽略,並且訓練只會在管理員上發生。
- with tf.distribute.MirroredStrategy():
- model = ...
+ model = ....
堆疊模型
TF-DF 模型不會反向傳播梯度。因此,除非 NN 已經過訓練,否則它們無法與 NN 模型組合。
從 tf.estimator.BoostedTrees {Classifier/Regressor/Estimator} 遷移
儘管聽起來相似,但 TF-DF 和 Estimator 提升樹狀結構是不同的演算法。TF-DF 實作了經典的 隨機森林 和 梯度提升機器 (使用樹狀結構) 論文。tf.estimator.BoostedTreesEstimator 是一種近似梯度提升樹演算法,具有 本文中描述的迷你批次訓練程序
某些超參數具有相似的語意 (例如 num_trees),但它們具有不同的品質含義。如果您調整了 tf.estimator.BoostedTreesEstimator 上的超參數,則需要在 TF-DF 內重新調整超參數以獲得最佳結果。
適用於 Yggdrasil 使用者
Yggdrasil 決策樹森林是 TF-DF 使用的核心訓練和推論程式庫。訓練組態和模型是交叉相容的 (也就是說,使用 TF-DF 訓練的模型可以與 Yggdrasil 推論一起使用)。
但是,某些 Yggdrasil 演算法 (尚未) 在 TF-DF 中提供。
- 具有分片取樣的梯度提升樹。