You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

158 KiB

None <html lang="en"> <head> </head>
In [2]:
import numpy as np 
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv("iris_basic.csv")
print(df.head())
    sl   sw   pl   pw  target  tNames
0  5.1  3.5  1.4  0.2       0  setosa
1  4.9  3.0  1.4  0.2       0  setosa
2  4.7  3.2  1.3  0.2       0  setosa
3  4.6  3.1  1.5  0.2       0  setosa
4  5.0  3.6  1.4  0.2       0  setosa
In [3]:
x = df["pw"].to_numpy().reshape(-1, 1)      # (150,1)
x
Out[3]:
array([[0.2],
       [0.2],
       [0.2],
       [0.2],
       [0.2],
       [0.4],
       [0.3],
       [0.2],
       [0.2],
       [0.1],
       [0.2],
       [0.2],
       [0.1],
       [0.1],
       [0.2],
       [0.4],
       [0.4],
       [0.3],
       [0.3],
       [0.3],
       [0.2],
       [0.4],
       [0.2],
       [0.5],
       [0.2],
       [0.2],
       [0.4],
       [0.2],
       [0.2],
       [0.2],
       [0.2],
       [0.4],
       [0.1],
       [0.2],
       [0.2],
       [0.2],
       [0.2],
       [0.1],
       [0.2],
       [0.2],
       [0.3],
       [0.3],
       [0.2],
       [0.6],
       [0.4],
       [0.3],
       [0.2],
       [0.2],
       [0.2],
       [0.2],
       [1.4],
       [1.5],
       [1.5],
       [1.3],
       [1.5],
       [1.3],
       [1.6],
       [1. ],
       [1.3],
       [1.4],
       [1. ],
       [1.5],
       [1. ],
       [1.4],
       [1.3],
       [1.4],
       [1.5],
       [1. ],
       [1.5],
       [1.1],
       [1.8],
       [1.3],
       [1.5],
       [1.2],
       [1.3],
       [1.4],
       [1.4],
       [1.7],
       [1.5],
       [1. ],
       [1.1],
       [1. ],
       [1.2],
       [1.6],
       [1.5],
       [1.6],
       [1.5],
       [1.3],
       [1.3],
       [1.3],
       [1.2],
       [1.4],
       [1.2],
       [1. ],
       [1.3],
       [1.2],
       [1.3],
       [1.3],
       [1.1],
       [1.3],
       [2.5],
       [1.9],
       [2.1],
       [1.8],
       [2.2],
       [2.1],
       [1.7],
       [1.8],
       [1.8],
       [2.5],
       [2. ],
       [1.9],
       [2.1],
       [2. ],
       [2.4],
       [2.3],
       [1.8],
       [2.2],
       [2.3],
       [1.5],
       [2.3],
       [2. ],
       [2. ],
       [1.8],
       [2.1],
       [1.8],
       [1.8],
       [1.8],
       [2.1],
       [1.6],
       [1.9],
       [2. ],
       [2.2],
       [1.5],
       [1.4],
       [2.3],
       [2.4],
       [1.8],
       [1.8],
       [2.1],
       [2.4],
       [2.3],
       [1.9],
       [2.3],
       [2.5],
       [2.3],
       [1.9],
       [2. ],
       [2.3],
       [1.8]])
In [4]:
y = df["target"].to_numpy().reshape(-1, 1)  # (150,1)
y = (y == 0).astype(float) 
y
Out[4]:
array([[1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [1.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.],
       [0.]])
In [5]:
def sigmoid(z):
    z = np.clip(z, -500, 500)
    sig = 1.0 / (1.0 + np.exp(-z))
    return sig
In [6]:
def log_loss(y, p, eps=1e-12):
    p = np.clip(p, eps, 1 - eps)
    return -np.mean(y*np.log(p) + (1-y)*np.log(1-p))
In [7]:
lr=0.1
epochs=2000 
l2=0.0,
X = np.column_stack([x, np.ones_like(x)])
m = X.shape[0]
theta = np.zeros((2,1))
theta
Out[7]:
array([[0.],
       [0.]])
In [8]:
X.T
Out[8]:
array([[0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.2, 0.1,
        0.1, 0.2, 0.4, 0.4, 0.3, 0.3, 0.3, 0.2, 0.4, 0.2, 0.5, 0.2, 0.2,
        0.4, 0.2, 0.2, 0.2, 0.2, 0.4, 0.1, 0.2, 0.2, 0.2, 0.2, 0.1, 0.2,
        0.2, 0.3, 0.3, 0.2, 0.6, 0.4, 0.3, 0.2, 0.2, 0.2, 0.2, 1.4, 1.5,
        1.5, 1.3, 1.5, 1.3, 1.6, 1. , 1.3, 1.4, 1. , 1.5, 1. , 1.4, 1.3,
        1.4, 1.5, 1. , 1.5, 1.1, 1.8, 1.3, 1.5, 1.2, 1.3, 1.4, 1.4, 1.7,
        1.5, 1. , 1.1, 1. , 1.2, 1.6, 1.5, 1.6, 1.5, 1.3, 1.3, 1.3, 1.2,
        1.4, 1.2, 1. , 1.3, 1.2, 1.3, 1.3, 1.1, 1.3, 2.5, 1.9, 2.1, 1.8,
        2.2, 2.1, 1.7, 1.8, 1.8, 2.5, 2. , 1.9, 2.1, 2. , 2.4, 2.3, 1.8,
        2.2, 2.3, 1.5, 2.3, 2. , 2. , 1.8, 2.1, 1.8, 1.8, 1.8, 2.1, 1.6,
        1.9, 2. , 2.2, 1.5, 1.4, 2.3, 2.4, 1.8, 1.8, 2.1, 2.4, 2.3, 1.9,
        2.3, 2.5, 2.3, 1.9, 2. , 2.3, 1.8],
       [1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. ,
        1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. ,
        1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. ,
        1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. ,
        1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. ,
        1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. ,
        1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. ,
        1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. ,
        1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. ,
        1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. ,
        1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. ,
        1. , 1. , 1. , 1. , 1. , 1. , 1. ]])
In [9]:
for i in range(epochs):
    z = X @ theta               # (m,1)
    h = sigmoid(z)              # (m,1)
    grad = (X.T @ (h - y)) / m  # (2,1)  <-- from your formula
    theta -= lr * grad

    #if (i % 0 == 0 or t == epochs-1):
     #   print(f"{i:4d}  loss={log_loss(y, h):.6f}  w={theta[0,0]:.6f}  b={theta[1,0]:.6f}")

w, b = theta[0,0], theta[1,0]
In [10]:
def predict_proba(x, w, b):
    x = np.asarray(x, float).reshape(-1)
    return sigmoid(w*x + b)

def predict(x, w, b, thresh=0.5):
    return (predict_proba(x, w, b) >= thresh).astype(int)
In [11]:
rng = np.random.default_rng(0)
m = 120
xNew = np.linspace(-0.5, 2.5, m)
p = predict_proba(xNew, w, b)
print(f"\nLearned: w={w:.3f}, b={b:.3f}, loss={log_loss(p.reshape(-1,1), p.reshape(-1,1)):.4f}")
Learned: w=-5.989, b=4.279, loss=0.1812
In [12]:
yJitter = y +np.random.uniform(-0.2, 0.2, size=y.shape)
plt.plot(x, yJitter, 'ok', alpha=0.1)
plt.plot(xNew,p)
Out[12]:
[<matplotlib.lines.Line2D at 0x114864980>]
No description has been provided for this image

Multi-Parametric Binary Classifier

In [13]:
x1 = df["sl"].to_numpy()
x2 = df["sw"].to_numpy()
X = np.column_stack([ np.ones_like(x1), x1, x2])
In [14]:
y = df["target"].to_numpy()
#y = (y == 2).astype(float) 
In [15]:
plt.plot(x1[y==0], x2[y==0],'.g' ,label='Set')
plt.plot(x1[y==1], x2[y==1],'.r', label='Ver')
plt.plot(x1[y==2], x2[y==2],'.b', label='Vir')
plt.legend()
plt.show()
No description has been provided for this image
In [16]:
y = df["target"].to_numpy()
y = (y == 2).astype(float) 
In [17]:
def predict_proba(X, theta):
    z = X@theta
    return sigmoid(z)
In [18]:
lr=0.01
epochs=5000
m = X.shape[0]
theta = np.random.randn(3)
theta
Out[18]:
array([-0.88031462,  0.80365083, -0.29048474])
In [19]:
for i in range(epochs):
    z = X @ theta               # (m,1)
    h = 1/(1+np.exp(-z))              # (m,1)
    grad = (X.T @ (h - y)) / m  # (2,1)  <-- from your formula
    theta -= lr * grad

    if (i % 100 == 0):
        print(f"{i:4d}  loss={log_loss(y, h):.6f}")
 
theta
   0  loss=1.808011
 100  loss=0.546449
 200  loss=0.539039
 300  loss=0.532486
 400  loss=0.526668
 500  loss=0.521482
 600  loss=0.516842
 700  loss=0.512674
 800  loss=0.508917
 900  loss=0.505520
1000  loss=0.502438
1100  loss=0.499632
1200  loss=0.497071
1300  loss=0.494726
1400  loss=0.492573
1500  loss=0.490592
1600  loss=0.488763
1700  loss=0.487072
1800  loss=0.485503
1900  loss=0.484045
2000  loss=0.482687
2100  loss=0.481420
2200  loss=0.480235
2300  loss=0.479124
2400  loss=0.478080
2500  loss=0.477099
2600  loss=0.476174
2700  loss=0.475301
2800  loss=0.474475
2900  loss=0.473693
3000  loss=0.472951
3100  loss=0.472246
3200  loss=0.471574
3300  loss=0.470934
3400  loss=0.470323
3500  loss=0.469739
3600  loss=0.469180
3700  loss=0.468644
3800  loss=0.468130
3900  loss=0.467636
4000  loss=0.467160
4100  loss=0.466702
4200  loss=0.466259
4300  loss=0.465833
4400  loss=0.465420
4500  loss=0.465020
4600  loss=0.464633
4700  loss=0.464258
4800  loss=0.463893
4900  loss=0.463539
Out[19]:
array([-1.86106309,  1.17821204, -1.9398732 ])
In [20]:
x1New, x2New = np.meshgrid(
    np.linspace(3,8,100).reshape(-1,1),
    np.linspace(0,6,100).reshape(-1,1))
XNew = np.column_stack([np.ones(x1New.size), x1New.ravel(), x2New.ravel()])

z = XNew @ theta
yPred = 1 / (1 + np.exp(-z))
zz = yPred.reshape(x1New.shape)
zz
Out[20]:
array([[8.42051618e-01, 8.49805795e-01, 8.57243833e-01, ...,
        9.99416348e-01, 9.99450047e-01, 9.99481801e-01],
       [8.25779343e-01, 8.34175058e-01, 8.42243475e-01, ...,
        9.99343580e-01, 9.99381478e-01, 9.99417189e-01],
       [8.08212477e-01, 8.17267413e-01, 8.25986882e-01, ...,
        9.99261747e-01, 9.99304366e-01, 9.99344527e-01],
       ...,
       [5.94372475e-05, 6.30812203e-05, 6.69485824e-05, ...,
        1.87344113e-02, 1.98602389e-02, 2.10522706e-02],
       [5.28448157e-05, 5.60846430e-05, 5.95230868e-05, ...,
        1.66910746e-02, 1.76963241e-02, 1.87609615e-02],
       [4.69835435e-05, 4.98640439e-05, 5.29211347e-05, ...,
        1.48672252e-02, 1.57643912e-02, 1.67147783e-02]], shape=(100, 100))
In [21]:
plt.figure(figsize=(8,6))
plt.plot(x1[y==0], x2[y==0],'or' ,label='No Virg')
plt.plot(x1[y==1], x2[y==1],'g^',label='Virginica')
contour = plt.contour(x1New,x2New,zz, linewidths=1)
plt.clabel(contour, inline=1,fontsize=15)
plt.xlabel("Sepal Length")
plt.ylabel("Sepal Width")
plt.legend()
plt.show()
No description has been provided for this image
In [22]:
# Softmax model ???
</html>