AutoFIS: Automatic Feature Interaction Selection in Factorization Models for Click-Through Rate Prediction
論文地址:https://arxiv.org/abs/2003.11235
代碼地址:https://github.com/zhuchenxv/AutoFIS
Abstract
- 在推薦系統中學習有效的特徵交互對於CTR預估任務是十分重要的。
- 本文提出了一種兩階段的算法:Automatic Feature Interaction Selection (AutoFIS).,能夠自動識別(identify) 在因子分解模型(Factorization Models)中重要的特徵交互(feature interactions),而計算成本僅僅相當於將模型訓練至收斂的計算成本:
- search stage: 引入結構上的參數(architecture parameters),並且使用正則化的優化器( regularized optimizer) 去學習這些參數,在這個階段,architecture parameters的作用在於去除無效的feature interactions
- retrain stage: 根據search stage的結果,去除冗餘的feature interactions, 保留architecture parameters重新訓練模型,這個時候,這些architecture parameters的作用相當於注意力單元(attention units)
Methodology
1. Factorization Model
Factorization models是這樣一類模型: 通過將不同特徵的embedding利用諸如內積、神經網絡等操作映射到一個實數上的過程對於特徵的交互進行建模。
本文基於FM, DeepFM 和 IPNN 對 AutoFIS 進行探索。
模型主要有以下幾個部分組成:
-
Embedding Layer
-
Feature Interaction Layer: 通過embedding內積的方式表示特徵交互
- 二階特徵交互
- 三階特徵交互
- 二階特徵交互
-
MLP Layer:
-
Output Layer:
- FM
- Deep FM
- IPNN
- FM
-
Objective Function
2. AutoFIS
AutoFIS旨在自動識別出有效的feature interaction, 避免無效的feature interaction引入噪聲。
分爲兩個階段: search stage(去檢測有效的feature interactions)和 retrain-stage(去除冗餘的feature interactions重新訓練模型)
2.1 search stage
Architecture parameters
- 爲每個feature interaction引入一個gate來控制是否選擇這個feature interaction:
- gate打開表示選擇這個interaction進入模型訓練,關閉則在訓練時丟掉這個interaction
- 對於2階的feature interaction,會有個gate,那麼就需要在 的空間內去進行gate的最優解搜索,這是十分困難的
- 文章並沒有在一個離散的空間內去解決這個問題,而是引入了 architecture parameters ,通過梯度下降來學習每個feature interaction的相對重要性
(instead of searching over a discrete set of open gates, we relax the choices to be continuous by introducing architecture parameters , so that the relative importance of each feature interaction can be learned by gradient descent.) - 具體地,Factorization Models 中的 interaction layer 如下:
其中,是 architecture parameters。在 search stage, 表示每個feature interaction對於最後預測貢獻的相對大小。
Batch Normalization
-
從整個神經網絡的角度看,某個feature interaction的貢獻由 整體的值來衡量。而將 和 同時 scale:,feature interaction<i,j>的貢獻值是不變的。
-
和 是共同學習的(都是可訓練的),這就會導致 的預估值是不穩定的,也就是說,並不能表示 的相對貢獻大小。
-
爲了去除 的縮放影響,對應用Batch Normalization:
-
在AutoFIS中,將 BN 中的 scale 和 shift 固定爲1和0:
GRDA Optimizer -
Generalized regularized dual averaging (GRDA) optimizer 會學習一個稀疏的神經網絡(a sparse deep neural network),在 step ,針對數據 , 的更新如下:
-
其中, ,是 learning rate,和是在accuracy 和 sparsity之間進行權衡的超參數
-
grda 的 github代碼: https://github.com/donlan2710/gRDA-Optimizer
-
超參數調整建議:
- . 越大,參數越稀疏。 爲了獲得和原始網絡相當的accuracy, 對於大型的任務,比如 ImageNet, 可以設置的接近於0.5,比如0.501;而對於較小的任務,比如CIFAR-10, 可以大一點,比如0.6;
- 。越大,模型越稀疏。但是的影響小於,並且在模型訓練早一些的step,的影響較大,在訓練後期,影響較小。
-
AutoFIS裏的c和mu設置:
One Level Optimization -
在DARTS中,被視作 higher-level的決策變量,而模型的其他參數 被視作是 lower-level的變量,假設模型只有在權重被正確學習之後,才能select operation,而和 是迭代學習的。
-
在本文中 和 被視作爲同一層級的參數,模型同時學習這兩套參數
代碼
feature interaction layer的實現:
#self.xv就是 <ei,ej> [batch_size, feature_num, emb_size]
# 生成所有的二階特徵組合
self.cols, self.rows = generate_pairs(range(self.xv.shape[1]),mask=comb_mask)
t_embedding_matrix = tf.transpose(self.xv, perm=[1, 0, 2]) # [feature_num, batch_size, emb_size]
left = tf.transpose(tf.gather(t_embedding_matrix, self.rows), perm=[1, 0, 2]) # [batch_size, C(feature_num,2), emb_size]
right = tf.transpose(tf.gather(t_embedding_matrix, self.cols), perm=[1, 0, 2]) # [batch_size, C(feature_num,2), emb_size]
level_2_matrix = tf.reduce_sum(tf.multiply(left, right), axis=-1) # [batch_size, C(feature_num,2)]
# edge_weights 就是 architecture parameters: alpha [C(feature_num,2)]
with tf.variable_scope("edge_weight", reuse=tf.AUTO_REUSE):
self.edge_weights = tf.get_variable('weights', shape=[len(self.cols)],
initializer=tf.random_uniform_initializer(
minval=weight_base - 0.001,
maxval=weight_base + 0.001))
normed_wts = tf.identity(self.edge_weights, name="normed_wts")
tf.add_to_collection("structure", self.edge_weights)
tf.add_to_collection("edge_weights", self.edge_weights)
mask = tf.identity(normed_wts, name="unpruned_mask")
mask = tf.expand_dims(mask, axis=0) #[1, C(feature_num,2)]
level_2_matrix = tf.layers.batch_normalization(level_2_matrix, axis=-1, training=self.training,
reuse=tf.AUTO_REUSE, scale=False, center=False, name='prune_BN')
level_2_matrix *= mask
參數的更新使用不同的optimizer:
weight_var = list(set(tf.get_collection("edge_weights")))
all_variable = [v for v in tf.trainable_variables()]
other_var = [i for i in all_variable if i not in weight_var]
self.optimizer1 = optimizer1.minimize(loss=_loss_, var_list=other_var) # adam
self.optimizer2 = optimizer2.minimize(loss=_loss_, var_list=weight_var) # grda
2.2 retrain-stage
search stage之後,一些不重要的 feature interaction就被自動丟棄了。我們中 來表示 feature interaction 的開關狀態:時,。
丟掉冗餘的feature interaction,重新訓練模型。在這個時候, 不再用來作爲決定 feature interaction 是否應該保留在模型中的indicator,而是作爲一個注意力單元來學習被留下來的feature interaction的相對重要性,feature interaction layer如下:
注意,此時包括在內的所有參數都是用同一個 Adam 優化器學習的:
all_variable = [v for v in tf.trainable_variables()]
self.optimizer1 = optimizer1.minimize(loss=_loss_, var_list=all_variable)
問題:
grad的超參不是很好調,而且篩選出來的特徵不穩定(用不同天的訓練集)