W2_A2_Ex-6_Normalize_Rows Note Correction

I’d like to correct the note in that exercise:

Note: Don’t try to use x /= x_norm. For the matrix division numpy must broadcast the x_norm, which is not supported by the operant /=

In reality, the /= is supported but the main issue here is the array data type, the tester passes in an integer array type while x_norm values are float types, and so to have it work, all what’s needed is to convert x to a float type.


Thank you for the careful analysis here! You’re right that the real problem is that the dataset type coercion rules are different for the “in-place” operators. It was quite a while ago when I worked this exercise, but I just used:

x = x / x_norm

instead of the “in-place” operator:

x /= x_norm

and it just worked, so I didn’t think any more about it. But now that you mention it and show your code change, your point is clear. You can tell that the course staff was just learning python when they implemented DLS back in 2017. The original Prof Ng ML course was in MATLAB/Octave and in MATLAB everything defaults to float types, instead of integers as in python. I will file a bug about this, but the problem is that changing the graders turns out to be hard to do for some reason. So it’s not likely that this will get fixed anytime soon.

Ah I see, that makes perfect sense. Thanks for caring and taking some time to try it out!

I guess its ok if it doesn’t get fixed anytime soon, more practice for the learner to solve it in a more manual fashion :grinning:

Just to follow up here, I did file the bug about this to get the instructions fixed. But there is another level of subtlety here: using “in place” operators like /=, +=, -= and so forth with numpy arrays has another potential downside. When you pass a numpy array or any other python “object” (as opposed to a simple scalar value) as a parameter to a function, it is passed “by reference” and not “by value”. In the case at hand here, that means that inside the local scope of the normalize_rows function, the variable x is actually a reference (pointer) to the same global object that was passed on the call to normalize_rows. That means if you use /= as you did in your code, you have overwritten the global variable, unless you take some action to prevent that. That would mean creating a local copy that is not a reference to the object that was passed. There are a number of ways to do that:

xlocal = x.copy()
xlocal = np.copy(x)
xlocal = np.array(x, copy = True)
xlocal = copy.deepcopy(x)

We will run into this issue later in the Week 3 and Week 4 assignments in DLS C1. Here’s a thread which explains the issue in more detail. Please read all the way through, not just the first post linked there.