SHA256
initial commit
This commit is contained in:
commit
900611f382
7 files changed
+3387
No files matched your search
+10
@@ -0,0 +1,10 @@
|
|||||||
|
# Python-generated files
|
||||||
|
__pycache__/
|
||||||
|
*.py[oc]
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
wheels/
|
||||||
|
*.egg-info
|
||||||
|
|
||||||
|
# Virtual environments
|
||||||
|
.venv
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
3.12
|
||||||
Binary file not shown.
@@ -0,0 +1,14 @@
|
|||||||
|
[project]
|
||||||
|
name = "2025-02-ai-hw2"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Add your description here"
|
||||||
|
readme = "README.md"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
dependencies = [
|
||||||
|
"jupyter>=1.1.1",
|
||||||
|
"matplotlib>=3.10.7",
|
||||||
|
"numpy>=2.3.5",
|
||||||
|
"scikit-learn>=1.7.2",
|
||||||
|
"seaborn>=0.13.2",
|
||||||
|
"torch>=2.9.1",
|
||||||
|
]
|
||||||
+991
@@ -0,0 +1,991 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 15,
|
||||||
|
"id": "e815086e",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import numpy as np\n",
|
||||||
|
"import matplotlib.pyplot as plt\n",
|
||||||
|
"from sklearn.datasets import load_digits\n",
|
||||||
|
"\n",
|
||||||
|
"import sklearn\n",
|
||||||
|
"import seaborn as sns\n",
|
||||||
|
"\n",
|
||||||
|
"import matplotlib.font_manager as fm\n",
|
||||||
|
"\n",
|
||||||
|
"import torch\n",
|
||||||
|
"import torch.nn as nn\n",
|
||||||
|
"import torch.optim as optim\n",
|
||||||
|
"import torch.nn.functional as F\n",
|
||||||
|
"\n",
|
||||||
|
"from collections import OrderedDict\n",
|
||||||
|
"\n",
|
||||||
|
"fm.fontManager.addfont('ChosunSm.ttf')\n",
|
||||||
|
"prop = fm.FontProperties(fname='ChosunSm.ttf')\n",
|
||||||
|
"plt.rcParams[\"font.family\"] = prop.get_name()\n",
|
||||||
|
"plt.rcParams[\"axes.unicode_minus\"] = False\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "9b5dff32",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# AI Homework 2025, Homework #2 Report"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "e8ed0fa0",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Load dataset"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 16,
|
||||||
|
"id": "66214571",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"image/png": "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 truncated
|
||||||
|
"text/plain": [
|
||||||
|
"<Figure size 640x480 with 1 Axes>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "display_data"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"data = load_digits()\n",
|
||||||
|
"plt.imshow(data.images[0], cmap=plt.cm.gray_r, interpolation='nearest')\n",
|
||||||
|
"plt.show()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "84818428",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Analysis about the datasets"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "c2ef5bfb",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"array([0, 1, 2, ..., 8, 9, 8], shape=(1797,))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 39,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"data.target"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 48,
|
||||||
|
"id": "e2eec4b9",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"=== 1. Basic Dataset Info ===\n",
|
||||||
|
"Total Samples: 1797\n",
|
||||||
|
"Feature Count: 64 (8x8 pixels flattened)\n",
|
||||||
|
"Target Classes: [0 1 2 3 4 5 6 7 8 9]\n",
|
||||||
|
"Feature Range: 0.0 ~ 16.0\n",
|
||||||
|
"============================\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAABVsAAAPcCAYAAABfPGsmAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjcsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvTLEjVAAAAAlwSFlzAAAPYQAAD2EBqD+naQABAABJREFUeJzs3XdcVvX///EnimBOxD3BkZZl7lGWI1c23ObAmftTJo4UR46WaEvNSi0/rpYN04+jUkvJiYkzFTduSEUEFyC8f3/48/p6BSoHD1ygj/vt5k3POa9zrte5rgs8PHlf7+NmjDECAAAAAAAAANyTLK5uAAAAAAAAAADuB4StAAAAAAAAAGADwlYAAAAAAAAAsAFhKwAAAAAAAADYgLAVAAAAAAAAAGxA2AoAAAAAAAAANiBsBQAAAAAAAAAbELYCAAAAAAAAgA0IWwHABQ4ePOjqFpAKvG4AAAAAgDshbAXSyYULF/TPP/+4ug1kAN9//7327Nnj6jaQCt9//7327t3r6jYAAAAAABkUYSuQBq5du6Z33nlHLVu2VNu2bVW4cGF5e3vr559/dtQcPHhQrVq1ckl/3377rR5//HG5ubmpcePG6tevn/r37y8/Pz8tXrxYxhin+ho1aqht27YpPv7+/fs1bNiwFNcPHTpUPj4+unz5siRp3Lhxypkzp6ZPn57iY9zJzJkztWzZMqd1U6dOVYECBXTs2DFbHiOlDh8+rO+++04tW7bU3r175ebmpgoVKqhfv36qVauW3NzcVL9+ffXp00c+Pj5yc3PT2bNn07XH23nppZfuWnPre+v5559X37591aVLFzVs2FArVqyw9HhLly5VQEBAattNE4MHD9agQYN07do1V7cCAMAD59KlS+rTp486duyogQMHaujQoVq8eLGOHDni6taUkJCgUaNGJbnmtCKtr9EladGiRcqTJ4+Cg4Od1qfkOm/9+vVq2rSp3NzcVL16dX3//feWHhsAHhTurm4AuN8kJiaqW7duKlu2rBYtWqSsWbMqNjZW/fr106ZNm9SvXz8tWbJEr776qooUKeKSHjt16qQCBQqoTZs2WrlypbJkufF7l+joaPXs2VPLly/XrFmz5ObmJkkqUqSIChYsmOLjR0REWOrH29tbRYoUUdasWSVJEyZM0Jo1aywd4279FC9e3Gld3rx5VbhwYXl6etr2OCkxcOBAjR49Wm5ubtqzZ4+efPJJrVmzRp6entq/f78eeeQR/fzzz/L29lZMTIzq1KmjPXv2qEGDBunaZ3JS8rre+t5atmyZ47114MAB1a5dWytXrlTNmjXvepx3331Xb731lgYOHHjPfdspR44cat68uSZPnqyxY8e6uh0AAB4o/fr102OPPaZRo0ZJunFt0qBBAw0aNEj9+/d3WV9XrlxRz5499f3332vp0qWpPk5aX6NLUu7cuVWkSBHlyJHDaX1KrvOefvppLV++XB4eHvriiy9UrVo1S48NAA8KRrYCNvvuu+909OhRvfvuu47w0NPTUzNmzND58+clSS1btnR5UJMtWzZ5eno6LuIkKU+ePPr666+1YcMGzZ8/37F+2bJlmjFjRoqPvXPnTku9jB49WsHBwcqePbtj3a193avk+unRo4f27NmTroH3X3/9pfDwcD311FOSpL1792ratGmOwPfm3x4eHpJuXAx/8MEHGWLKgaioKIWFhaWoNrn3Vvny5fXSSy/pm2++SdExRo8ebXmkRnrp3bu3ZsyYoejoaFe3AgDAA+Pq1av6/vvv1a9fP8e6woUL69tvv9X69etd2NmNX8Z+9913Klq06D0fKy2v0SWpSZMmOnDggCpVquRYZ/U6T/q/61UAQFKErYDNPvroI73++utJwsLs2bNr0qRJjo//ZNQLlOzZsysgIECffPKJ5X0TExN14MABTZ06NQ06sy4+Pl6rVq26pxEGdpo9e7batWvnGI3QpUsX1ahR4477PPfcc2revHl6tHdbUVFRGjNmjBITE+/pOMWKFVNkZGSK6zPq10iePHlUp04d/fDDD65uBQCAB0Z0dLSuX7+e5HqkSpUqKleunKVj/fvj+HZwc3NL02uXe7lGvxO7rvOktHleASAzYhoBwEYxMTEKCQlxjFz8t4oVK95236tXr8rf31/u7u7y9vbW7t271a9fP0fQFh0dLX9/f8dvk69du6Zu3bqpUaNGio+P1xtvvKGYmBh5eHjo+vXrqlevnrp27Zqq83juuefUvXt3xcTEKHfu3Nq8ebPmz5+vzz77TJJ0+vRpDR06VN7e3rp27ZpiYmL03nvvKT4+XvPmzdNDDz2kP//8UwEBASpZsqReffVVxcbGqk+fPho+fLh++uknffjhh3rjjTf05ptvKiIiQj169NAvv/zi1MeFCxfUu3dvxcbGKjIyUtWqVdPYsWOVLVs2rVy5UuPGjVPJkiUd80X99ddfGjlypK5cuaKNGzdq5cqVWrdunR566CHNnTtX69evV/369dW8eXPFxMToxRdfVFBQkOPxwsLCFBAQoDx58ujatWsqWLCg3nnnHT300EOSpGPHjmnQoEGaOXOmJk2apIsXL2rfvn367LPPVKVKlbs+r7///ru+/PJLx3LZsmXvuo+bm5vKlCmjxMREjR49Wv/8849KlCihPXv2qEWLFurWrZukGxe3M2fO1PXr1+Xr66tevXqpWrVqWr58udzc3DR16lQFBwerdOnSCgsL08MPP6zly5crOjpa+/btU2JiosaOHavQ0FDly5dP169f1+eff66cOXNq2rRpioyM1OXLlx1zqA4ZMkSFChW6a/+32rdvn5555hlJuuv5JOfo0aMaNmyYHn74YUlSaGio3n//fcfy1atX1apVKy1cuFDTp0/X6dOntW3bNr3++uvq3Lmz4zjXrl3TmDFjFBkZqSxZsuiff/7RJ598Ih8fH0nSli1bNG7cOPn6+uro0aN6/fXX9fzzzzv18tRTT+n3339Xr169LD0HAAAgdQoVKiQfHx9NmDBB06ZNcxrYMH78eMe/v/32Wy1atEiPPvqozpw5o1y5cunDDz901IeFhWnOnDmqW7eulixZop07dyowMFBPPPGE3nnnHR09elQnT57UN998o9KlS2vPnj165513tHz5cr355pv69ddf5evrq2PHjql3797q2LHjbXuOiYnR0KFDFRMToyxZsqhgwYJ6//33HdfzVt3tGl2SvvrqKy1ZskTly5fX6dOn5e3trT179mjnzp3atWuX8uTJox49emjixIny9fW15TovMTFRH330kRo0aKCff/5ZBw4cUK5cufTll19q+fLl+uWXX7Rlyxa9/PLLGjFihGO/KVOm6K+//lK5cuV06NAhVa5cWcOHD3dsP3TokMaMGaPixYvLGKOwsDA9+uijmj59uqZMmaKePXve8brtdj+zWA3nAcAyA8A2e/fuNW5ubub69et3rZ0zZ46pXr26Y3nSpEnm0UcfdSwfOnTIFChQwMTFxRljjBkyZIiZNGmSY/vEiRPNgAEDjDHGTJs2zfFvY4z55ptvTPPmze/4+GvWrDH58+dPdltiYqLJli2b+fvvv81nn31mcuXKZbp37+7Y3qZNG7Nw4UJHbb9+/Zx66969uxk6dKhj+dSpU+a5554zksw777xj6tatax555BFTuXJls2bNGlO2bFnj4+Pj1EP9+vWNp6en2bBhg+NxXnnlFTNo0CBHzciRI03btm2d9psxY4bT82qMMT4+Pmbp0qWO5V27dpmqVauaW78FxsTEGB8fH7Ny5UrHutGjR5v27dsbY4xZsmSJKVGihKlataoZOHCguXr1qjHGmMmTJ5tq1aol+zze6tq1a0aSOXbs2G1rjh49aiSZmJiYJNsWLlxocubM6XhvRUdHGy8vLxMeHm6MMea1114zbm5uJiAgwDz66KOmSZMmRpKJjIw0//3vf83jjz/ueC8lJCSY559/3gwaNMhMnz7dJCYmmtdee8289NJLjuNPmzbNtGnTxvH4d3q//FtytYsWLTKVK1c2UVFRKTofY5K+j5o3b+70Pv/yyy9Ny5YtjTHG7Nmzx9SpU8dIMqNGjTKHDx82xhizZcsW4+7ubs6fP2+MufE+at26tfnoo48cx3n55Zcd53r48GGTL18+s3HjRmOMMZGRkaZChQomJCTE6Xy+//57U6lSpRQ9HwAAwB5//PGHyZMnj6lWrZqZP3++uXz5stP206dPmyxZspjg4GDHuqefftr8/PPPxhhjvvrqK5MvXz5TtWpVs3z5cmPMjevC0qVLm48++shcuXLFGGNMv379TOfOnR3HCA0NNZJMixYtTHx8vDHGmH/++cf4+vqaX3/91VH372vOF1980fznP/8xiYmJxpgb1/NDhgy54zneyzX677//bgoXLuy43jLGmAEDBpguXbqYDz/80Bw7dszUr1/fSDJHjx5N0WMmR5LZvXu3McaYs2fPmubNmxtJxt/f3/GatGnTxowcOdIsWrTIGGPMyZMnTZYsWcz+/fuNMcYEBwcbSSYiIsIYY0x8fLzx9fU127dvdyyXLl3afPvtt47HDQ4ONvnz5zezZ882u3fvvut1291+ZgGAtMI0AoCNIiMjlTt3bsdcrVYULVpUjz76qGO5TJkyOnfunE6ePClJ2rNnj9M8UCNGjFC+fPmS3dapUyfVqFFD169fT9V5uLm5KXv27Lpw4YIGDBignj17Om2/9fFujpq8evXqbY9XrFgxLVmyRNKNO8yvXLlS69ev1zfffKMGDRpo8uTJye7XvHlzxyhhNzc3vfXWW5o5c6YuXLggKfmPmafkhleVKlVyGmEqSd988418fX3VpEkTx7qAgACtWLFCBw8eVIsWLfTmm29q165d8vPzc8wvW79+fe3ateuuj3lzvt68efPetTY5+fLlU82aNR2vae7cuZUnTx7t3btXkvTJJ5+oTp06mjNnjn788UetWLFCGzduVL58+RQcHKw6deo4RlFLine truncated
|
||||||
|
"text/plain": [
|
||||||
|
"<Figure size 1600x1200 with 15 Axes>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "display_data"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"print(\"=== 1. Basic Dataset Info ===\")\n",
|
||||||
|
"print(f\"Total Samples: {data.data.shape[0]}\")\n",
|
||||||
|
"print(f\"Feature Count: {data.data.shape[1]} (8x8 pixels flattened)\")\n",
|
||||||
|
"print(f\"Target Classes: {data.target_names}\")\n",
|
||||||
|
"print(f\"Feature Range: {np.min(data.data)} ~ {np.max(data.data)}\")\n",
|
||||||
|
"print(\"============================\")\n",
|
||||||
|
"\n",
|
||||||
|
"fig = plt.figure(figsize=(16, 12))\n",
|
||||||
|
"\n",
|
||||||
|
"ax1 = fig.add_subplot(2, 2, 1)\n",
|
||||||
|
"labels, counts = np.unique(data.target, return_counts=True)\n",
|
||||||
|
"ax1.bar(labels, counts, color='skyblue', align='center')\n",
|
||||||
|
"ax1.set_title(\"Class Distribution (Target Balance)\")\n",
|
||||||
|
"ax1.set_xlabel(\"Digit Label\")\n",
|
||||||
|
"ax1.set_xticks(labels)\n",
|
||||||
|
"ax1.set_ylabel(\"Count\")\n",
|
||||||
|
"\n",
|
||||||
|
"ax2 = fig.add_subplot(2, 2, 2)\n",
|
||||||
|
"ax2.axis('off')\n",
|
||||||
|
"ax2.set_title(\"Sample Digit Images\")\n",
|
||||||
|
"for i in range(10):\n",
|
||||||
|
" sub_ax = fig.add_axes([0.55 + (i % 5) * 0.08, 0.75 - (i // 5) * 0.1, 0.08, 0.08])\n",
|
||||||
|
" sub_ax.imshow(data.images[i], cmap=plt.cm.gray_r, interpolation='nearest')\n",
|
||||||
|
" sub_ax.axis('off')\n",
|
||||||
|
" sub_ax.set_title(str(data.target[i]), fontsize=10)\n",
|
||||||
|
"\n",
|
||||||
|
"ax3 = fig.add_subplot(2, 2, 3)\n",
|
||||||
|
"mean_images = []\n",
|
||||||
|
"for i in range(10):\n",
|
||||||
|
" mean_images.append(np.mean(data.images[data.target == i], axis=0))\n",
|
||||||
|
"\n",
|
||||||
|
"combined_img = np.zeros((8 * 2, 8 * 5))\n",
|
||||||
|
"for i in range(10):\n",
|
||||||
|
" row = i // 5\n",
|
||||||
|
" col = i % 5\n",
|
||||||
|
" combined_img[row*8:(row+1)*8, col*8:(col+1)*8] = mean_images[i]\n",
|
||||||
|
"ax3.imshow(combined_img, cmap=plt.cm.gray_r, interpolation='nearest')\n",
|
||||||
|
"ax3.set_title(\"Mean Images per Class\")\n",
|
||||||
|
"ax3.axis('off')\n",
|
||||||
|
"\n",
|
||||||
|
"ax4 = fig.add_subplot(2, 2, 4)\n",
|
||||||
|
"pca = sklearn.decomposition.PCA(n_components=2)\n",
|
||||||
|
"X_pca = pca.fit_transform(data.data)\n",
|
||||||
|
"\n",
|
||||||
|
"scatter = ax4.scatter(X_pca[:, 0], X_pca[:, 1], c=data.target, cmap='tab10', alpha=0.6, s= 15)\n",
|
||||||
|
"ax4.set_title(\"2D PCA Projection of Digits\")\n",
|
||||||
|
"#ax4.set_xlabel(\"PCA Component 1\")\n",
|
||||||
|
"#ax4.set_ylabel(\"PCA Component 2\")\n",
|
||||||
|
"plt.colorbar(scatter, ax=ax4, label = \"Digit Class\")\n",
|
||||||
|
"\n",
|
||||||
|
"#plt.tight_layout()\n",
|
||||||
|
"plt.show()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "93f40d6e",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"데이터 개요 (Overview):\n",
|
||||||
|
"\n",
|
||||||
|
" 총 1,797개의 샘플이 있으며, 각 샘플은 8x8 픽셀(64개 feature)로 이루어진 흑백(grayscale) 이미지이다.\n",
|
||||||
|
"\n",
|
||||||
|
" 각 픽셀 값은 0(흰색)부터 16(검은색) 사이의 정수 값을 가진다. (이 때문에 학습 전 StandardScaler를 이용한 정규화가 필요함을 언급하면 좋습니다.)\n",
|
||||||
|
"\n",
|
||||||
|
"클래스 균형 (Class Balance):\n",
|
||||||
|
"\n",
|
||||||
|
" 첫 번째 그래프(Bar chart)를 보면 0부터 9까지의 데이터 개수가 거의 비슷하다.\n",
|
||||||
|
"\n",
|
||||||
|
" 분석: 데이터 불균형(Imbalance) 문제가 없으므로, 정확도(Accuracy)를 주요 평가지표로 사용해도 타당하다.\n",
|
||||||
|
"\n",
|
||||||
|
"데이터의 특징 (Characteristics):\n",
|
||||||
|
"\n",
|
||||||
|
" 세 번째 그림(Average Image)을 보면, 같은 숫자라도 필기체라 모양이 조금씩 다르지만 평균을 내보면 숫자의 형태가 뚜렷하게 나타난다.\n",
|
||||||
|
"\n",
|
||||||
|
" 이는 픽셀 데이터 간에 일관된 패턴이 존재함을 의미한다.\n",
|
||||||
|
"\n",
|
||||||
|
"분류 가능성 (Separability - PCA Plot):\n",
|
||||||
|
"\n",
|
||||||
|
" 마지막 산점도(PCA)를 보면, 64차원을 2차원으로 줄였음에도 불구하고 같은 색깔(같은 숫자)끼리 잘 뭉쳐 있고, 다른 색깔과는 분리되는 경향을 보인다.\n",
|
||||||
|
"\n",
|
||||||
|
" 분석: 이는 데이터가 비교적 선형적으로 분리 가능하거나(Linearly Separable) 패턴이 뚜렷하여, SVM이나 Logistic Regression 같은 알고리즘으로도 높은 성능을 낼 수 있음을 시사한다."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "f8ad8d28",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## reproducing Datasets"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 17,
|
||||||
|
"id": "df8d0f6c",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split(\n",
|
||||||
|
" data.data, data.target, test_size=0.2, random_state=8\n",
|
||||||
|
")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 18,
|
||||||
|
"id": "d341c075",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"scaler = sklearn.preprocessing.StandardScaler()\n",
|
||||||
|
"X_train_scaled = scaler.fit_transform(X_train)\n",
|
||||||
|
"X_test_scaled = scaler.transform(X_test)\n",
|
||||||
|
"\n",
|
||||||
|
"X_train_tensor = torch.tensor(X_train_scaled.reshape(-1, 1, 8, 8), dtype=torch.float32)\n",
|
||||||
|
"X_test_tensor = torch.tensor(X_test_scaled.reshape(-1, 1, 8, 8), dtype=torch.float32)\n",
|
||||||
|
"y_train_tensor = torch.tensor(y_train, dtype=torch.long)\n",
|
||||||
|
"y_test_tensor = torch.tensor(y_test, dtype=torch.long)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "b5d94d91",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# Preparing Models"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 19,
|
||||||
|
"id": "55952278",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"class DigitCNN(nn.Module):\n",
|
||||||
|
" def __init__(self):\n",
|
||||||
|
" super(DigitCNN, self).__init__()\n",
|
||||||
|
"\n",
|
||||||
|
" self.conv1 = nn.Conv2d(in_channels=1, out_channels=16, kernel_size=3, padding=1)\n",
|
||||||
|
" self.relu = nn.ReLU()\n",
|
||||||
|
"\n",
|
||||||
|
" self.pool = nn.MaxPool2d(kernel_size=2, stride=2)\n",
|
||||||
|
" self.conv2 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=3, padding=1)\n",
|
||||||
|
"\n",
|
||||||
|
" self.fc1 = nn.Linear(32 * 4 * 4, 128)\n",
|
||||||
|
" self.fc2 = nn.Linear(128, 10)\n",
|
||||||
|
" \n",
|
||||||
|
" def forward(self, x):\n",
|
||||||
|
" x = self.conv1(x)\n",
|
||||||
|
" x = self.relu(x)\n",
|
||||||
|
" x = self.pool(x)\n",
|
||||||
|
" \n",
|
||||||
|
" x = self.conv2(x)\n",
|
||||||
|
" x = self.relu(x)\n",
|
||||||
|
"\n",
|
||||||
|
" x = x.view(-1, 32 * 4 * 4)\n",
|
||||||
|
"\n",
|
||||||
|
" x = self.fc1(x)\n",
|
||||||
|
" x = self.relu(x)\n",
|
||||||
|
" x = self.fc2(x)\n",
|
||||||
|
"\n",
|
||||||
|
" return x\n",
|
||||||
|
" \n",
|
||||||
|
"class AdvancedCNN(nn.Module):\n",
|
||||||
|
" def __init__(self):\n",
|
||||||
|
" super(AdvancedCNN, self).__init__()\n",
|
||||||
|
"\n",
|
||||||
|
" self.layer1 = nn.Sequential(\n",
|
||||||
|
" nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, padding=1),\n",
|
||||||
|
" nn.BatchNorm2d(32),\n",
|
||||||
|
" nn.ReLU(),\n",
|
||||||
|
" nn.MaxPool2d(kernel_size=2)\n",
|
||||||
|
" )\n",
|
||||||
|
"\n",
|
||||||
|
" self.layer2 = nn.Sequential(\n",
|
||||||
|
" nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1),\n",
|
||||||
|
" nn.BatchNorm2d(64),\n",
|
||||||
|
" nn.ReLU(),\n",
|
||||||
|
" nn.MaxPool2d(kernel_size=2)\n",
|
||||||
|
" )\n",
|
||||||
|
"\n",
|
||||||
|
" self.fc_layer = nn.Sequential(\n",
|
||||||
|
" nn.Flatten(),\n",
|
||||||
|
" nn.Linear(64 * 2 * 2, 256),\n",
|
||||||
|
" nn.ReLU(),\n",
|
||||||
|
" nn.Dropout(0.5),\n",
|
||||||
|
" nn.Linear(256, 10)\n",
|
||||||
|
" )\n",
|
||||||
|
" \n",
|
||||||
|
" def forward(self, x):\n",
|
||||||
|
" x = self.layer1(x)\n",
|
||||||
|
" x = self.layer2(x)\n",
|
||||||
|
" x = self.fc_layer(x)\n",
|
||||||
|
" return x\n",
|
||||||
|
" \n",
|
||||||
|
"\n",
|
||||||
|
"class SelfAttention(nn.Module):\n",
|
||||||
|
" def __init__(self, in_dim):\n",
|
||||||
|
" super(SelfAttention, self).__init__()\n",
|
||||||
|
" self.query_conv = nn.Conv2d(in_channels=in_dim, out_channels=in_dim // 8, kernel_size=1)\n",
|
||||||
|
" self.key_conv = nn.Conv2d(in_channels=in_dim, out_channels=in_dim // 8, kernel_size=1)\n",
|
||||||
|
" self.value_conv = nn.Conv2d(in_channels=in_dim, out_channels=in_dim, kernel_size=1)\n",
|
||||||
|
" self.gamma = nn.Parameter(torch.zeros(1))\n",
|
||||||
|
" self.softmax = nn.Softmax(dim=-1)\n",
|
||||||
|
"\n",
|
||||||
|
" def forward(self, x):\n",
|
||||||
|
" batch_size, C, width, height = x.size()\n",
|
||||||
|
" proj_query = self.query_conv(x).view(batch_size, -1, width * height).permute(0, 2, 1)\n",
|
||||||
|
" proj_key = self.key_conv(x).view(batch_size, -1, width * height)\n",
|
||||||
|
" energy = torch.bmm(proj_query, proj_key)\n",
|
||||||
|
" attention = self.softmax(energy)\n",
|
||||||
|
" proj_value = self.value_conv(x).view(batch_size, -1, width * height)\n",
|
||||||
|
"\n",
|
||||||
|
" out = torch.bmm(proj_value, attention.permute(0, 2, 1))\n",
|
||||||
|
" out = out.view(batch_size, C, width, height)\n",
|
||||||
|
"\n",
|
||||||
|
" out = self.gamma * out + x\n",
|
||||||
|
" return out\n",
|
||||||
|
" \n",
|
||||||
|
"class AttentionCNN(nn.Module):\n",
|
||||||
|
" def __init__(self):\n",
|
||||||
|
" super(AttentionCNN, self).__init__()\n",
|
||||||
|
"\n",
|
||||||
|
" self.layer1 = nn.Sequential(\n",
|
||||||
|
" nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, padding=1),\n",
|
||||||
|
" nn.BatchNorm2d(32),\n",
|
||||||
|
" nn.ReLU(),\n",
|
||||||
|
" nn.MaxPool2d(kernel_size=2),\n",
|
||||||
|
" SelfAttention(32)\n",
|
||||||
|
" )\n",
|
||||||
|
"\n",
|
||||||
|
" self.layer2 = nn.Sequential(\n",
|
||||||
|
" nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1),\n",
|
||||||
|
" nn.BatchNorm2d(64),\n",
|
||||||
|
" nn.ReLU(),\n",
|
||||||
|
" nn.MaxPool2d(kernel_size=2),\n",
|
||||||
|
" SelfAttention(64),\n",
|
||||||
|
" )\n",
|
||||||
|
"\n",
|
||||||
|
" self.fc_layer = nn.Sequential(\n",
|
||||||
|
" nn.Flatten(),\n",
|
||||||
|
" nn.Linear(64 * 2 * 2, 256),\n",
|
||||||
|
" nn.ReLU(),\n",
|
||||||
|
" nn.Dropout(0.5),\n",
|
||||||
|
" nn.Linear(256, 10)\n",
|
||||||
|
" )\n",
|
||||||
|
" \n",
|
||||||
|
" def forward(self, x):\n",
|
||||||
|
" x = self.layer1(x)\n",
|
||||||
|
" x = self.layer2(x)\n",
|
||||||
|
" x = self.fc_layer(x)\n",
|
||||||
|
" return x"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 20,
|
||||||
|
"id": "d6022185",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"class MicroViT(nn.Module):\n",
|
||||||
|
" def __init__(self, image_size=8, patch_size=2, num_classes=10, dim=64, depth=4, heads=4, mlp_dim=128):\n",
|
||||||
|
" super(MicroViT, self).__init__()\n",
|
||||||
|
" \n",
|
||||||
|
" num_patches = (image_size // patch_size) ** 2\n",
|
||||||
|
" patch_dim = 1 * patch_size * patch_size\n",
|
||||||
|
" \n",
|
||||||
|
" self.patch_to_embedding = nn.Linear(patch_dim, dim)\n",
|
||||||
|
" \n",
|
||||||
|
" self.pos_embedding = nn.Parameter(torch.randn(1, num_patches + 1, dim))\n",
|
||||||
|
"\n",
|
||||||
|
" self.cls_token = nn.Parameter(torch.randn(1, 1, dim))\n",
|
||||||
|
"\n",
|
||||||
|
" encoder_layer = nn.TransformerEncoderLayer(d_model=dim, nhead=heads, dim_feedforward=mlp_dim, dropout=0.1, batch_first=True)\n",
|
||||||
|
" self.transformer = nn.TransformerEncoder(encoder_layer, num_layers=depth)\n",
|
||||||
|
" self.to_cls_token = nn.Identity()\n",
|
||||||
|
" self.mlp_head = nn.Sequential(\n",
|
||||||
|
" nn.LayerNorm(dim),\n",
|
||||||
|
" nn.Linear(dim, num_classes)\n",
|
||||||
|
" )\n",
|
||||||
|
"\n",
|
||||||
|
" self.patch_size = patch_size\n",
|
||||||
|
" self.dim = dim\n",
|
||||||
|
"\n",
|
||||||
|
" def forward(self, img):\n",
|
||||||
|
" # img shape: (batch, 1, 8, 8)\n",
|
||||||
|
" p = self.patch_size\n",
|
||||||
|
" # Flatten Patches\n",
|
||||||
|
" # (batch, 1, 8, 8) -> (batch, 16, 4)\n",
|
||||||
|
" x = img.unfold(2, p, p).unfold(3, p, p).permute(0, 2, 3, 1, 4, 5).contiguous().view(img.shape[0], -1, p*p)\n",
|
||||||
|
" # Embedding\n",
|
||||||
|
" x = self.patch_to_embedding(x) # (batch, 16, 64)\n",
|
||||||
|
" cls_tokens = self.cls_token.expand(x.shape[0], -1, -1)\n",
|
||||||
|
" x = torch.cat((cls_tokens, x), dim=1) # (batch, 17, 64)\n",
|
||||||
|
" x += self.pos_embedding[:, :(x.shape[1])]\n",
|
||||||
|
" x = self.transformer(x)\n",
|
||||||
|
" x = x[:, 0]\n",
|
||||||
|
" return self.mlp_head(x)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 21,
|
||||||
|
"id": "a8d6d064",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Model Declaration\n",
|
||||||
|
"models = {\n",
|
||||||
|
" \"Logistic Regression\": sklearn.linear_model.LogisticRegression(random_state=8),\n",
|
||||||
|
" \"KNN (k=3)\": sklearn.neighbors.KNeighborsClassifier(n_neighbors=3),\n",
|
||||||
|
" \"KNN (k=5)\": sklearn.neighbors.KNeighborsClassifier(n_neighbors=5),\n",
|
||||||
|
" \"KNN (k=7)\": sklearn.neighbors.KNeighborsClassifier(n_neighbors=7),\n",
|
||||||
|
" \"SVM-rbf\": sklearn.svm.SVC(kernel = 'rbf', random_state=8),\n",
|
||||||
|
" \"SVM-linear\": sklearn.svm.SVC(kernel='linear', random_state=8),\n",
|
||||||
|
" \"SVM-sigmoid\": sklearn.svm.SVC(kernel=\"sigmoid\", random_state=8),\n",
|
||||||
|
" \"Decision Tree\": sklearn.tree.DecisionTreeClassifier(random_state=8),\n",
|
||||||
|
" \"Random Forest (50)\": sklearn.ensemble.RandomForestClassifier(n_estimators=50, random_state=8),\n",
|
||||||
|
" \"Random Forest (100)\": sklearn.ensemble.RandomForestClassifier(n_estimators=100, random_state=8),\n",
|
||||||
|
"\n",
|
||||||
|
" \"FDA\": sklearn.discriminant_analysis.LinearDiscriminantAnalysis(),\n",
|
||||||
|
" \"Gaussian NB\": sklearn.naive_bayes.GaussianNB(),\n",
|
||||||
|
" \"MLP (100)\": sklearn.neural_network.MLPClassifier(random_state=8, hidden_layer_sizes=(100,)),\n",
|
||||||
|
" \"MLP (200)\": sklearn.neural_network.MLPClassifier(random_state=8, hidden_layer_sizes=(200,)),\n",
|
||||||
|
" \"MLP (256)\": sklearn.neural_network.MLPClassifier(random_state=8, hidden_layer_sizes=(256,)),\n",
|
||||||
|
"\n",
|
||||||
|
" \"Ensenble (Hard Voting)\": sklearn.ensemble.VotingClassifier(estimators=\n",
|
||||||
|
" [\n",
|
||||||
|
" ('knn', sklearn.neighbors.KNeighborsClassifier(n_neighbors=5)),\n",
|
||||||
|
" ('svm', sklearn.svm.SVC(kernel='rbf', random_state=8)),\n",
|
||||||
|
" ('mlp', sklearn.neural_network.MLPClassifier(random_state=8, hidden_layer_sizes=(200,)))\n",
|
||||||
|
" ],\n",
|
||||||
|
" voting='hard'\n",
|
||||||
|
" ),\n",
|
||||||
|
"}\n",
|
||||||
|
"\n",
|
||||||
|
"results = OrderedDict()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 22,
|
||||||
|
"id": "355b4d31",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# scikit-learn Model\n",
|
||||||
|
"for name, model in models.items():\n",
|
||||||
|
" # Model\n",
|
||||||
|
" model.fit(X_train_scaled, y_train)\n",
|
||||||
|
" \n",
|
||||||
|
" # Prediction\n",
|
||||||
|
" y_pred = model.predict(X_test_scaled)\n",
|
||||||
|
" \n",
|
||||||
|
" # Evaluation\n",
|
||||||
|
" acc = sklearn.metrics.accuracy_score(y_test, y_pred)\n",
|
||||||
|
" results[name] = acc\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 23,
|
||||||
|
"id": "cb5a927a",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Epoch 1/20, Loss: 1.4835\n",
|
||||||
|
"Epoch 2/20, Loss: 0.3041\n",
|
||||||
|
"Epoch 3/20, Loss: 0.1692\n",
|
||||||
|
"Epoch 4/20, Loss: 0.1133\n",
|
||||||
|
"Epoch 5/20, Loss: 0.0763\n",
|
||||||
|
"Epoch 6/20, Loss: 0.0634\n",
|
||||||
|
"Epoch 7/20, Loss: 0.0397\n",
|
||||||
|
"Epoch 8/20, Loss: 0.0345\n",
|
||||||
|
"Epoch 9/20, Loss: 0.0372\n",
|
||||||
|
"Epoch 10/20, Loss: 0.0189\n",
|
||||||
|
"Epoch 11/20, Loss: 0.0167\n",
|
||||||
|
"Epoch 12/20, Loss: 0.0132\n",
|
||||||
|
"Epoch 13/20, Loss: 0.0096\n",
|
||||||
|
"Epoch 14/20, Loss: 0.0092\n",
|
||||||
|
"Epoch 15/20, Loss: 0.0080\n",
|
||||||
|
"Epoch 16/20, Loss: 0.0074\n",
|
||||||
|
"Epoch 17/20, Loss: 0.0044\n",
|
||||||
|
"Epoch 18/20, Loss: 0.0039\n",
|
||||||
|
"Epoch 19/20, Loss: 0.0025\n",
|
||||||
|
"Epoch 20/20, Loss: 0.0021\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# CNN\n",
|
||||||
|
"\n",
|
||||||
|
"model = DigitCNN()\n",
|
||||||
|
"crit = nn.CrossEntropyLoss()\n",
|
||||||
|
"optimizer = optim.Adam(model.parameters(), lr = 0.001)\n",
|
||||||
|
"\n",
|
||||||
|
"train_ds = torch.utils.data.TensorDataset(X_train_tensor, y_train_tensor)\n",
|
||||||
|
"train_loader = torch.utils.data.DataLoader(train_ds, batch_size=32, shuffle=True)\n",
|
||||||
|
"\n",
|
||||||
|
"epochs = 20\n",
|
||||||
|
"\n",
|
||||||
|
"for ep in range(epochs):\n",
|
||||||
|
" model.train()\n",
|
||||||
|
" running_loss = 0.0\n",
|
||||||
|
" for inputs, labels in train_loader:\n",
|
||||||
|
" optimizer.zero_grad()\n",
|
||||||
|
" pred = model(inputs)\n",
|
||||||
|
" loss = crit(pred, labels)\n",
|
||||||
|
" loss.backward()\n",
|
||||||
|
" optimizer.step()\n",
|
||||||
|
"\n",
|
||||||
|
" running_loss += loss.item()\n",
|
||||||
|
" \n",
|
||||||
|
" print(f\"Epoch {ep+1}/{epochs}, Loss: {running_loss/len(train_loader):.4f}\")\n",
|
||||||
|
"\n",
|
||||||
|
"model.eval()\n",
|
||||||
|
"with torch.no_grad():\n",
|
||||||
|
" outputs = model(X_test_tensor)\n",
|
||||||
|
"\n",
|
||||||
|
" _, predicted = torch.max(outputs, 1)\n",
|
||||||
|
"\n",
|
||||||
|
" correct = (predicted == y_test_tensor).sum().item()\n",
|
||||||
|
" total = len(y_test_tensor)\n",
|
||||||
|
"\n",
|
||||||
|
" acc = correct / total\n",
|
||||||
|
" results[\"CNN(Basic)\"] = acc\n",
|
||||||
|
"\n",
|
||||||
|
"models[\"CNN(Basic)\"] = model"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 24,
|
||||||
|
"id": "c12d6f80",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Epoch 1/30, Loss: 1.0062\n",
|
||||||
|
"Epoch 2/30, Loss: 0.2038\n",
|
||||||
|
"Epoch 3/30, Loss: 0.0946\n",
|
||||||
|
"Epoch 4/30, Loss: 0.0699\n",
|
||||||
|
"Epoch 5/30, Loss: 0.0722\n",
|
||||||
|
"Epoch 6/30, Loss: 0.0523\n",
|
||||||
|
"Epoch 7/30, Loss: 0.0287\n",
|
||||||
|
"Epoch 8/30, Loss: 0.0869\n",
|
||||||
|
"Epoch 9/30, Loss: 0.0896\n",
|
||||||
|
"Epoch 10/30, Loss: 0.0572\n",
|
||||||
|
"Epoch 11/30, Loss: 0.0138\n",
|
||||||
|
"Epoch 12/30, Loss: 0.0083\n",
|
||||||
|
"Epoch 13/30, Loss: 0.0079\n",
|
||||||
|
"Epoch 14/30, Loss: 0.0040\n",
|
||||||
|
"Epoch 15/30, Loss: 0.0025\n",
|
||||||
|
"Epoch 16/30, Loss: 0.0031\n",
|
||||||
|
"Epoch 17/30, Loss: 0.0030\n",
|
||||||
|
"Epoch 18/30, Loss: 0.0014\n",
|
||||||
|
"Epoch 19/30, Loss: 0.0074\n",
|
||||||
|
"Epoch 20/30, Loss: 0.0023\n",
|
||||||
|
"Epoch 21/30, Loss: 0.0028\n",
|
||||||
|
"Epoch 22/30, Loss: 0.0028\n",
|
||||||
|
"Epoch 23/30, Loss: 0.0015\n",
|
||||||
|
"Epoch 24/30, Loss: 0.0014\n",
|
||||||
|
"Epoch 25/30, Loss: 0.0014\n",
|
||||||
|
"Epoch 26/30, Loss: 0.0028\n",
|
||||||
|
"Epoch 27/30, Loss: 0.0019\n",
|
||||||
|
"Epoch 28/30, Loss: 0.0016\n",
|
||||||
|
"Epoch 29/30, Loss: 0.0009\n",
|
||||||
|
"Epoch 30/30, Loss: 0.0011\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# More Advanced CNN\n",
|
||||||
|
"\n",
|
||||||
|
"model = AdvancedCNN()\n",
|
||||||
|
"crit = nn.CrossEntropyLoss()\n",
|
||||||
|
"optimizer = optim.Adam(model.parameters(), lr = 0.003)\n",
|
||||||
|
"\n",
|
||||||
|
"train_ds = torch.utils.data.TensorDataset(X_train_tensor, y_train_tensor)\n",
|
||||||
|
"train_loader = torch.utils.data.DataLoader(train_ds, batch_size=32, shuffle=True)\n",
|
||||||
|
"\n",
|
||||||
|
"scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.5)\n",
|
||||||
|
"epochs = 30\n",
|
||||||
|
"\n",
|
||||||
|
"for ep in range(epochs):\n",
|
||||||
|
" model.train()\n",
|
||||||
|
" running_loss = 0.0\n",
|
||||||
|
" for inputs, labels in train_loader:\n",
|
||||||
|
" optimizer.zero_grad()\n",
|
||||||
|
" pred = model(inputs)\n",
|
||||||
|
" loss = crit(pred, labels)\n",
|
||||||
|
" loss.backward()\n",
|
||||||
|
" optimizer.step()\n",
|
||||||
|
"\n",
|
||||||
|
" running_loss += loss.item()\n",
|
||||||
|
" scheduler.step()\n",
|
||||||
|
" \n",
|
||||||
|
" print(f\"Epoch {ep+1}/{epochs}, Loss: {running_loss/len(train_loader):.4f}\")\n",
|
||||||
|
"\n",
|
||||||
|
"model.eval()\n",
|
||||||
|
"with torch.no_grad():\n",
|
||||||
|
" outputs = model(X_test_tensor)\n",
|
||||||
|
"\n",
|
||||||
|
" _, predicted = torch.max(outputs, 1)\n",
|
||||||
|
"\n",
|
||||||
|
" correct = (predicted == y_test_tensor).sum().item()\n",
|
||||||
|
" total = len(y_test_tensor)\n",
|
||||||
|
"\n",
|
||||||
|
" acc = correct / total\n",
|
||||||
|
" results[\"CNN(Advanced)\"] = acc\n",
|
||||||
|
"\n",
|
||||||
|
"models[\"CNN(Advanced)\"] = model"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 25,
|
||||||
|
"id": "2302086f",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Epoch 1/30, Loss: 0.9964\n",
|
||||||
|
"Epoch 2/30, Loss: 0.1444\n",
|
||||||
|
"Epoch 3/30, Loss: 0.1252\n",
|
||||||
|
"Epoch 4/30, Loss: 0.0942\n",
|
||||||
|
"Epoch 5/30, Loss: 0.0990\n",
|
||||||
|
"Epoch 6/30, Loss: 0.0206\n",
|
||||||
|
"Epoch 7/30, Loss: 0.0215\n",
|
||||||
|
"Epoch 8/30, Loss: 0.0290\n",
|
||||||
|
"Epoch 9/30, Loss: 0.0399\n",
|
||||||
|
"Epoch 10/30, Loss: 0.0283\n",
|
||||||
|
"Epoch 11/30, Loss: 0.0218\n",
|
||||||
|
"Epoch 12/30, Loss: 0.0047\n",
|
||||||
|
"Epoch 13/30, Loss: 0.0032\n",
|
||||||
|
"Epoch 14/30, Loss: 0.0030\n",
|
||||||
|
"Epoch 15/30, Loss: 0.0016\n",
|
||||||
|
"Epoch 16/30, Loss: 0.0017\n",
|
||||||
|
"Epoch 17/30, Loss: 0.0016\n",
|
||||||
|
"Epoch 18/30, Loss: 0.0011\n",
|
||||||
|
"Epoch 19/30, Loss: 0.0014\n",
|
||||||
|
"Epoch 20/30, Loss: 0.0015\n",
|
||||||
|
"Epoch 21/30, Loss: 0.0016\n",
|
||||||
|
"Epoch 22/30, Loss: 0.0009\n",
|
||||||
|
"Epoch 23/30, Loss: 0.0013\n",
|
||||||
|
"Epoch 24/30, Loss: 0.0005\n",
|
||||||
|
"Epoch 25/30, Loss: 0.0009\n",
|
||||||
|
"Epoch 26/30, Loss: 0.0011\n",
|
||||||
|
"Epoch 27/30, Loss: 0.0005\n",
|
||||||
|
"Epoch 28/30, Loss: 0.0015\n",
|
||||||
|
"Epoch 29/30, Loss: 0.0011\n",
|
||||||
|
"Epoch 30/30, Loss: 0.0005\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Attention CNN\n",
|
||||||
|
"\n",
|
||||||
|
"model = AttentionCNN()\n",
|
||||||
|
"crit = nn.CrossEntropyLoss()\n",
|
||||||
|
"optimizer = optim.Adam(model.parameters(), lr = 0.003)\n",
|
||||||
|
"\n",
|
||||||
|
"train_ds = torch.utils.data.TensorDataset(X_train_tensor, y_train_tensor)\n",
|
||||||
|
"train_loader = torch.utils.data.DataLoader(train_ds, batch_size=32, shuffle=True)\n",
|
||||||
|
"\n",
|
||||||
|
"scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.5)\n",
|
||||||
|
"epochs = 30\n",
|
||||||
|
"\n",
|
||||||
|
"for ep in range(epochs):\n",
|
||||||
|
" model.train()\n",
|
||||||
|
" running_loss = 0.0\n",
|
||||||
|
" for inputs, labels in train_loader:\n",
|
||||||
|
" optimizer.zero_grad()\n",
|
||||||
|
" pred = model(inputs)\n",
|
||||||
|
" loss = crit(pred, labels)\n",
|
||||||
|
" loss.backward()\n",
|
||||||
|
" optimizer.step()\n",
|
||||||
|
"\n",
|
||||||
|
" running_loss += loss.item()\n",
|
||||||
|
" scheduler.step()\n",
|
||||||
|
" \n",
|
||||||
|
" print(f\"Epoch {ep+1}/{epochs}, Loss: {running_loss/len(train_loader):.4f}\")\n",
|
||||||
|
"\n",
|
||||||
|
"model.eval()\n",
|
||||||
|
"with torch.no_grad():\n",
|
||||||
|
" outputs = model(X_test_tensor)\n",
|
||||||
|
"\n",
|
||||||
|
" _, predicted = torch.max(outputs, 1)\n",
|
||||||
|
"\n",
|
||||||
|
" correct = (predicted == y_test_tensor).sum().item()\n",
|
||||||
|
" total = len(y_test_tensor)\n",
|
||||||
|
"\n",
|
||||||
|
" acc = correct / total\n",
|
||||||
|
" results[\"CNN(Attention)\"] = acc\n",
|
||||||
|
"\n",
|
||||||
|
"models[\"CNN(Attention)\"] = model"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 26,
|
||||||
|
"id": "d37f1199",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Epoch 1/50, Loss: 1.7488\n",
|
||||||
|
"Epoch 2/50, Loss: 0.5374\n",
|
||||||
|
"Epoch 3/50, Loss: 0.2700\n",
|
||||||
|
"Epoch 4/50, Loss: 0.1750\n",
|
||||||
|
"Epoch 5/50, Loss: 0.1070\n",
|
||||||
|
"Epoch 6/50, Loss: 0.0909\n",
|
||||||
|
"Epoch 7/50, Loss: 0.0724\n",
|
||||||
|
"Epoch 8/50, Loss: 0.0588\n",
|
||||||
|
"Epoch 9/50, Loss: 0.0535\n",
|
||||||
|
"Epoch 10/50, Loss: 0.0513\n",
|
||||||
|
"Epoch 11/50, Loss: 0.0481\n",
|
||||||
|
"Epoch 12/50, Loss: 0.0489\n",
|
||||||
|
"Epoch 13/50, Loss: 0.0683\n",
|
||||||
|
"Epoch 14/50, Loss: 0.0676\n",
|
||||||
|
"Epoch 15/50, Loss: 0.0413\n",
|
||||||
|
"Epoch 16/50, Loss: 0.0394\n",
|
||||||
|
"Epoch 17/50, Loss: 0.0257\n",
|
||||||
|
"Epoch 18/50, Loss: 0.0174\n",
|
||||||
|
"Epoch 19/50, Loss: 0.0241\n",
|
||||||
|
"Epoch 20/50, Loss: 0.0203\n",
|
||||||
|
"Epoch 21/50, Loss: 0.0109\n",
|
||||||
|
"Epoch 22/50, Loss: 0.0087\n",
|
||||||
|
"Epoch 23/50, Loss: 0.0105\n",
|
||||||
|
"Epoch 24/50, Loss: 0.0111\n",
|
||||||
|
"Epoch 25/50, Loss: 0.0082\n",
|
||||||
|
"Epoch 26/50, Loss: 0.0050\n",
|
||||||
|
"Epoch 27/50, Loss: 0.0032\n",
|
||||||
|
"Epoch 28/50, Loss: 0.0040\n",
|
||||||
|
"Epoch 29/50, Loss: 0.0050\n",
|
||||||
|
"Epoch 30/50, Loss: 0.0060\n",
|
||||||
|
"Epoch 31/50, Loss: 0.0035\n",
|
||||||
|
"Epoch 32/50, Loss: 0.0024\n",
|
||||||
|
"Epoch 33/50, Loss: 0.0023\n",
|
||||||
|
"Epoch 34/50, Loss: 0.0038\n",
|
||||||
|
"Epoch 35/50, Loss: 0.0020\n",
|
||||||
|
"Epoch 36/50, Loss: 0.0019\n",
|
||||||
|
"Epoch 37/50, Loss: 0.0021\n",
|
||||||
|
"Epoch 38/50, Loss: 0.0042\n",
|
||||||
|
"Epoch 39/50, Loss: 0.0023\n",
|
||||||
|
"Epoch 40/50, Loss: 0.0025\n",
|
||||||
|
"Epoch 41/50, Loss: 0.0022\n",
|
||||||
|
"Epoch 42/50, Loss: 0.0039\n",
|
||||||
|
"Epoch 43/50, Loss: 0.0018\n",
|
||||||
|
"Epoch 44/50, Loss: 0.0017\n",
|
||||||
|
"Epoch 45/50, Loss: 0.0018\n",
|
||||||
|
"Epoch 46/50, Loss: 0.0017\n",
|
||||||
|
"Epoch 47/50, Loss: 0.0020\n",
|
||||||
|
"Epoch 48/50, Loss: 0.0020\n",
|
||||||
|
"Epoch 49/50, Loss: 0.0030\n",
|
||||||
|
"Epoch 50/50, Loss: 0.0021\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Micro ViT\n",
|
||||||
|
"train_ds = torch.utils.data.TensorDataset(X_train_tensor, y_train_tensor)\n",
|
||||||
|
"train_loader = torch.utils.data.DataLoader(train_ds, batch_size=32, shuffle=True)\n",
|
||||||
|
"\n",
|
||||||
|
"model = MicroViT()\n",
|
||||||
|
"crit = nn.CrossEntropyLoss()\n",
|
||||||
|
"optimizer = optim.AdamW(model.parameters(), lr = 0.001, weight_decay=1e-4)\n",
|
||||||
|
"scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=50)\n",
|
||||||
|
"epochs = 50\n",
|
||||||
|
"\n",
|
||||||
|
"for ep in range(epochs):\n",
|
||||||
|
" model.train()\n",
|
||||||
|
" running_loss = 0.0\n",
|
||||||
|
" for inputs, labels in train_loader:\n",
|
||||||
|
" optimizer.zero_grad()\n",
|
||||||
|
" pred = model(inputs)\n",
|
||||||
|
" loss = crit(pred, labels)\n",
|
||||||
|
" loss.backward()\n",
|
||||||
|
" optimizer.step()\n",
|
||||||
|
"\n",
|
||||||
|
" running_loss += loss.item()\n",
|
||||||
|
" scheduler.step()\n",
|
||||||
|
" \n",
|
||||||
|
" print(f\"Epoch {ep+1}/{epochs}, Loss: {running_loss/len(train_loader):.4f}\")\n",
|
||||||
|
"\n",
|
||||||
|
"model.eval()\n",
|
||||||
|
"with torch.no_grad():\n",
|
||||||
|
" outputs = model(X_test_tensor)\n",
|
||||||
|
"\n",
|
||||||
|
" _, predicted = torch.max(outputs, 1)\n",
|
||||||
|
"\n",
|
||||||
|
" correct = (predicted == y_test_tensor).sum().item()\n",
|
||||||
|
" total = len(y_test_tensor)\n",
|
||||||
|
"\n",
|
||||||
|
" acc = correct / total\n",
|
||||||
|
" results[\"MicroViT\"] = acc\n",
|
||||||
|
"\n",
|
||||||
|
"models[\"MicroViT\"] = model"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 27,
|
||||||
|
"id": "60671a49",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Algorithm | Accuracy \n",
|
||||||
|
"--------------------------------------------------\n",
|
||||||
|
"CNN(Advanced) | 0.9889\n",
|
||||||
|
"CNN(Attention) | 0.9861\n",
|
||||||
|
"Ensenble (Hard Voting) | 0.9833\n",
|
||||||
|
"MicroViT | 0.9833\n",
|
||||||
|
"CNN(Basic) | 0.9806\n",
|
||||||
|
"KNN (k=5) | 0.9778\n",
|
||||||
|
"SVM-rbf | 0.9778\n",
|
||||||
|
"MLP (200) | 0.9778\n",
|
||||||
|
"KNN (k=3) | 0.9750\n",
|
||||||
|
"KNN (k=7) | 0.9750\n",
|
||||||
|
"MLP (256) | 0.9750\n",
|
||||||
|
"SVM-linear | 0.9722\n",
|
||||||
|
"Random Forest (50) | 0.9722\n",
|
||||||
|
"MLP (100) | 0.9722\n",
|
||||||
|
"Logistic Regression | 0.9667\n",
|
||||||
|
"Random Forest (100) | 0.9667\n",
|
||||||
|
"FDA | 0.9583\n",
|
||||||
|
"SVM-sigmoid | 0.9528\n",
|
||||||
|
"Decision Tree | 0.8556\n",
|
||||||
|
"Gaussian NB | 0.7750\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"image/png": "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 truncated
|
||||||
|
"text/plain": [
|
||||||
|
"<Figure size 1400x800 with 1 Axes>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "display_data"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"print(f\"{'Algorithm':<35} | {'Accuracy':<10}\")\n",
|
||||||
|
"print(\"-\" * 50)\n",
|
||||||
|
"\n",
|
||||||
|
"results = OrderedDict(\n",
|
||||||
|
" sorted(results.items(), key=lambda item: item[1], reverse=True)\n",
|
||||||
|
")\n",
|
||||||
|
"\n",
|
||||||
|
"# --- 5. 결과 시각화 ---\n",
|
||||||
|
"for model, acc in results.items():\n",
|
||||||
|
" print(f\"{model:<35} | {acc:.4f}\")\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"plt.figure(figsize=(14, 8))\n",
|
||||||
|
"sns.barplot(x=list(results.values()), y=list(results.keys()), hue=list(results.keys()), palette=\"plasma\", legend=False)\n",
|
||||||
|
"plt.title(\"Model Performance Comparison (Accuracy)\")\n",
|
||||||
|
"plt.xlabel(\"Accuracy\")\n",
|
||||||
|
"plt.xlim(0.75, 1.0) # 정확도 차이를 잘 보기 위해 범위 조정\n",
|
||||||
|
"plt.grid(axis='x', linestyle='--', alpha=0.7)\n",
|
||||||
|
"plt.show()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "02290a5a",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"## Error Analysis\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 33,
|
||||||
|
"id": "19c824f7",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"image/png": "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 truncated
|
||||||
|
"text/plain": [
|
||||||
|
"<Figure size 1200x600 with 5 Axes>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "display_data"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"model = models[\"CNN(Attention)\"]\n",
|
||||||
|
"model.eval()\n",
|
||||||
|
"\n",
|
||||||
|
"with torch.no_grad():\n",
|
||||||
|
" outputs = model(X_test_tensor)\n",
|
||||||
|
" _, predicted = torch.max(outputs, 1)\n",
|
||||||
|
" \n",
|
||||||
|
" # 정답과 예측이 다른 인덱스 추출\n",
|
||||||
|
" wrong_indices = (predicted != y_test_tensor).nonzero(as_tuple=True)[0].numpy()\n",
|
||||||
|
" \n",
|
||||||
|
" # 실제 라벨과 예측 라벨 가져오기\n",
|
||||||
|
" wrong_labels = y_test_tensor[wrong_indices].numpy()\n",
|
||||||
|
" wrong_preds = predicted[wrong_indices].numpy()\n",
|
||||||
|
" wrong_images = X_test_tensor[wrong_indices].numpy()\n",
|
||||||
|
"\n",
|
||||||
|
"# 시각화 (최대 10개만)\n",
|
||||||
|
"plt.figure(figsize=(12, 6))\n",
|
||||||
|
"num_show = min(10, len(wrong_indices))\n",
|
||||||
|
"\n",
|
||||||
|
"for i in range(num_show):\n",
|
||||||
|
" ax = plt.subplot(2, 5, i + 1)\n",
|
||||||
|
" # 이미지 형태 복원 (1, 8, 8) -> (8, 8)\n",
|
||||||
|
" img = wrong_images[i].reshape(8, 8) \n",
|
||||||
|
" ax.imshow(img, cmap='gray_r')\n",
|
||||||
|
" ax.set_title(f\"True: {wrong_labels[i]}\\nPred: {wrong_preds[i]}\", color='red')\n",
|
||||||
|
" ax.axis('off')\n",
|
||||||
|
"\n",
|
||||||
|
"plt.suptitle(\"Misclassified Samples Analysis\", fontsize=16)\n",
|
||||||
|
"plt.tight_layout()\n",
|
||||||
|
"plt.show()"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "2025-02-ai-hw2",
|
||||||
|
"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.12.11"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
||||||
Reference in new issue
Block a user