Logistic Classification
Logistic Predict (Given Weights)
Classify rows using given weights w and bias b (no training). For each row: z = dot(w,x)+b; p = sigmoid(z); class = 1 if p>=0.5 else 0. Library: NumPy matrix multiply X@w+b, then scipy.special.expit and threshold. RESULT: list of predicted classes (0/1).
By hand
w=[1.0,−1.0], b=0.0. X=[[2,1],[1,3],[4,2]]. z: 2−1=1, 1−3=−2, 4−2=2. p: 0.7311, 0.1192, 0.8808. Threshold 0.5 → classes: 1, 0, 1.
naive.py
Replay: real traced execution (multi-file project)
import math
w = [1.0, -1.0]
b = 0.0
X = [[2, 1], [1, 3], [4, 2]]
classes = []
for row in X:
z = w[0] * row[0] + w[1] * row[1] + b
p = 1 / (1 + math.exp(-z))
c = 1 if p >= 0.5 else 0
classes.append(c)
print('RESULT:', classes)
import math
1import math2w = [1.0, -1.0]w ← [1.0, -1.0]
1import math2w = [1.0, -1.0]3b = 0.0values this step[1.0, -1.0]wb ← 0.0
2w = [1.0, -1.0]3b = 0.04X = [[2, 1], [1, 3], [4, 2]]values this step0.0bX ← [[2, 1], [1, 3], [4, 2]]
3b = 0.04X = [[2, 1], [1, 3], [4, 2]]5classes = []values this step[[2, 1], [1, 3], [4, 2]]Xclasses ← []
4X = [[2, 1], [1, 3], [4, 2]]5classes = []6for row in X:values this step[]classesrow ← [2, 1]
5classes = []6for row in X:7 z = w[0] * row[0] + w[1] * row[1] + bvalues this step[2, 1]rowz ← 1.0
6for row in X:7 z = w[0] * row[0] + w[1] * row[1] + b8 p = 1 / (1 + math.exp(-z))values this step1.0zp ← 0.7310585786300049
7z = w[0] * row[0] + w[1] * row[1] + b8p = 1 / (1 + math.exp(-z))9c = 1 if p >= 0.5 else 0values this step0.7310585786300049pc ← 1
8p = 1 / (1 + math.exp(-z))9c = 1 if p >= 0.5 else 010classes.append(c)values this step1cclasses ← [1]
9 c = 1 if p >= 0.5 else 010 classes.append(c)11print('RESULT:', classes)values this step[] → [1]classesrow ← [1, 3]
5classes = []6for row in X:7 z = w[0] * row[0] + w[1] * row[1] + bvalues this step[2, 1] → [1, 3]rowz ← -2.0
6for row in X:7 z = w[0] * row[0] + w[1] * row[1] + b8 p = 1 / (1 + math.exp(-z))values this step1.0 → -2.0zp ← 0.11920292202211755
7z = w[0] * row[0] + w[1] * row[1] + b8p = 1 / (1 + math.exp(-z))9c = 1 if p >= 0.5 else 0values this step0.7310585786300049 → 0.11920292202211755pc ← 0
8p = 1 / (1 + math.exp(-z))9c = 1 if p >= 0.5 else 010classes.append(c)values this step1 → 0cclasses ← [1, 0]
9 c = 1 if p >= 0.5 else 010 classes.append(c)11print('RESULT:', classes)values this step[1] → [1, 0]classesrow ← [4, 2]
5classes = []6for row in X:7 z = w[0] * row[0] + w[1] * row[1] + bvalues this step[1, 3] → [4, 2]rowz ← 2.0
6for row in X:7 z = w[0] * row[0] + w[1] * row[1] + b8 p = 1 / (1 + math.exp(-z))values this step-2.0 → 2.0zp ← 0.8807970779778823
7z = w[0] * row[0] + w[1] * row[1] + b8p = 1 / (1 + math.exp(-z))9c = 1 if p >= 0.5 else 0values this step0.11920292202211755 → 0.8807970779778823pc ← 1
8p = 1 / (1 + math.exp(-z))9c = 1 if p >= 0.5 else 010classes.append(c)values this step0 → 1cclasses ← [1, 0, 1]
9 c = 1 if p >= 0.5 else 010 classes.append(c)11print('RESULT:', classes)values this step[1, 0] → [1, 0, 1]classesfor row in X:
5classes = []6for row in X:7 z = w[0] * row[0] + w[1] * row[1] + bstdout ← RESULT: [1, 0, 1]
10 classes.append(c)11print('RESULT:', classes)values this stepRESULT: [1, 0, 1]stdout
With NumPy
X @ w + b computes all dot products in one vectorized step. expit
applies sigmoid element-wise; list comprehension thresholds at 0.5.
library.py
import numpy as np
from scipy.special import expit
from dalib.display import set_display
set_display()
w = np.array([1.0, -1.0])
b = 0.0
X = np.array([[2, 1], [1, 3], [4, 2]])
z = X @ w + b
raw_probs = expit(z)
probs = [round(float(p), 4) for p in raw_probs]
classes = [1 if float(p) >= 0.5 else 0 for p in raw_probs]
print('z scores:', [round(float(v), 4) for v in z])
print('probs:', probs)
print('RESULT:', classes)
z scores: [1.0, -2.0, 2.0]
probs: [0.7311, 0.1192, 0.8808]
RESULT: [1, 0, 1]
Implementation notes
- Weights are given, not trained — this lesson isolates the predict step. Training (e.g. gradient descent on log-loss) is a separate concern.
- The linear score z = dot(w,x)+b is the same as in linear regression;
sigmoid converts it to a probability. Cross-reference:
normal-equation-1d(ch03) for the linear-score part. - Threshold 0.5 corresponds to z=0 (s(0)=0.5). Different thresholds trade precision against recall — not shown here.
X @ wrequires X as a 2D numpy array and w as a 1D array; the result is a 1D array of scores, one per row.- Cross-reference:
sigmoid-function(this chapter) for the activation; sklearn'sLogisticRegression.predict_probawraps the same computation after fitting.