input: Write a function to implement the Gradient Descent Algorithm for linear regression. The function should take in the input features `x`, target values `y`, an optional learning rate, and an optional number of iterations. It should compute the current slope `m_curr` and intercept `b_curr`, update them iteratively, and print the values of `m_curr`, `b_curr`, and the cost function at each iteration. Finally, it should return the optimized values of `m_curr` and `b_curr`.
  
  
  import numpy as np
  
  def gradient_descent(x, y, learning_rate=0.01, iterations=100):
      m_curr = b_curr = 0
      n = len(x)
      for i in range(iterations):
          y_predicted = m_curr * x + b_curr
          cost = (1/n) * sum([val**2 for val in (y-y_predicted)])
          md = -(2/n)*sum(x*(y-y_predicted))
          bd = -(2/n)*sum(y-y_predicted)
          m_curr = m_curr - learning_rate * md
          b_curr = b_curr - learning_rate * bd
          print ("m {}, b {}, cost {} iteration {}".format(m_curr,b_curr,cost, i))
      return m_curr, b_curr
  
  
  assert gradient_descent(np.array([1, 2, 3, 4, 5]), np.array([5, 7, 9, 11, 13])) == (2.0, 3.0)
  assert gradient_descent(np.array([1, 2, 3, 4, 5]), np.array([2, 4, 6, 8, 10])) == (2.0, 0.0)
  assert gradient_descent(np.array([]), np.array([])) == (0.0, 0.0)
  assert gradient_descent(np.array([1, 2, 3, 4, 5]), np.array([1, 3, 5, 7, 9])) == (2.0, -1.0)
output: def gradient_descent(x, y, learning_rate=0.01, iterations=100):
      m_curr = b_curr = 0
      n = len(x)
      for i in range(iterations):
          y_predicted = m_curr * x + b_curr
          cost = (1/n) * sum([val**2 for val in (y-y_predicted)])
          md = -(2/n)*sum(x*(y-y_predicted))
          bd = -(2/n)*sum(y-y_predicted)
          m_curr = m_curr - learning_rate * md
          b_curr = b_curr - learning_rate * bd
          print ("m {}, b {}, cost {} iteration {}".format(m_curr,b_curr,cost, i))
      return m_curr, b_curr