1.4 - Africa

Ghana (~500) -> Mali (~1200) -> Songhay Empire (1464 - 1591)

Sunni Ali = Songhay Ruler
Gao = Capital of Songhay empire

Africa is very diverse

To solve Exercise 2, we need to take the partial derivatives of the loss function with respect to both parameters, (\theta_0) and (\theta_1). The loss function is given by:

[ L(\Theta) = \frac{1}{2m}\sum_{i=1}^m (f_\Theta(x^i) - y^i)^2 ]

where ( f_\Theta(x^i) = \theta_0 + \theta_1 x^i ).

Partial Derivative with Respect to (\theta_0)

Taking the derivative of the loss function with respect to (\theta_0) gives us the gradient component for (\theta_0). This tells us how the loss changes as (\theta_0) changes. The derivative is:

[ \frac{\partial L}{\partial \theta_0} = \frac{1}{m} \sum_{i=1}^m (f_\Theta(x^i) - y^i) ]

This expression comes from the chain rule, considering that the derivative of ( f_\Theta(x^i) ) with respect to (\theta_0) is 1.

Partial Derivative with Respect to (\theta_1)

Similarly, the derivative of the loss function with respect to (\theta_1) gives us the gradient component for (\theta_1), indicating how the loss changes as (\theta_1) changes. The derivative is:

[ \frac{\partial L}{\partial \theta_1} = \frac{1}{m} \sum_{i=1}^m (f_\Theta(x^i) - y^i) \cdot x^i ]

Here, the derivative of ( f_\Theta(x^i) ) with respect to (\theta_1) is (x^i), again applying the chain rule.

Gradient Calculation Function

Now, to implement the calculate_gradient function, we use these derivatives to compute the gradient with respect to both (\theta_0) and (\theta_1). This gradient tells us in which direction to adjust our parameters to minimize the loss.

def calculate_gradient(X, y, theta):
  m = len(y)  # Number of data points
  y_hat = predict(X, theta)  # Predicted values using current theta

  # Gradient with respect to theta_0
  dL_d0 = np.sum(y_hat - y) / m

  # Gradient with respect to theta_1
  dL_d1 = np.sum((y_hat - y) * X) / m

  # Full gradient as a tuple
  nabla = (dL_d0, dL_d1)
  return nabla

This function calculates the gradients for both parameters and returns them as a tuple. These gradients can then be used in a gradient descent algorithm to iteratively update (\theta_0) and (\theta_1) in the opposite direction of the gradient, aiming to find the parameters that minimize the loss.