Question about Gradient Descent Lab

Hi, I am a bit lost on this last optional lab of the week 1.

When we define gradient_descent, it involves cost_function and gradient_function. However, in the previous cells, we have only defined compute_cost and compute_gradient, so I am confused where we got the cost_function and gradient_function?

It seems to me that Python automatically recognizes these two functions, so are they part of any libraries? Some clarification here would greatly help, thanks!

Hi Sapphire_Hou,

as in many programming languages, the parameters of a function in python are just defined by its order. Such you have to pass a cost function to the function gradient_descent as the 7th parameter. Similarly you have to pass the function for computing the gradient as the 8th parameter.

The name you give it in the declaration_line (“def gradient_descent(…”) is just the name you use when calling the function from within the gradient_descent-function.

But take care that the definitions match!

When defininig compute_gradient you pass it 4 parameters (x,y,w,b in this order: 1st parameter is x, second is y, third is w, fourth is b)

When you call the gradient function from within the gradient_descent-function its name must be “gradient_function”.

The call of gradient_function in the function gradient_descent must match the definition of compute_gradient which we defined earlier.

Hope to have clarified something.


1 Like

Hi Holger_Prokoph,

Thanks for such a detailed explanation!

Just to make sure I understand correctly-- after I define something in the compute_XXX format, if then I want to utilize this newly defined function as a parameter within a new definition (e.g., compute_gradient within gradient_descent), I should type XXX_function (e.g., gradient_function) rather than compute_XXX (e.g., compute_gradient) as Python already knows I am referring to the function defined in the compute_XXX format right?

In other words, I just want to make sure if the following declaration line also works in this case:

def gradient_descent (x, y, w_in, b_in, alpha, num_iters, compute_cost, compute_gradient)

Thanks for your patience with a newbie!


The concept that’s being discussed here is called Higher Order Functions Higher Order Functions in Python - GeeksforGeeks

Let’s go through two examples from the GeeksforGeeks website (linked above) that are similar to your question.

# Python program to illustrate functions
# can be treated as objects
def shout(text):
	return text.upper()
yell = shout

The above shows us that we can make a function and assign a reference of it to another variable,
in this case the “yell”. We can then use yell as if it was the shout function. This is important for the next code example.

# Python program to illustrate functions
# can be passed as arguments to other functions
def shout(text):
    return text.upper()

def whisper(text):
    return text.lower()

def greet(func):
    # storing the function in a variable
    greeting = func("Hi, I am created by a function passed as an argument.")


In the second code example a function is being passed into another function and being called inside that function.
When the function is being passed into the other function think of it as similar to the first example where yell = shout. But this time func = shout or func = whisper depending on if it’s being called as greet(shout) or greet(whisper).
func exists inside the greet function and can be used as if it was the shout or whisper functions.

def gradient_descent(x, y, w_in, b_in, alpha, num_iters, cost_function, gradient_function)

Is the same as greet(func) only this time cost_function = compute_cost and gradient_function = compute_gradient when they are passed into the function.
This is done in the lab here:

w_final, b_final, J_hist, p_hist = gradient_descent(x_train ,y_train, w_init, b_init, tmp_alpha, 
                                                    iterations, compute_cost, compute_gradient)

Can the parameter functions have different names? Yes! all you have to do is use those new names in the function when you change them.
So if you change the method signature to:
def gradient_descent(x, y, w_in, b_in, alpha, num_iters, compute_cost, compute_gradient):
and gradient_descent is called like in the lab again:

w_final, b_final, J_hist, p_hist = gradient_descent(x_train ,y_train, w_init, b_init, tmp_alpha, 
                                                    iterations, compute_cost, compute_gradient)

then compute_cost (method variable) = compute_cost (function defined in lab) and compute_gradient (method variable) = compute_gradient (function defined in lab)
The method variables can now be used in the method as the functions passed into them.

Hope this clears things up!

1 Like

Hi Sam,

This makes much more sense to me, and I am glad to see how Holger’s response fits into a larger context in terms of the concept of higher order functions.

Thanks so much for both of you replying to this thread and your time :blush: