Thanks for the response, my confusion comes from the fact that the code included below calculates SGD by taking a tensor that is the size of my training set and performing at update one sample at the time. i.e for each iteration of the loop an update of SGD is performed for every sample in the tensor
In the initial code in the second nested loop, the data loader provides a tensor the size of my mini-batch, then how come it does not follow the same procedure as above, i.e for each iteration performing an update on each sample in the tensor.
from torch import nn
import torch
import numpy as np
import matplotlib.pyplot as plt
from torch import nn,optim
from torch.utils.data import Dataset, DataLoader
class Data(Dataset):
   def __init__(self):
       self.x=torch.arange(-3,3,0.1).view(-1, 1)
       self.y=-3*self.x+1+0.1*torch.randn(self.x.size())
       self.len=self.x.shape[0]
   def __getitem__(self,index):    
           
       return self.x[index],self.y[index]
   def __len__(self):
       return self.len
class linear_regression(nn.Module):
   def __init__(self,input_size,output_size):
       super(linear_regression,self).__init__()
       self.linear=nn.Linear(input_size,output_size)
   def forward(self,x):
       yhat=self.linear(x)
       return yhat

class linear_regression(nn.Module):
   def __init__(self,input_size,output_size):
       super(linear_regression,self).__init__()
       self.linear=nn.Linear(input_size,output_size)
   def forward(self,x):
       yhat=self.linear(x)
       return yhat
model=linear_regression(1,1)
optimizer = optim.SGD(model.parameters(), lr = 0.01)
criterion = nn.MSELoss()
dataset=Data()


x,y=dataset[:]
LOSS=[]

n=1;
for epoch in range(5):
       yhat=model(x)
       loss=criterion(yhat,y)
       optimizer.zero_grad()
       loss.backward()
       optimizer.step()
       LOSS.append(loss)