In the lines in the optional lab below
w = copy.deepcopy(w_in) # avoid modifying global w_in
# An array to store cost J and w's at each iteration primarily for graphing later
J_history = []
p_history = []
b = b_in
w = w_in
is the assignment w = w_in
doing what the comment says we want to avoid doing,
specifically modifying global w_in?
Thank you for this great class!
<Update: sorry, the following explanation is interesting, but missed the point of the question actually being asked. Be sure to also read my later reply below.>
The semantics of argument passing to functions in python can cause trouble if you’re not careful. Objects are passed “by reference” not “by value”. So if w_in is a numpy array, then what you are passing to the function is a reference to the global object. If you modify w_in within the function by using an “in place” operation like:
w_in -= ( ... some expression ...)
then you have modified the global value. That may or may not be a good thing, but that is a “side effect” of a function. Generally speaking, it’s always a better idea to make your functions “self-contained” meaning that they do not reference global variables even in “read-only” mode and to make sure that they don’t have side effects like modifying global objects, unless that is your explicit goal. What the “deepcopy” there does is make sure that you’ve created your own private copy of the object pointed to by w_in. The difference between simple copy and “deep” copy is that if the object itself contains object references, then you need the “deep” version. That is discussed more on the thread that I reference below. In the case of numpy arrays, the “deep” copy is not really necessary, but it doesn’t hurt to be on the safe side. If the object in question is a python dictionary containing numpy arrays, then the “deep” copy is definitely required. So maybe it’s better just to get in the habit of using deepcopy.
Here’s a thread from DLS which covers some examples like this. Make sure to also read this later post in that same thread which has another example of the nasty surprises you can get from python object references.
4 Likes
Oh, sorry, I missed your point in my explanation above. You’re right: that looks like a bug and it specifically defeats the purpose of the previous deepcopy. I’ll report the bug. What they meant to say was probably:
w_in = copy.deepcopy(w_in) # avoid modifying global w_in
# An array to store cost J and w's at each iteration primarily for graphing later
J_history = []
p_history = []
b = b_in
w = w_in
2 Likes
Thank you for the explanation. That was really helpful. I was wondering why only w was copied but b was not.
Because b is a scalar, so it is passed “by value”. But w is a numpy array, which is a python “object”, which means it is passed “by reference”.
Got you! Thank you so much!
hi.
I didn’t understand when you said w is a numpy array, because it’s not. It’s actually a scalar as it’s mentioned in comments in the lab.
Hi @Ehsan_10537,
It is true that you are seeing the case where w
is a scalar, but when you have more than one feature, the w
will be an array. I think the take-away for this discussion is, how can we make sure we do not modify the global w
inside a function when such modification is not expected. The use of deepcopy can achieve that, and although it is not needed by a python scalar, it does not harm to apply the same technique.
Raymond