DLS C4, wk4, lab "Face Recognition", grader fails me - all outputs and code are correct

DLS C4, wk4, lab “Face Recognition”, grader fails me - all outputs and code are correct.

I got all outputs as expected and the I am sure my code is correct.

When I submitted the assignment the grader gave me just 66% and gave the following feedback:

“Code Cell UNQ_C2: Unexpected error (TypeError(“ufunc ‘isfinite’ not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ‘‘safe’’”)) occurred during function check. We expected function verify to return verify test 1 failed. Please check that this function is defined properly.”

Please help.

That’s a pretty clear indication there’s a problem in your code, regardless of how sure you are that it’s correct.

Not all errors are caught by the notebook’s built-in test cases.

If you search the forums for that error string, you find lots of hits, including this one which seems worth a look.

@TMosh,

Thank you.

In the function np.linalg.norm() I had set axis=-1 as a parameter earlier and it didn’t complain at all - and even the output was as expected (probably the distance calculated was still ok).

I just removed the parameter “axis”, and used ord=2, and it gave the same expected output again. But this time the grader accepted the submission and it’s a success.

It’d be better to add a check in the graded cell for this issue.

Also, could you please post a short tutorial/link where I can read/practise the different norms (using Python)?

I tried making the same mistake that you list there: adding axis = -1 to the np.linalg.norm call in verify and the tests fail for me with the exact same message you show from the grader:

with tf.norm dist = 0.5436482429504395
with np.linalg.norm dist = [0.54364824]
Dist for bertrand = [0.54364824]
It's bertrand, welcome in!
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-18-02e2f1840f11> in <module>
----> 1 assert(np.allclose(verify("images/camera_1.jpg", "bertrand", database, FRmodel), (0.54364836, True)))
      2 assert(np.allclose(verify("images/camera_3.jpg", "bertrand", database, FRmodel), (0.38616243, True)))
      3 assert(np.allclose(verify("images/camera_1.jpg", "younes", database, FRmodel), (1.3963861, False)))
      4 assert(np.allclose(verify("images/camera_3.jpg", "younes", database, FRmodel), (1.3872949, False)))
      5 

<__array_function__ internals> in allclose(*args, **kwargs)

/opt/conda/lib/python3.7/site-packages/numpy/core/numeric.py in allclose(a, b, rtol, atol, equal_nan)
   2157 
   2158     """
-> 2159     res = all(isclose(a, b, rtol=rtol, atol=atol, equal_nan=equal_nan))
   2160     return bool(res)
   2161 

<__array_function__ internals> in isclose(*args, **kwargs)

/opt/conda/lib/python3.7/site-packages/numpy/core/numeric.py in isclose(a, b, rtol, atol, equal_nan)
   2255     y = array(y, dtype=dt, copy=False, subok=True)
   2256 
-> 2257     xfin = isfinite(x)
   2258     yfin = isfinite(y)
   2259     if all(xfin) and all(yfin):

TypeError: ufunc 'isfinite' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

The key thing to note is that

[0.54364824] is not the same thing as 0.54364824: the former is a numpy array, whereas the latter is a python scalar, even though the values may be the same.

It is the case in all of the various numpy primitives that take arrays as input that specifying the axis parameter means you are telling it to do the operation only along that axis and to return the result as an array. Try it with np.sum for example:

np.random.seed(42)
A = np.random.randint(0, 10, (2,3))
print(f"A =\n{A}")
print(f"np.sum(A, axis = -1) = {np.sum(A, axis = -1)}")
print(f"np.sum(A) = {np.sum(A)}")
A =
[[6 3 7]
 [4 6 9]]
np.sum(A, axis = -1) = [16 19]
np.sum(A) = 35

So you can see that what happened was that it took the sum “across the columns” in the axis = -1 case (sum across the last axis). So we end up with a (2,) 1D array with the sums of the rows. Without the axis specified, it sums the entire array and returns a scalar.

Now watch and see that you get the same idea with np.linalg.norm:

print(f"np.linalg.norm(A, axis = -1) = {np.linalg.norm(A, axis = -1)}")
print(f"np.linalg.norm(A) = {np.linalg.norm(A)}")
np.linalg.norm(A, axis = -1) = [ 9.69535971 11.53256259]
np.linalg.norm(A) = 15.066519173319364

We get the norms of the rows in the axis = -1 case.