首页 > 解决方案 > Pytorch 中的批量学习是如何进行的?

问题描述

当您查看 pytorch 代码内部如何构建网络架构时,我们需要扩展torch.nn.Module和 inside __init__,我们定义了网络模块,pytorch 将跟踪这些模块的参数梯度。然后在forward函数内部,我们定义应该如何为我们的网络完成前向传递。

我在这里不明白的是批量学习将如何发生。在上述定义中,包括forward函数在内,我们都不关心网络输入的批次维度。我们需要设置执行批量学习的唯一一件事是向输入添加一个额外的维度,该维度对应于批量大小,但如果我们使用批量学习,网络定义中的任何内容都不会改变。至少,这是我在这里的代码中看到的。

所以,如果到目前为止我解释的所有事情都是正确的(如果你让我知道我是否误解了一些东西,我将非常感激),如果在我们的网络类的定义中没有声明任何关于批量大小的声明,批量学习是如何执行的(继承的类torch.nn.Module)?具体来说,我很想知道当我们刚刚设置nn.MSELoss批量维度时,在 pytorch 中如何实现批量梯度下降算法。

标签: pythonneural-networkpytorch

解决方案


检查这个:

import torch
import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
    def __init__(self):
        super().__init__()         

    def forward(self, x):
        print("Hi ma")        
        print(x)
        x = F.relu(x)
        return x

n = Net()
r = n(torch.tensor(-1))
print(r)
r = n.forward(torch.tensor(1)) #not planned to call directly
print(r)

出去:

Hi ma
tensor(-1)
tensor(0)
Hi ma
tensor(1)
tensor(1)

要记住的是forward不应该直接调用。PyTorch 使此 Module 对象n可调用。他们实现了可调用,例如:

 def __call__(self, *input, **kwargs):
    for hook in self._forward_pre_hooks.values():
        hook(self, input)
    if torch._C._get_tracing_state():
        result = self._slow_forward(*input, **kwargs)
    else:
        result = self.forward(*input, **kwargs)
    for hook in self._forward_hooks.values():
        hook_result = hook(self, input, result)
        if hook_result is not None:
            raise RuntimeError(
                "forward hooks should never return any values, but '{}'"
                "didn't return None".format(hook))
    if len(self._backward_hooks) > 0:
        var = result
        while not isinstance(var, torch.Tensor):
            if isinstance(var, dict):
                var = next((v for v in var.values() if isinstance(v, torch.Tensor)))
            else:
                var = var[0]
        grad_fn = var.grad_fn
        if grad_fn is not None:
            for hook in self._backward_hooks.values():
                wrapper = functools.partial(hook, self)
                functools.update_wrapper(wrapper, hook)
                grad_fn.register_hook(wrapper)
    return result

并且n()forward自动调用。

通常,__init__定义模块结构并forward()定义单个批次的操作。

如果某些结构元素需要,该操作可能会重复,或者您可以像我们一样直接在张量上调用函数x = F.relu(x)

你做得很好,PyTorch 中的所有内容都将分批(小批量)进行,因为 PyTorch 已针对这种方式进行了优化。

这意味着当您读取图像时,您不会读取单个图像,而是读取bs一批图像。


推荐阅读