我正在尝试一个基本的平均示例,但验证结果和损失值不匹配,并且如果增加训练时间,网络无法收敛。我正在训练一个具有2个隐藏层的网络,每个隐藏层有500个单元,输入是来自[0,9]范围内的三个整数,学习率为1e-1,使用Adam优化器,批次大小为1,3000次迭代,每100次迭代进行一次验证。如果标签与假设之间的绝对差异小于一个阈值,这里我将阈值设为1,我认为这是正确的。能否有人告诉我这是不是损失函数选择的问题,Pytorch本身的问题,还是我操作上的错误?以下是一些图表:
val_diff = 1acc_diff = torch.FloatTensor([val_diff]).expand(self.batch_size)
在验证过程中循环100次:
num_correct += torch.sum(torch.abs(val_h - val_y) < acc_diff)
在每次验证阶段后追加:
validate.append(num_correct / total_val)
以下是假设和标签的一些示例:
[...(-0.7043088674545288, 6.0), (-0.15691305696964264, 2.6666667461395264), (0.2827358841896057, 3.3333332538604736)]
我尝试了API中通常用于回归的六种损失函数:
torch.nn.L1Loss(size_average=False)
torch.nn.MSELoss(size_average=False)
torch.nn.SmoothL1Loss(size_average=False)
谢谢。
网络代码:
class Feedforward(nn.Module): def __init__(self, topology): super(Feedforward, self).__init__() self.input_dim = topology['features'] self.num_hidden = topology['hidden_layers'] self.hidden_dim = topology['hidden_dim'] self.output_dim = topology['output_dim'] self.input_layer = nn.Linear(self.input_dim, self.hidden_dim) self.hidden_layer = nn.Linear(self.hidden_dim, self.hidden_dim) self.output_layer = nn.Linear(self.hidden_dim, self.output_dim) self.dropout_layer = nn.Dropout(p=0.2) def forward(self, x): batch_size = x.size()[0] feat_size = x.size()[1] input_size = batch_size * feat_size self.input_layer = nn.Linear(input_size, self.hidden_dim).cuda() hidden = self.input_layer(x.view(1, input_size)).clamp(min=0) for _ in range(self.num_hidden): hidden = self.dropout_layer(F.relu(self.hidden_layer(hidden))) output_size = batch_size * self.output_dim self.output_layer = nn.Linear(self.hidden_dim, output_size).cuda() return self.output_layer(hidden).view(output_size)
训练代码:
def train(self): if self.cuda: self.network.cuda() dh = DataHandler(self.data) # loss_fn = nn.L1Loss(size_average=False) # loss_fn = nn.L1Loss() # loss_fn = nn.SmoothL1Loss(size_average=False) # loss_fn = nn.SmoothL1Loss() # loss_fn = nn.MSELoss(size_average=False) loss_fn = torch.nn.MSELoss() losses = [] validate = [] hypos = [] labels = [] val_size = 100 val_diff = 1 total_val = float(val_size * self.batch_size) for i in range(self.iterations): x, y = dh.get_batch(self.batch_size) x = self.tensor_to_Variable(x) y = self.tensor_to_Variable(y) self.optimizer.zero_grad() loss = loss_fn(self.network(x), y) loss.backward() self.optimizer.step()
回答:
看起来你对PyTorch中层的使用有些误解,以下是一些建议:
-
在你的forward函数中,当你使用
nn.Linear(...)
时,你实际上是在定义新的层,而不是使用你在网络__init__
中预定义的层。因此,权重不断被重新初始化,网络无法学习任何东西。 -
你不需要在
net.forward(...)
中调用.cuda()
,因为你已经在train
函数中通过调用self.network.cuda()
将网络复制到GPU上了。 -
理想情况下,
net.forward(...)
的输入应该直接具有第一层的形状,这样你就不需要修改它。在这里,你应该有x.size() <=> Linear -- > (Batch_size, Features)
。
你的forward函数应该类似于这样:
def forward(self, x): x = F.relu(self.input_layer(x)) x = F.dropout(F.relu(self.hidden_layer(x)),training=self.training) x = self.output_layer(x) return x