@Peter_Ham because pytorch accumulates gradients, to do batch descent, you can just call optimizer.step() at the end of your dataset epoch.
For example:
for epoch in range(epochs):
    optimizer.zero_grad()
    for data, target in dataset:
        out = model(input)
        err = loss_fn(out, target)
        err.backward()
    optimizer.step()