回归损失函数错误

我正在尝试一个基本的平均示例,但验证结果和损失值不匹配,并且如果增加训练时间,网络无法收敛。我正在训练一个具有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)enter image description here

                                                                      torch.nn.L1Loss()enter image description here

                                                     torch.nn.MSELoss(size_average=False)enter image description here

                                                                   torch.nn.MSELoss()enter image description here

                                             torch.nn.SmoothL1Loss(size_average=False)enter image description here

                                                               torch.nn.SmoothL1Loss()enter image description here

谢谢。

网络代码:

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

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注