{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# MNIST digits: Softmax Regression "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.datasets import fetch_openml # MNIST data\n",
    "from sklearn.linear_model import LogisticRegression\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.metrics import classification_report\n",
    "from sklearn.metrics import accuracy_score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# load MNIST data from https://www.openml.org/d/554\n",
    "X, y = fetch_openml('mnist_784', version=1, return_X_y=True)\n",
    "X = X.to_numpy()\n",
    "y = y.to_numpy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# generate training and test datasets\n",
    "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 8264 characters]\n",
      "text/plain": [
       "<Figure size 1080x360 with 6 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.subplots(1, 6, figsize=(15,5))\n",
    "for i in range(6):\n",
    "    index = 9000 + i # image number\n",
    "    pixels = np.array(X_train[index], dtype='uint8')\n",
    "    pixels = pixels.reshape((28, 28))\n",
    "    plt.subplot(1, 6, i+1)\n",
    "    plt.title('Label is {label}'.format(label=y_train[index]))\n",
    "    plt.imshow(pixels, cmap='gray')\n",
    "    plt.xticks(())\n",
    "    plt.yticks(())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# apply logistic regressor with 'sag' solver, C is the inverse regularization strength\n",
    "clf = LogisticRegression(multi_class='multinomial',\n",
    "                         penalty='none', solver='sag', tol=0.1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "LogisticRegression(multi_class='multinomial', penalty='none', solver='sag',\n",
       "                   tol=0.1)"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# fit data\n",
    "clf.fit(X_train, y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "              precision    recall  f1-score   support\n",
      "\n",
      "           0       0.95      0.97      0.96      1407\n",
      "           1       0.96      0.97      0.96      1525\n",
      "           2       0.92      0.89      0.91      1410\n",
      "           3       0.91      0.90      0.90      1453\n",
      "           4       0.91      0.93      0.92      1407\n",
      "           5       0.90      0.84      0.87      1260\n",
      "           6       0.93      0.96      0.94      1387\n",
      "           7       0.93      0.94      0.94      1434\n",
      "           8       0.87      0.88      0.88      1375\n",
      "           9       0.90      0.90      0.90      1342\n",
      "\n",
      "    accuracy                           0.92     14000\n",
      "   macro avg       0.92      0.92      0.92     14000\n",
      "weighted avg       0.92      0.92      0.92     14000\n",
      "\n",
      "0.9195714285714286\n"
     ]
    }
   ],
   "source": [
    "#Test the model\n",
    "predictions = clf.predict(X_test)\n",
    "\n",
    "#Precision, recall, f1-score\n",
    "print(classification_report(y_test, predictions))\n",
    "print(accuracy_score(y_test, predictions))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAOsAAADrCAYAAACICmHVAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAFkUlEQVR4nO3dsWpUWxiG4T2HEBRBQRTE5iRFBCFCIGJnqzaBXEBIYeNVWHkDqS0lja3p0oeAYBCNCorIQQMRT2OwUCHOuQH3P5lxZ/Q78zxl/tnOal6WsFh7ev1+vwH+fH/97gUARyNWCCFWCCFWCCFWCCFWCDE1zId7vZ5zHjhm/X6/97O/21khhFghhFghhFghhFghhFghhFghhFghhFghhFghhFghhFghhFghhFghhFghhFghhFghhFghhFghhFghhFghhFghhFghhFghhFghhFghhFghhFghhFghxFC/Isf43b17t5zPzc390r+/urr6S88zPnZWCCFWCCFWCCFWCCFWCCFWCCFWCNHr9/tH/3Cvd/QPT5C1tbVyPjMzU84XFhZaZ4eHh+Wznz9/LueD7O3tlfOlpaVf+vcZXr/f7/3s73ZWCCFWCCFWCCFWCCFWCCFWCCFWCOGc9Qg2NzfL+eXLl8v59+/fy/nW1lbr7Ljvm+7s7JTz6hz24cOH5bPr6+sjrWnSOWeFcGKFEGKFEGKFEGKFEGKFEF5F2jTNkydPyvmg461Xr16V8xs3bgy9pnHZ3d0t5zdv3mydDTq6oVt2VgghVgghVgghVgghVgghVgghVgjhnLVpmrdv35bz06dPl/Nbt251uZyxGnT9b35+vnV29erV8llX5LplZ4UQYoUQYoUQYoUQYoUQYoUQYoUQXkVKaWNjo3V28eLF8tnFxcWulzMRvIoUwokVQogVQogVQogVQogVQogVQrjPSunKlSuts/fv349xJdhZIYRYIYRYIYRYIYRYIYRYIYRYIYRz1gm3trZWzg8PD1tng945TLfsrBBCrBBCrBBCrBBCrBBCrBDCq0gn3OvXr8v59PR062xmZqbj1dA0XkUK8cQKIcQKIcQKIcQKIcQKIcQKIVyRCzfomtqlS5fK+fPnz8v50tLS0GvieNhZIYRYIYRYIYRYIYRYIYRYIYRYIYT7rB3Y2dkp53Nzc+X8xIkTI3/31FR9VP7169dy/u3bt3L+6NGj1tnq6mr5LKNxnxXCiRVCiBVCiBVCiBVCiBVCiBVCuM/agd3d3XL+48ePcv7hw4fW2eLiYvns/fv3y/m7d+/K+e3bt8v5oO9nfOysEEKsEEKsEEKsEEKsEEKsEEKsEMJ9VkobGxuts/n5+fLZ2dnZrpczEdxnhXBihRBihRBihRBihRBihRCuyFF6/Phx6+zatWtjXAl2VgghVgghVgghVgghVgghVgghVgjhnJVS9SrTL1++lM+urKyU8/X19ZHWNKnsrBBCrBBCrBBCrBBCrBBCrBBCrBDCq0gZ2cePH8v59vZ2OV9eXu5wNf8fXkUK4cQKIcQKIcQKIcQKIcQKIcQKIdxnZWR7e3vl/ODgYEwrmQx2VgghVgghVgghVgghVgghVgjh6KZpms3NzXJ+8uTJcn79+vUulxPj7Nmzv3sJE8XOCiHECiHECiHECiHECiHECiHECiGcszZN8/Lly3J+586dcv7p06dyfv78+aHX9Kd49uzZyM8OOr9mOHZWCCFWCCFWCCFWCCFWCCFWCCFWCOEnHzvw4sWLcn7u3LlyXv104v7+/khrOup3nzlzppyfOnWqdXbhwoWR1kTNTz5COLFCCLFCCLFCCLFCCLFCCLFCCOesY/DgwYNyvrCwcGzf/fTp03L+5s2bcn7v3r0OV8NROGeFcGKFEGKFEGKFEGKFEGKFEGKFEM5Z4Q/jnBXCiRVCiBVCiBVCiBVCiBVCiBVCiBVCiBVCiBVCiBVCiBVCiBVCiBVCiBVCiBVCiBVCiBVCiBVCiBVCiBVCiBVCTA35+X+bpvnnOBYCNE3TNH+3DYZ6bzDw+/hvMIQQK4QQK4QQK4QQK4QQK4QQK4QQK4QQK4T4D1Fb9wK3fp4mAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import png\n",
    "filename = \"/local/home/marks/syncDir/doc/anaKurs/notebooks/your_own_digit.png\"\n",
    "image = np.zeros((1, 28, 28, 1), dtype=np.uint8)\n",
    "pngdata = png.Reader(open(filename, 'rb')).asDirect()\n",
    "for i_row, row in enumerate(pngdata[2]):\n",
    "    image[0, i_row, :, 0] = row\n",
    "\n",
    "plt.imshow(np.squeeze(image), cmap=\"gray\")\n",
    "plt.xticks(())\n",
    "plt.yticks(())\n",
    "plt.show()\n",
    "\n",
    "# one digit, -1: unspecified number determined by numpy\n",
    "my_digit = image.reshape((1,-1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1.11972749e-05 1.82203682e-05 1.39789844e-02 9.62151101e-01\n",
      "  1.50087700e-04 5.80624586e-03 7.91859994e-07 8.48579889e-06\n",
      "  1.77603280e-02 1.14557842e-04]]\n",
      "prediction = 3\n"
     ]
    }
   ],
   "source": [
    "probabilities = clf.predict_proba(my_digit)\n",
    "prediction = np.argmax(probabilities)\n",
    "print(probabilities)\n",
    "print(f\"prediction = {prediction}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.10.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
