C1_W3 Lab Logistic Regression: Attribute error makes no sense [Solved]

Hello,

Why does my code for exercise 1 yield the following error when the result I got matches the expected. What am I doing wrong?

Result I got: [0.26894142 0.5 0.73105858 0.88079708]
Expected: [0.26894142 0.5 0.73105858 0.88079708]

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-49-11ebc8ea1ba1> in <module>
      3 # UNIT TESTS
      4 from public_tests import *
----> 5 sigmoid_test(sigmoid)

~/work/public_tests.py in sigmoid_test(target)
      8 
      9     g_scalar = target(3.0)
---> 10     assert g_scalar.shape == (), f"Scalar input should also output a scalar. Got shape {g_scalar.shape}"
     11 
     12     expected = 0.9525741268224334

AttributeError: 'float' object has no attribute 'shape'

My pseudocode:

check if z is an int or float.

--> if int/float: 
1. calculate sigmoid as normal and store into g

--> if not:
1. m = len(z)
2. create empty array of len(z) called temp_g
3. for every element in z, do temp_g[i] = 1 / (1+math.exp(-z[i]) [a for loop]
4. outside of the loop, g = temp_g

then return g

Edit:

So I used an AI LLM and they said to use np.exp instead of math.exp … how does one even come up with this :face_with_bags_under_eyes:. I thought that maybe the note “If the input is an array of numbers, we’d like to apply the sigmoid function to each value in the input array” was very misleading :sob:.

The error is because math.exp returns a plain Python float, which doesn’t have a .shape attribute. The unit test expects a NumPy scalar (which does have .shape == ()).

You also don’t need the if/else branching or the for loop at all. np.exp is vectorized, so it works on both scalars and arrays out of the box.

math.exp np.exp
Accepts arrays? No Yes
Scalar output type Python float (no .shape) numpy.float64 (has .shape)
Needs a loop? Yes, for arrays No

The sigmoid formula:

g(z) = \frac{1}{1 + e^{-z}}

can be implemented in one line using np.exp(-z) instead of math.exp(-z). NumPy handles the rest, whether z is a scalar or an array.

The note about “apply the sigmoid function to each value” was hinting at vectorization (using NumPy), not manual loops. It’s a common early gotcha, you’re on the right track.

Yeah, I definitely over complicated it. Just not used to using numpy because I was never allowed to use it in my discrete structures class… then I switched majors and never programmed in python again until now. Thank you for the explanation!