From c4e9b59bed95221642d9532a504299f0303a4313 Mon Sep 17 00:00:00 2001 From: Gerardo Marx Date: Mon, 20 Oct 2025 10:26:58 -0600 Subject: [PATCH] basic binary classifier --- Readme.md | 499 +++++++++++++++++++++++++++++++ main.ipynb | 612 +++++++++++++++++++++++++++++++++++++++ main_files/main_10_1.png | Bin 0 -> 22252 bytes 3 files changed, 1111 insertions(+) create mode 100644 Readme.md create mode 100644 main.ipynb create mode 100644 main_files/main_10_1.png diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..f82845c --- /dev/null +++ b/Readme.md @@ -0,0 +1,499 @@ +```python +#!pip3 install scikit-learn +from sklearn import datasets +iris = datasets.load_iris() +print(iris.DESCR) + +``` + + .. _iris_dataset: + + Iris plants dataset + -------------------- + + **Data Set Characteristics:** + + :Number of Instances: 150 (50 in each of three classes) + :Number of Attributes: 4 numeric, predictive attributes and the class + :Attribute Information: + - sepal length in cm + - sepal width in cm + - petal length in cm + - petal width in cm + - class: + - Iris-Setosa + - Iris-Versicolour + - Iris-Virginica + + :Summary Statistics: + + ============== ==== ==== ======= ===== ==================== + Min Max Mean SD Class Correlation + ============== ==== ==== ======= ===== ==================== + sepal length: 4.3 7.9 5.84 0.83 0.7826 + sepal width: 2.0 4.4 3.05 0.43 -0.4194 + petal length: 1.0 6.9 3.76 1.76 0.9490 (high!) + petal width: 0.1 2.5 1.20 0.76 0.9565 (high!) + ============== ==== ==== ======= ===== ==================== + + :Missing Attribute Values: None + :Class Distribution: 33.3% for each of 3 classes. + :Creator: R.A. Fisher + :Donor: Michael Marshall (MARSHALL%PLU@io.arc.nasa.gov) + :Date: July, 1988 + + The famous Iris database, first used by Sir R.A. Fisher. The dataset is taken + from Fisher's paper. Note that it's the same as in R, but not as in the UCI + Machine Learning Repository, which has two wrong data points. + + This is perhaps the best known database to be found in the + pattern recognition literature. Fisher's paper is a classic in the field and + is referenced frequently to this day. (See Duda & Hart, for example.) The + data set contains 3 classes of 50 instances each, where each class refers to a + type of iris plant. One class is linearly separable from the other 2; the + latter are NOT linearly separable from each other. + + .. dropdown:: References + + - Fisher, R.A. "The use of multiple measurements in taxonomic problems" + Annual Eugenics, 7, Part II, 179-188 (1936); also in "Contributions to + Mathematical Statistics" (John Wiley, NY, 1950). + - Duda, R.O., & Hart, P.E. (1973) Pattern Classification and Scene Analysis. + (Q327.D83) John Wiley & Sons. ISBN 0-471-22361-1. See page 218. + - Dasarathy, B.V. (1980) "Nosing Around the Neighborhood: A New System + Structure and Classification Rule for Recognition in Partially Exposed + Environments". IEEE Transactions on Pattern Analysis and Machine + Intelligence, Vol. PAMI-2, No. 1, 67-71. + - Gates, G.W. (1972) "The Reduced Nearest Neighbor Rule". IEEE Transactions + on Information Theory, May 1972, 431-433. + - See also: 1988 MLC Proceedings, 54-64. Cheeseman et al"s AUTOCLASS II + conceptual clustering system finds 3 classes in the data. + - Many, many more ... + + + + +```python +import numpy as np +import matplotlib.pyplot as plt +x = iris.data[:,3:4] +y = (iris.target == 0).astype(int).reshape(-1,1) +y +``` + + + + + 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]]) + + + + +```python +def sigmoid(z): + z = np.clip(z, -500, 500) + sig = 1.0 / (1.0 + np.exp(-z)) + return sig +``` + + +```python +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)) +``` + + +```python +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)) +``` + + +```python +X +``` + + + + + array([[0.2, 1. ], + [0.2, 1. ], + [0.2, 1. ], + [0.2, 1. ], + [0.2, 1. ], + [0.4, 1. ], + [0.3, 1. ], + [0.2, 1. ], + [0.2, 1. ], + [0.1, 1. ], + [0.2, 1. ], + [0.2, 1. ], + [0.1, 1. ], + [0.1, 1. ], + [0.2, 1. ], + [0.4, 1. ], + [0.4, 1. ], + [0.3, 1. ], + [0.3, 1. ], + [0.3, 1. ], + [0.2, 1. ], + [0.4, 1. ], + [0.2, 1. ], + [0.5, 1. ], + [0.2, 1. ], + [0.2, 1. ], + [0.4, 1. ], + [0.2, 1. ], + [0.2, 1. ], + [0.2, 1. ], + [0.2, 1. ], + [0.4, 1. ], + [0.1, 1. ], + [0.2, 1. ], + [0.2, 1. ], + [0.2, 1. ], + [0.2, 1. ], + [0.1, 1. ], + [0.2, 1. ], + [0.2, 1. ], + [0.3, 1. ], + [0.3, 1. ], + [0.2, 1. ], + [0.6, 1. ], + [0.4, 1. ], + [0.3, 1. ], + [0.2, 1. ], + [0.2, 1. ], + [0.2, 1. ], + [0.2, 1. ], + [1.4, 1. ], + [1.5, 1. ], + [1.5, 1. ], + [1.3, 1. ], + [1.5, 1. ], + [1.3, 1. ], + [1.6, 1. ], + [1. , 1. ], + [1.3, 1. ], + [1.4, 1. ], + [1. , 1. ], + [1.5, 1. ], + [1. , 1. ], + [1.4, 1. ], + [1.3, 1. ], + [1.4, 1. ], + [1.5, 1. ], + [1. , 1. ], + [1.5, 1. ], + [1.1, 1. ], + [1.8, 1. ], + [1.3, 1. ], + [1.5, 1. ], + [1.2, 1. ], + [1.3, 1. ], + [1.4, 1. ], + [1.4, 1. ], + [1.7, 1. ], + [1.5, 1. ], + [1. , 1. ], + [1.1, 1. ], + [1. , 1. ], + [1.2, 1. ], + [1.6, 1. ], + [1.5, 1. ], + [1.6, 1. ], + [1.5, 1. ], + [1.3, 1. ], + [1.3, 1. ], + [1.3, 1. ], + [1.2, 1. ], + [1.4, 1. ], + [1.2, 1. ], + [1. , 1. ], + [1.3, 1. ], + [1.2, 1. ], + [1.3, 1. ], + [1.3, 1. ], + [1.1, 1. ], + [1.3, 1. ], + [2.5, 1. ], + [1.9, 1. ], + [2.1, 1. ], + [1.8, 1. ], + [2.2, 1. ], + [2.1, 1. ], + [1.7, 1. ], + [1.8, 1. ], + [1.8, 1. ], + [2.5, 1. ], + [2. , 1. ], + [1.9, 1. ], + [2.1, 1. ], + [2. , 1. ], + [2.4, 1. ], + [2.3, 1. ], + [1.8, 1. ], + [2.2, 1. ], + [2.3, 1. ], + [1.5, 1. ], + [2.3, 1. ], + [2. , 1. ], + [2. , 1. ], + [1.8, 1. ], + [2.1, 1. ], + [1.8, 1. ], + [1.8, 1. ], + [1.8, 1. ], + [2.1, 1. ], + [1.6, 1. ], + [1.9, 1. ], + [2. , 1. ], + [2.2, 1. ], + [1.5, 1. ], + [1.4, 1. ], + [2.3, 1. ], + [2.4, 1. ], + [1.8, 1. ], + [1.8, 1. ], + [2.1, 1. ], + [2.4, 1. ], + [2.3, 1. ], + [1.9, 1. ], + [2.3, 1. ], + [2.5, 1. ], + [2.3, 1. ], + [1.9, 1. ], + [2. , 1. ], + [2.3, 1. ], + [1.8, 1. ]]) + + + + +```python +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] +``` + + +```python +w +``` + + + + + np.float64(-5.989972912185251) + + + + +```python +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) + +``` + + +```python +rng = np.random.default_rng(0) +m = 120 +xNew = np.linspace(-1, 3, 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.990, b=4.280, loss=0.1361 + + + +```python +yJitter = y +np.random.uniform(-0.1, 0.1, size=y.shape) +plt.plot(x, yJitter, 'ok', alpha=0.1) +plt.plot(xNew,p) +``` + + + + + [] + + + + + +![png](main_files/main_10_1.png) + + + + +```python + +``` diff --git a/main.ipynb b/main.ipynb new file mode 100644 index 0000000..7d48a92 --- /dev/null +++ b/main.ipynb @@ -0,0 +1,612 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 3, + "id": "cf10ec2f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + ".. _iris_dataset:\n", + "\n", + "Iris plants dataset\n", + "--------------------\n", + "\n", + "**Data Set Characteristics:**\n", + "\n", + ":Number of Instances: 150 (50 in each of three classes)\n", + ":Number of Attributes: 4 numeric, predictive attributes and the class\n", + ":Attribute Information:\n", + " - sepal length in cm\n", + " - sepal width in cm\n", + " - petal length in cm\n", + " - petal width in cm\n", + " - class:\n", + " - Iris-Setosa\n", + " - Iris-Versicolour\n", + " - Iris-Virginica\n", + "\n", + ":Summary Statistics:\n", + "\n", + "============== ==== ==== ======= ===== ====================\n", + " Min Max Mean SD Class Correlation\n", + "============== ==== ==== ======= ===== ====================\n", + "sepal length: 4.3 7.9 5.84 0.83 0.7826\n", + "sepal width: 2.0 4.4 3.05 0.43 -0.4194\n", + "petal length: 1.0 6.9 3.76 1.76 0.9490 (high!)\n", + "petal width: 0.1 2.5 1.20 0.76 0.9565 (high!)\n", + "============== ==== ==== ======= ===== ====================\n", + "\n", + ":Missing Attribute Values: None\n", + ":Class Distribution: 33.3% for each of 3 classes.\n", + ":Creator: R.A. Fisher\n", + ":Donor: Michael Marshall (MARSHALL%PLU@io.arc.nasa.gov)\n", + ":Date: July, 1988\n", + "\n", + "The famous Iris database, first used by Sir R.A. Fisher. The dataset is taken\n", + "from Fisher's paper. Note that it's the same as in R, but not as in the UCI\n", + "Machine Learning Repository, which has two wrong data points.\n", + "\n", + "This is perhaps the best known database to be found in the\n", + "pattern recognition literature. Fisher's paper is a classic in the field and\n", + "is referenced frequently to this day. (See Duda & Hart, for example.) The\n", + "data set contains 3 classes of 50 instances each, where each class refers to a\n", + "type of iris plant. One class is linearly separable from the other 2; the\n", + "latter are NOT linearly separable from each other.\n", + "\n", + ".. dropdown:: References\n", + "\n", + " - Fisher, R.A. \"The use of multiple measurements in taxonomic problems\"\n", + " Annual Eugenics, 7, Part II, 179-188 (1936); also in \"Contributions to\n", + " Mathematical Statistics\" (John Wiley, NY, 1950).\n", + " - Duda, R.O., & Hart, P.E. (1973) Pattern Classification and Scene Analysis.\n", + " (Q327.D83) John Wiley & Sons. ISBN 0-471-22361-1. See page 218.\n", + " - Dasarathy, B.V. (1980) \"Nosing Around the Neighborhood: A New System\n", + " Structure and Classification Rule for Recognition in Partially Exposed\n", + " Environments\". IEEE Transactions on Pattern Analysis and Machine\n", + " Intelligence, Vol. PAMI-2, No. 1, 67-71.\n", + " - Gates, G.W. (1972) \"The Reduced Nearest Neighbor Rule\". IEEE Transactions\n", + " on Information Theory, May 1972, 431-433.\n", + " - See also: 1988 MLC Proceedings, 54-64. Cheeseman et al\"s AUTOCLASS II\n", + " conceptual clustering system finds 3 classes in the data.\n", + " - Many, many more ...\n", + "\n" + ] + } + ], + "source": [ + "#!pip3 install scikit-learn\n", + "from sklearn import datasets\n", + "iris = datasets.load_iris()\n", + "print(iris.DESCR)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "b27685c7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [1],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0],\n", + " [0]])" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import numpy as np \n", + "import matplotlib.pyplot as plt\n", + "x = iris.data[:,3:4]\n", + "y = (iris.target == 0).astype(int).reshape(-1,1)\n", + "y" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "8a2a7b97", + "metadata": {}, + "outputs": [], + "source": [ + "def sigmoid(z):\n", + " z = np.clip(z, -500, 500)\n", + " sig = 1.0 / (1.0 + np.exp(-z))\n", + " return sig" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "9774b339", + "metadata": {}, + "outputs": [], + "source": [ + "def log_loss(y, p, eps=1e-12):\n", + " p = np.clip(p, eps, 1 - eps)\n", + " return -np.mean(y*np.log(p) + (1-y)*np.log(1-p))" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "6ab87f00", + "metadata": {}, + "outputs": [], + "source": [ + "lr=0.1\n", + "epochs=2000 \n", + "l2=0.0,\n", + "X = np.column_stack([X, np.ones_like(X)])\n", + "m = X.shape[0]\n", + "theta = np.zeros((2,1))" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "2a9d4df3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0.2, 1. ],\n", + " [0.2, 1. ],\n", + " [0.2, 1. ],\n", + " [0.2, 1. ],\n", + " [0.2, 1. ],\n", + " [0.4, 1. ],\n", + " [0.3, 1. ],\n", + " [0.2, 1. ],\n", + " [0.2, 1. ],\n", + " [0.1, 1. ],\n", + " [0.2, 1. ],\n", + " [0.2, 1. ],\n", + " [0.1, 1. ],\n", + " [0.1, 1. ],\n", + " [0.2, 1. ],\n", + " [0.4, 1. ],\n", + " [0.4, 1. ],\n", + " [0.3, 1. ],\n", + " [0.3, 1. ],\n", + " [0.3, 1. ],\n", + " [0.2, 1. ],\n", + " [0.4, 1. ],\n", + " [0.2, 1. ],\n", + " [0.5, 1. ],\n", + " [0.2, 1. ],\n", + " [0.2, 1. ],\n", + " [0.4, 1. ],\n", + " [0.2, 1. ],\n", + " [0.2, 1. ],\n", + " [0.2, 1. ],\n", + " [0.2, 1. ],\n", + " [0.4, 1. ],\n", + " [0.1, 1. ],\n", + " [0.2, 1. ],\n", + " [0.2, 1. ],\n", + " [0.2, 1. ],\n", + " [0.2, 1. ],\n", + " [0.1, 1. ],\n", + " [0.2, 1. ],\n", + " [0.2, 1. ],\n", + " [0.3, 1. ],\n", + " [0.3, 1. ],\n", + " [0.2, 1. ],\n", + " [0.6, 1. ],\n", + " [0.4, 1. ],\n", + " [0.3, 1. ],\n", + " [0.2, 1. ],\n", + " [0.2, 1. ],\n", + " [0.2, 1. ],\n", + " [0.2, 1. ],\n", + " [1.4, 1. ],\n", + " [1.5, 1. ],\n", + " [1.5, 1. ],\n", + " [1.3, 1. ],\n", + " [1.5, 1. ],\n", + " [1.3, 1. ],\n", + " [1.6, 1. ],\n", + " [1. , 1. ],\n", + " [1.3, 1. ],\n", + " [1.4, 1. ],\n", + " [1. , 1. ],\n", + " [1.5, 1. ],\n", + " [1. , 1. ],\n", + " [1.4, 1. ],\n", + " [1.3, 1. ],\n", + " [1.4, 1. ],\n", + " [1.5, 1. ],\n", + " [1. , 1. ],\n", + " [1.5, 1. ],\n", + " [1.1, 1. ],\n", + " [1.8, 1. ],\n", + " [1.3, 1. ],\n", + " [1.5, 1. ],\n", + " [1.2, 1. ],\n", + " [1.3, 1. ],\n", + " [1.4, 1. ],\n", + " [1.4, 1. ],\n", + " [1.7, 1. ],\n", + " [1.5, 1. ],\n", + " [1. , 1. ],\n", + " [1.1, 1. ],\n", + " [1. , 1. ],\n", + " [1.2, 1. ],\n", + " [1.6, 1. ],\n", + " [1.5, 1. ],\n", + " [1.6, 1. ],\n", + " [1.5, 1. ],\n", + " [1.3, 1. ],\n", + " [1.3, 1. ],\n", + " [1.3, 1. ],\n", + " [1.2, 1. ],\n", + " [1.4, 1. ],\n", + " [1.2, 1. ],\n", + " [1. , 1. ],\n", + " [1.3, 1. ],\n", + " [1.2, 1. ],\n", + " [1.3, 1. ],\n", + " [1.3, 1. ],\n", + " [1.1, 1. ],\n", + " [1.3, 1. ],\n", + " [2.5, 1. ],\n", + " [1.9, 1. ],\n", + " [2.1, 1. ],\n", + " [1.8, 1. ],\n", + " [2.2, 1. ],\n", + " [2.1, 1. ],\n", + " [1.7, 1. ],\n", + " [1.8, 1. ],\n", + " [1.8, 1. ],\n", + " [2.5, 1. ],\n", + " [2. , 1. ],\n", + " [1.9, 1. ],\n", + " [2.1, 1. ],\n", + " [2. , 1. ],\n", + " [2.4, 1. ],\n", + " [2.3, 1. ],\n", + " [1.8, 1. ],\n", + " [2.2, 1. ],\n", + " [2.3, 1. ],\n", + " [1.5, 1. ],\n", + " [2.3, 1. ],\n", + " [2. , 1. ],\n", + " [2. , 1. ],\n", + " [1.8, 1. ],\n", + " [2.1, 1. ],\n", + " [1.8, 1. ],\n", + " [1.8, 1. ],\n", + " [1.8, 1. ],\n", + " [2.1, 1. ],\n", + " [1.6, 1. ],\n", + " [1.9, 1. ],\n", + " [2. , 1. ],\n", + " [2.2, 1. ],\n", + " [1.5, 1. ],\n", + " [1.4, 1. ],\n", + " [2.3, 1. ],\n", + " [2.4, 1. ],\n", + " [1.8, 1. ],\n", + " [1.8, 1. ],\n", + " [2.1, 1. ],\n", + " [2.4, 1. ],\n", + " [2.3, 1. ],\n", + " [1.9, 1. ],\n", + " [2.3, 1. ],\n", + " [2.5, 1. ],\n", + " [2.3, 1. ],\n", + " [1.9, 1. ],\n", + " [2. , 1. ],\n", + " [2.3, 1. ],\n", + " [1.8, 1. ]])" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "X" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "42a2d7ba", + "metadata": {}, + "outputs": [], + "source": [ + "for i in range(epochs):\n", + " z = X @ theta # (m,1)\n", + " h = sigmoid(z) # (m,1)\n", + " grad = (X.T @ (h - y)) / m # (2,1) <-- from your formula\n", + " theta -= lr * grad\n", + "\n", + " #if (i % 0 == 0 or t == epochs-1):\n", + " # print(f\"{i:4d} loss={log_loss(y, h):.6f} w={theta[0,0]:.6f} b={theta[1,0]:.6f}\")\n", + "\n", + "w, b = theta[0,0], theta[1,0]" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "5a224528", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "np.float64(-5.989972912185251)" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "w" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "d3dbe4b2", + "metadata": {}, + "outputs": [], + "source": [ + "def predict_proba(x, w, b):\n", + " x = np.asarray(x, float).reshape(-1)\n", + " return sigmoid(w*x + b)\n", + "\n", + "def predict(x, w, b, thresh=0.5):\n", + " return (predict_proba(x, w, b) >= thresh).astype(int)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cd88d5ee", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Learned: w=-5.990, b=4.280, loss=0.1361\n" + ] + } + ], + "source": [ + "rng = np.random.default_rng(0)\n", + "m = 120\n", + "xNew = np.linspace(-1, 3, m)\n", + "p = predict_proba(xNew, w, b)\n", + "print(f\"\\nLearned: w={w:.3f}, b={b:.3f}, loss={log_loss(p.reshape(-1,1), p.reshape(-1,1)):.4f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "id": "63707def", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 64, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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MEJERESWYjBCRERElmIwQkRERJZiMEJERESWYjBCREREloqJGVj1jPWYVpaIiIhig663B1t5JiaCESysBHqpbyIiIoodqMexRk1ML5SHxY9OnDihVni02WwhjdgQ4FRXV8ftAnzxfo28vtgX79fI64t98X6NTWG8PoQYCERGjBihFjGM6ZYRXEBZWVnYnh9vfjz+A0uka+T1xb54v0ZeX+yL92vMDtP1DdQiojGBlYiIiCzFYISIiIgsldDBSGpqqixbtkzdx6t4v0ZeX+yL92vk9cW+eL/G1Ci4vphIYCUiIqL4ldAtI0RERGQ9BiNERERkKQYjREREZCkGI0RERGSphAtGfvrTn8oll1wiGRkZkpubG9BjkOO7dOlSGT58uKSnp8v8+fPlwIEDEo3OnDkjN910k5q4Btf3zW9+U1paWgZ8zOWXX65mtjXevv3tb0u0WLFihZSXl0taWprMnj1btmzZMuD5f/7zn+Xcc89V559//vmyZs0aiWZmru+55577zGeFx0Wrd955R6677jo1+yLKunr16kEfs2HDBpk+fbrK7B8/fry65mhm9hpxfd6fIW61tbUSjZYvXy4XXXSRmgG7uLhYbrjhBtm3b9+gj4uV38Ngri+Wfg9/85vfyAUXXOCZ0GzOnDny6quvRt1nl3DBSFdXl9x4441y1113BfyYn//85/If//Ef8uSTT8oHH3wgmZmZsmDBAuno6JBog0Bk165dsm7dOnn55ZfVH8o777xz0MfdcccdUlNT47nhmqPBqlWrZPHixWrY2fbt22Xq1Knqva+rq/N5/vvvvy+LFi1SQdhHH32k/rDg9sknn0g0Mnt9gD8oxs/q6NGjEq1aW1vVNSHgCkRlZaVce+21csUVV8iOHTvk7rvvlttvv11ee+01iZdr1FDhGT9HVITR6O2335bvfOc7snnzZvV3pbu7W66++mp13f7E0u9hMNcXS7+HZWVl8tBDD8m2bdtk69at8vnPf16uv/56VU9E1WfnTlC/+93v3Dk5OYOe53K53KWlpe5f/OIXnn0NDQ3u1NRU9x//+Ed3NNm9ezeGabs//PBDz75XX33VbbPZ3MePH/f7uHnz5rm///3vu6PRrFmz3N/5znc8206n0z1ixAj38uXLfZ7/1a9+1X3ttdf22zd79mz3t771LXc8XF+g/26jEf5tvvTSSwOe88Mf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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "yJitter = y +np.random.uniform(-0.1, 0.1, size=y.shape)\n", + "plt.plot(x, yJitter, 'ok', alpha=0.1)\n", + "plt.plot(xNew,p)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8f1ffe41", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv (3.13.5)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/main_files/main_10_1.png b/main_files/main_10_1.png new file mode 100644 index 0000000000000000000000000000000000000000..96d4a541814b094603e1491703d637cb273900b2 GIT binary patch literal 22252 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