【推薦演算法】Wide & Deep
阿新 • • 發佈:2021-06-30
Wide & Deep主要解決了FM的以下幾個痛點:
- 強化記憶能力。FM這類embedding類模型擁有強大的泛化能力,在embedding的過程中傳入了大量的全域性資訊,對於一些很少出現甚至沒有出現過的特徵組合,也能計算出合理的特徵組合權重。但是,當共現矩陣過於稀疏時,模型會過分泛化,推薦出很多相關性低的內容。Wide & Deep不僅強調了模型的“泛化能力”,還強調了“記憶能力”。具體來說,記憶能力表示一類規則式的推薦,即當出現情況A時,就推薦B。
演算法
如圖,模型由左邊的wide與右邊的deep結合而成,兩者的結果相加後經過一個sigmoid層得到最終的CTR預估值。其中,deep中包含所有特徵,wide中包含人工設計的需要加強記憶能力的特徵交叉(如下載軟體A與展現軟體B),特徵交叉方法使用交叉積,可以看做特徵one-hot表示下的向量內積。
模型輸入
首先定義一個mlp實現deep部分:
class MultiLayerPerceptron(torch.nn.Module): def __init__(self, input_dim, embed_dims, dropout): super().__init__() layers = list() for embed_dim in embed_dims: layers.append(torch.nn.Linear(input_dim, embed_dim)) layers.append(torch.nn.BatchNorm1d(embed_dim)) layers.append(torch.nn.ReLU()) layers.append(torch.nn.Dropout(p=dropout)) input_dim = embed_dim layers.append(torch.nn.Linear(input_dim, 1)) self.mlp = torch.nn.Sequential(*layers) def forward(self, x): """ :param x: Float tensor of size ``(batch_size, embed_dim)`` """ return self.mlp(x)
為了簡化,我們使用全量物品特徵加入wide部分,並且不手工設計特徵交叉。程式碼中使用LR的實現來實現wide部分(很不嚴謹)。最後,構建完整的DeepFM前向傳播鏈路:
class WideAndDeepModel(torch.nn.Module): def __init__(self, field_dims, embed_dim=16, mlp_dims=(16, 16), dropout=0.2): super().__init__() self.linear = FeaturesLinear(field_dims) self.embedding = FeaturesEmbedding(field_dims, embed_dim) self.embed_output_dim = len(field_dims) * embed_dim self.mlp = MultiLayerPerceptron(self.embed_output_dim, mlp_dims, dropout) def forward(self, x): """ :param x: Long tensor of size ``(batch_size, num_fields)`` """ embed_x = self.embedding(x) x = self.linear(x) + self.mlp(embed_x.view(-1, self.embed_output_dim)) return torch.sigmoid(x.squeeze(1))
模型效果
設定:
資料集:ml-100k
優化方法:Adam
學習率:0.003
效果:
收斂epoch: 10
train logloss: 0.52100
val auc: 0.78681
test auc: 0.78500