deep-learning - 使用更大的批量训练矩阵分解问题时损失更高
问题描述
首先,我要感谢任何考虑阅读此问题的人,如果我的问题如此固执,以及我的英语很差,我很抱歉。
所以目前我正在研究一个推荐系统问题,我的方法是使用矩阵分解和使用 BPR ( arXiv:1205.2618 ) 的隐式反馈。不知何故,我发现当我使用大批量(在本例中为 4096)训练我的模型(BPRMF)时,与使用较小批量(1024)时相比,BPR 损失更差。我在几个时代的训练日志。
我注意到更高的批量大小导致更快的训练时间,因为它可以更有效地利用 GPU 内存,但更高的损失可能是我不太愿意交易的东西。据我所知,大批量为梯度下降步骤带来了更多信息,以便采取更好的步骤,因此它应该有助于收敛,通常大批量的问题在于内存和资源,而不是损失。
我对此进行了一些研究,并看到大批量训练导致泛化能力差,而这里又是另一个,但就我而言,它在训练时丢失了。
我最好的猜测是,使用大批量大小,然后取损失的平均值使梯度流向用户和项目嵌入的平均值(1 /批量大小)系数降低,使得在训练时难以逃脱局部最大值。这是这种情况下的答案吗?(但是,我看到最近的研究表明局部最小值不一定是坏的,所以......)
真的很感谢有人帮我回答为什么大批量最终会出现异常结果。
旁注:可能是另一个愚蠢的问题,但正如您在下面的代码中看到的那样,您可以看到 l2 损失没有按批量大小标准化,所以当我将批量大小乘以 4 时,我希望它至少翻倍或四倍,但在上面的日志中似乎并非如此。
这是我的代码
from typing import Tuple
import torch
from torch.nn.parameter import Parameter
import torch.nn.functional as F
from .PretrainedModel import PretrainedModel
class BPRMFModel(PretrainedModel):
def __init__(self, n_users: int, n_items: int, u_embed: int, l2:float,
dataset: str, u_i_pretrained_dir, use_pretrained = 0, **kwargs) -> None:
super().__init__(n_users=n_users, n_items=n_items, u_embed=u_embed, dataset=dataset,
u_i_pretrained_dir=u_i_pretrained_dir, use_pretrained=use_pretrained,
**kwargs)
self.l2 = l2
self.reset_parameters()
self.items_e = Parameter(self._items_e)
self.users_e = Parameter(self._users_e)
def forward(self, u: torch.Tensor, i: torch.Tensor) -> torch.Tensor:
u = F.embedding(u, self.users_e)
i = F.embedding(i, self.items_e)
return torch.matmul(u, i.T)
def CF_loss(self, u: torch.Tensor, i_pos: torch.Tensor, i_neg: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]:
#u, i_pos, i_neg shape is [batch_size,]
u = F.embedding(u, self.users_e)
i_pos = F.embedding(i_pos, self.items_e)
i_neg = F.embedding(i_neg, self.items_e)
pos_scores = torch.einsum("ij,ij->i", u, i_pos)
neg_scores = torch.einsum("ij,ij->i", u, i_neg)
# loss = torch.mean(
# F.softplus(-(pos_scores - neg_scores))
# )
loss = torch.neg(
torch.mean(
F.logsigmoid(pos_scores - neg_scores)
)
)
l2_loss = (
u.pow(2).sum() +
i_pos.pow(2).sum() +
i_neg.pow(2).sum()
)
return loss, self.l2 * l2_loss
def get_users_rating_for_each_items(self, u: torch.Tensor, i: torch.Tensor) -> torch.Tensor:
return self(u, i)
def save_pretrained(self):
self._items_e = self.items_e.data
self._users_e = self.users_e.data
return super().save_pretrained()
PretrainedModel 只是帮助我保存和加载模型权重的基类
真的很感激任何能忍受我到此为止的人。
解决方案
推荐阅读
- python - 使用 service_account_file 找不到电子表格
- vba - VBA替换某些马车
- ruby-on-rails - has_many_association 多个查询使其变慢
- neo4j - 撤消 neo4j 模式中的操作
- javascript - 无法在axios成功回调中更新vue对象的属性
- linux - 尝试连接到服务器时,Sshutle 连接被拒绝
- android - Android Room DB:无法运行失效跟踪器。数据库关闭了吗?
- dns - 如何设置您的 DNS 以从您的邮件服务器代表您的其他域发送邮件
- java - 带开关的枚举
- java - 在 Map 中获取前 N 个元素的最佳方法是什么
基于他们的价值观?