Can Sigmoid(z) be straight line?

I am trying to build a model and do Sigmoid(z) vs Z plotting with the following code,

import numpy as np
%matplotlib widget
import matplotlib.pyplot as plt
from plt_one_addpt_onclick import plt_one_addpt_onclick
from lab_utils_common import plot_data, sigmoid, draw_vthresh
plt.style.use('./deeplearning.mplstyle')

X = np.array([[0.5, 1.5], [1,1], [1.5, 0.5], [3, 0.5], [2, 2], [1, 2.5]])
y = np.array([0, 0, 0, 1, 1, 1])
w = np.array([1,1])
b = -3

def compute_z(x,w,b):
    m = x.shape[0]
    z_i = np.zeros(m)
    for i in range(m):
        z_i[i] = np.dot(x[i],w) + b
    
    return z_i

z = compute_z(X,w,b)
s_z = sigmoid(z)
fig,ax = plt.subplots(1,1,figsize=(5,3))

# Plot z vs sigmoid(z)
ax.plot(z, s_z, c="b")

ax.set_title("Sigmoid function")
ax.set_ylabel('sigmoid(z)')
ax.set_xlabel('z')
draw_vthresh(ax,0)

When the graph is plotted I see the Sigmoid as straight line ? Can Sigmoid be a straight line or is there anything wrong with my impl ?

Regards,
Kamesh

Sigmoid is clearly not a straight line, so there must be something wrong with your methodology. For starters, note that your first four X values will all give the same value of z when w = [1,1], right?

2 Likes

Try not using a for-loop with a dot product inside it.
That’s doubly-redundant.

2 Likes

Kamesh, Paul’s check is the first thing we should do. The first three X values give us the same z, but how many different z do we expect to have? With such number of different points, can we see a curve easily?

thanks @paulinpaloalto and @rmwkwok

TMosh - thanks for the tip, I updated my method to be like ( was kind of trying some thing :smiley: )

def compute_z(x,w,b):
    return np.dot(x,w) + b

@paulinpaloalto and @rmwkwok ,

Here is the output of z and sigmoid(z) for my example data, I see the first three values of Z and its corresponding g(z) is same inline with your comment earlier.

z:[-1.  -1.  -1.   0.5  1.   0.5]
sigmoid(z):[0.269 0.269 0.269 0.622 0.731 0.622]

But it is really weird why plot is coming as straightline instead of s kind of line,

  • Is it because of number of points is less?
  • Am I plotting it wrongly ?

Any thoughts ?

In your line def compute_z(x,w,b), why is the ‘b’ in a red font? Is that a syntax error?

So, you are trying to observe a curve with just three different points. Here are two things you can do:

  1. add 6 more points where z = -2, -1.5, -0.5, 0, 1.5, 2 respectively. This way you have evenly distributed points along z from -2 to 2.

  2. check out the graph below:

Cheers,
Raymond

I can try with extra data points.

But the image you attached seem to be straight line plot right ? or am I seeing it wrong?

No, it is not a straight line. Please do add those points.

1 Like

yeah, I fixed after the copy

that did not help @rmwkwok I am still not able to observe the curve. Not sure what am I missing :frowning:

@kameshsampath, could you share the latest code and graph like you did in your first post in this thread?

Maybe test your plotting separately from the sigmoid function by just plotting these points. They should form a parabola.
-3,9
-2,4
-1,1
0,0
1,1
2,4
3,9

I think you are missing the point about why that is a problem. Think about it: there are really only 3 distinct points there. So you are drawing the graph based on just 3 points. How is that possibly going to show the full curvature of the sigmoid function? So, yes, you need to modify your input data to provide more variety. What is the point (pun intended) of including duplicate points?

1 Like

A more sophisticated and realistic approach would be to use an evenly spaced range of values, e.g.:

X = np.linspace(-5, 5, num=100)

thanks @paulinpaloalto trying with a bigger dataset and more data points.

Here is something I tried now with a bigger data set,

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

def sigmoid(z):
    """
    Compute the sigmoid of z

    Args:
     z (ndarray) : A scalar, numpy array of any size

    Returns:
     g(ndarray): sigmoid(z), with the same shape as z
    """

    g_z = 1/(1+ np.exp(-z))

    return g_z

def load_data(filename):
    data = np.loadtxt(filename, delimiter=',')
    X = data[:,:2]
    y = data[:,2]
    return X, y

X,_ = load_data('./data/ex2data2.txt')
w = np.array([1,1])
b = -3

z = np.dot(X,w)+ b
# disregard duplicates
z = np.unique(z)
g_z = sigmoid(z)

# just printing some samples
print(f"z:{z[:5]}")
print(f"sigmoid(z):{g_z[:20]}")

plt.plot(z,g_z,c="b")
plt.title("Sigmoid Function")
plt.xlabel("z")
plt.ylabel("$g(z)$")
plt.show()

The dataset I used is from Sample data for sigmoid plotting · GitHub

And got a plot like this. Does this seem to be right ?

output2

That probably is correct for that domain of the function, but you really need to include something like the range I suggested from -5 to 5 to see the full shape of sigmoid. Note that I mean that as the range for z, not for x.

Note that your choice of b = -3 and w = [1,1] is going to skew the results in the negative direction.

I would start by just graphing sigmoid without the z = x \cdot w + b first just to see the shape of sigmoid. Then take the next step of figuring out what range of x values you need to cover the domain [-5, 5] for the inputs to sigmoid.

I agree with Paul. @kameshsampath, can you change the following line

X,_ = load_data('./data/ex2data2.txt')

into

X = np.array([ [-2, 0], [-1, 0], [0, 0], [1, 0], [2, 0], [3, 0], [4, 0], [5, 0], [6, 0], [7, 0], [8, 0] ])

This will give you a dataset that will span from z = -5 to x = 5.

1 Like