input: Write a python function to perform Linear Regression using Stochastic Gradient Descent.
  assert np.allclose(gradient_descent(np.array([[1, 1], [1, 2], [2, 2]]), np.array([1, 2, 3]), n_iter=1000, learning_rate=0.01), np.array([0.499, 0.999]), atol=0.01)
  assert np.allclose(gradient_descent(np.array([[1, 1], [1, 2], [1, 3], [1, 4]]), np.array([2, 3, 4, 5]), n_iter=1000, learning_rate=0.01), np.array([1.5, 1.0]), atol=0.1)
  assert np.allclose(gradient_descent(np.array([[1, 2], [2, 3], [3, 4], [4, 5]]), np.array([3, 5, 7, 9]), n_iter=1000, learning_rate=0.01), np.array([1, 2]), atol=0.1)
output: def gradient_descent(X, y, n_iter=1000, learning_rate=0.01):
      m, n = X.shape
      theta = np.zeros(n)
      for _ in range(n_iter):
          for i in range(m):
              xi = X[i]
              yi = y[i]
              gradient = (np.dot(xi, theta) - yi) * xi
              theta -= learning_rate * gradient
      return theta