二塔网做深不学

数据挖掘 神经网络 火炬 推荐系统
2022-03-03 22:31:16

我一直在尝试训练一个相对简单的两塔网络进行推荐。我正在使用 PyTorch,实现如下 - 基本上为用户和项目嵌入层,两个塔的可选前馈网络,用户和项目表示之间的点积,以及 sigmoid。

class SimpleTwoTower(nn.Module):
    
    def __init__(self, n_items, n_users, ln):
        super(SimpleTwoTower, self).__init__()
        
        self.ln = ln
        self.item_emb = nn.Embedding(num_embeddings=n_items, embedding_dim=self.ln[0])
        self.user_emb = nn.Embedding(num_embeddings=n_users, embedding_dim=self.ln[0])
       
        
        self.item_layers = [] #nn.ModuleList()
        self.user_layers = [] #nn.ModuleList()
        
        for i, n in enumerate(ln[0:-1]):
            m = int(ln[i+1])
            self.item_layers.append(nn.Linear(n, m, bias=True))
            self.item_layers.append(nn.ReLU())
            
            self.user_layers.append(nn.Linear(n, m, bias=True))
            self.user_layers.append(nn.ReLU())
            
            
        self.item_layers = nn.Sequential(*self.item_layers)
        self.user_layers = nn.Sequential(*self.user_layers)
        
        self.dot = torch.matmul
        self.sigmoid = nn.Sigmoid()
        
    def forward(self, items, users):
        
        item_emb = self.item_emb(items)
        user_emb = self.user_emb(users)
        
        item_emb = self.item_layers(item_emb)
        user_emb = self.user_layers(user_emb)

        dp = self.dot(user_emb, item_emb.t())
        return self.sigmoid(dp)

我正在使用二进制交叉熵损失和 Adam 优化器。当我只使用嵌入时,我看到了从一个时期到另一个时期的改进(损失在减少,评估指标在增加)。然而,一旦我添加了一个前馈层,网络在第一个 epoch 中只学习了一点,然后就停滞不前了。我试图用 ReLU 编写一个线性层,以检查问题是否与我创建层列表的方式有关,但这并没有改变任何东西。

有没有其他人有类似的问题?

编辑:在这里,我在 PyTorch 论坛上发布了这个问题,我有一些回复。

1个回答

我现在有一个工作网络。事实证明,仅在大约 3000 次更新步骤之后,梯度全为零。我尝试了两种方法来解决这个问题——在前馈网络中的每个激活函数之后使用 Batch Normalization,并将激活函数从 ReLU 更改为 Leaky ReLU。两者都有效,我最终使用了没有归一化的 Leaky ReLU。

对于 PyTorch 讨论论坛中的完整主题,请点击此处