Pytorch Siamese NN 与 BERT 用于句子匹配
Pytorch Siamese NN with BERT for sentence matching
我正在尝试使用 pytorch 构建 Siamese 神经网络,我在其中输入 BERT 词嵌入并试图找出两个句子是否相似(想象重复的帖子匹配、产品匹配等)。这是模型:
class SiameseNetwork(torch.nn.Module):
def __init__(self):
super(SiameseNetwork, self).__init__()
self.brothers = torch.nn.Sequential(
torch.nn.Linear(512 * 768, 512),
torch.nn.BatchNorm1d(512),
torch.nn.ReLU(inplace=True),
torch.nn.Linear(512, 256),
torch.nn.BatchNorm1d(256),
torch.nn.ReLU(inplace=True),
torch.nn.Linear(256, 32),
)
self.final = torch.nn.Sequential(
torch.nn.Linear(32, 16),
torch.nn.ReLU(inplace=True),
torch.nn.Linear(16, 2),
)
def forward(self, left, right):
outputLeft = self.brothers(left)
outputRight = self.brothers(right)
output = self.final((outputLeft - outputRight) ** 2)
return output
bros = SiameseNetwork()
bros = bros.to(device)
标准和优化器:
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(params=bros.parameters(), lr=0.001)
训练循环:
for batch in tqdm(tLoader, desc=f"Train epoch: {epoch+1}"):
a = batch[0].to(device)
b = batch[1].to(device)
y = torch.unsqueeze(batch[2].type(torch.FloatTensor), 1).to(device)
optimizer.zero_grad()
output = bros(a,b)
loss = criterion(output, y)
loss.backward()
trainingLoss += loss.item()
optimizer.step()
现在,这似乎有效,因为它产生的结果是合理的,但验证错误在一个时期后停止下降到 0.13。使用 Pytorch 在这种神经网络上找不到很多东西。有没有办法优化它?我做错了什么吗?
您的第一层参数严重过高且容易过拟合(总共有 2.01 亿个参数)。我假设形状 512 * 768
反映了标记的数量乘以它们的维度;如果是这样,您需要重新考虑您的架构。您需要某种权重共享或池化策略来将 num_words * dim
输入减少为固定表示(这正是循环网络取代句子编码的完全连接变体的原因)。特别是在基于转换器的架构中,[CLS]
标记(标记编号 0,输入前缀)通常用作序列级和双序列级任务的“摘要”标记。
我正在尝试使用 pytorch 构建 Siamese 神经网络,我在其中输入 BERT 词嵌入并试图找出两个句子是否相似(想象重复的帖子匹配、产品匹配等)。这是模型:
class SiameseNetwork(torch.nn.Module):
def __init__(self):
super(SiameseNetwork, self).__init__()
self.brothers = torch.nn.Sequential(
torch.nn.Linear(512 * 768, 512),
torch.nn.BatchNorm1d(512),
torch.nn.ReLU(inplace=True),
torch.nn.Linear(512, 256),
torch.nn.BatchNorm1d(256),
torch.nn.ReLU(inplace=True),
torch.nn.Linear(256, 32),
)
self.final = torch.nn.Sequential(
torch.nn.Linear(32, 16),
torch.nn.ReLU(inplace=True),
torch.nn.Linear(16, 2),
)
def forward(self, left, right):
outputLeft = self.brothers(left)
outputRight = self.brothers(right)
output = self.final((outputLeft - outputRight) ** 2)
return output
bros = SiameseNetwork()
bros = bros.to(device)
标准和优化器:
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(params=bros.parameters(), lr=0.001)
训练循环:
for batch in tqdm(tLoader, desc=f"Train epoch: {epoch+1}"):
a = batch[0].to(device)
b = batch[1].to(device)
y = torch.unsqueeze(batch[2].type(torch.FloatTensor), 1).to(device)
optimizer.zero_grad()
output = bros(a,b)
loss = criterion(output, y)
loss.backward()
trainingLoss += loss.item()
optimizer.step()
现在,这似乎有效,因为它产生的结果是合理的,但验证错误在一个时期后停止下降到 0.13。使用 Pytorch 在这种神经网络上找不到很多东西。有没有办法优化它?我做错了什么吗?
您的第一层参数严重过高且容易过拟合(总共有 2.01 亿个参数)。我假设形状 512 * 768
反映了标记的数量乘以它们的维度;如果是这样,您需要重新考虑您的架构。您需要某种权重共享或池化策略来将 num_words * dim
输入减少为固定表示(这正是循环网络取代句子编码的完全连接变体的原因)。特别是在基于转换器的架构中,[CLS]
标记(标记编号 0,输入前缀)通常用作序列级和双序列级任务的“摘要”标记。