Initial commit

This commit is contained in:
2025-12-19 10:11:58 +01:00
commit ccad4e85a9
12 changed files with 417 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" />
</content>
<orderEntry type="jdk" jdkName="Python 3.12 (cnn_image_classification)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
+6
View File
@@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.12 (cnn_image_classification)" />
</component>
</project>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/cnn_image_classification.iml" filepath="$PROJECT_DIR$/.idea/cnn_image_classification.iml" />
</modules>
</component>
</project>
Generated
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
+9
View File
@@ -0,0 +1,9 @@
# Tutorial
## Python CNN image classification from with jupyter, torch, torchvision and pillow
from https://youtu.be/CtzfbUwrYGI?si=09iwSO4S5DtaAl4G
# Notes
## Register venv at jupyter lab
pip3 install ipykernel
python3 -m ipykernel install --user --name=.venv
Executable
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Executable
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Executable
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

+349
View File
@@ -0,0 +1,349 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 17,
"id": "2e9496e9-ec07-445f-b29d-fc44aabb377d",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"from PIL import Image\n",
"import torch\n",
"import torch.nn as nn\n",
"import torch.nn.functional as F\n",
"import torch.optim as optim\n",
"import torchvision\n",
"import torchvision.transforms as transforms"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "9b17757b-76c5-4562-a2be-e3a50201c9ee",
"metadata": {},
"outputs": [],
"source": [
"transform = transforms.Compose([transforms.ToTensor(), import numpy as np\n",
"from PIL import Image\n",
"import torch\n",
"import torch.nn as nn\n",
"import torch.nn.functional as F\n",
"import torch.optim as opim\n",
"import torchvision\n",
"import torchvision.transform as transform\n",
"\n",
"]) "
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "5b898116-e9a8-429d-8491-67db5a65d358",
"metadata": {},
"outputs": [],
"source": [
"train_data = torchvision.datasets.CIFAR10(root='./data', train=True, transform=transform, download=True)\n",
"test_data = torchvision.datasets.CIFAR10(root='./data', train=False, transform=transform, download=True)\n",
"\n",
"train_loader = torch.utils.data.DataLoader(train_data, batch_size=32, shuffle=True, num_workers=2)\n",
"test_loader = torch.utils.data.DataLoader(test_data, batch_size=32, shuffle=True, num_workers=2)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "49712fae-dfe6-4b6f-92ea-2e97a965c15c",
"metadata": {},
"outputs": [],
"source": [
"image, label = train_data[0]"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "d783e1a5-3410-4992-88a6-230dd2ec85dd",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"torch.Size([3, 32, 32])"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"image.size()"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "8ef21399-f2f2-46f4-8268-f60f36bbb533",
"metadata": {},
"outputs": [],
"source": [
"class_names = ['plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "192ff676-c4b8-4611-9338-ec9b35a502d5",
"metadata": {},
"outputs": [],
"source": [
"class NeuralNet(nn.Module):\n",
" def __init__(self):\n",
" super().__init__()\n",
" self.conv1 = nn.Conv2d(3, 12, 5) # (12, 28, 28)\n",
" self.pool = nn.MaxPool2d(2, 2) # (12, 14, 14)\n",
" self.conv2 = nn.Conv2d(12, 24, 5) # (24, 10, 10) -> (24, 5, 5) -> Flatten (25 * 5 * 5)\n",
" self.fc1 = nn.Linear(24 * 5 * 5, 120)\n",
" self.fc2 = nn.Linear(120, 84)\n",
" self.fc3 = nn.Linear(84, 10)\n",
"\n",
" def forward(self, x):\n",
" x = self.pool(F.relu(self.conv1(x)))\n",
" x = self.pool(F.relu(self.conv2(x)))\n",
" x = torch.flatten(x, 1)\n",
" x = F.relu(self.fc1(x))\n",
" x = F.relu(self.fc2(x))\n",
" x = self.fc3(x)\n",
" return x"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "f48dd819-9196-4aa5-92c4-ddcc644c6aa9",
"metadata": {},
"outputs": [],
"source": [
"net = NeuralNet()\n",
"loss_function = nn.CrossEntropyLoss()\n",
"optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "3a91ce0c-e71d-4bfb-b945-47edfc8ca8d6",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Training epoch 0...\n",
"Loss: 2.1758\n",
"Training epoch 1...\n",
"Loss: 1.7324\n",
"Training epoch 2...\n",
"Loss: 1.5096\n",
"Training epoch 3...\n",
"Loss: 1.3996\n",
"Training epoch 4...\n",
"Loss: 1.3065\n",
"Training epoch 5...\n",
"Loss: 1.2286\n",
"Training epoch 6...\n",
"Loss: 1.1649\n",
"Training epoch 7...\n",
"Loss: 1.1101\n",
"Training epoch 8...\n",
"Loss: 1.0568\n",
"Training epoch 9...\n",
"Loss: 1.0140\n",
"Training epoch 10...\n",
"Loss: 0.9719\n",
"Training epoch 11...\n",
"Loss: 0.9321\n",
"Training epoch 12...\n",
"Loss: 0.8969\n",
"Training epoch 13...\n",
"Loss: 0.8649\n",
"Training epoch 14...\n",
"Loss: 0.8326\n",
"Training epoch 15...\n",
"Loss: 0.8014\n",
"Training epoch 16...\n",
"Loss: 0.7764\n",
"Training epoch 17...\n",
"Loss: 0.7449\n",
"Training epoch 18...\n",
"Loss: 0.7199\n",
"Training epoch 19...\n",
"Loss: 0.6991\n",
"Training epoch 20...\n",
"Loss: 0.6700\n",
"Training epoch 21...\n",
"Loss: 0.6438\n",
"Training epoch 22...\n",
"Loss: 0.6243\n",
"Training epoch 23...\n",
"Loss: 0.6051\n",
"Training epoch 24...\n",
"Loss: 0.5802\n",
"Training epoch 25...\n",
"Loss: 0.5609\n",
"Training epoch 26...\n",
"Loss: 0.5381\n",
"Training epoch 27...\n",
"Loss: 0.5162\n",
"Training epoch 28...\n",
"Loss: 0.4949\n",
"Training epoch 29...\n",
"Loss: 0.4752\n"
]
}
],
"source": [
"for epoch in range(30):\n",
" print(f'Training epoch {epoch}...')\n",
"\n",
" running_loss = 0.0\n",
"\n",
" for i, data in enumerate(train_loader):\n",
" inputs, labels = data\n",
" optimizer.zero_grad()\n",
" outputs = net(inputs)\n",
" loss = loss_function(outputs, labels)\n",
" loss.backward()\n",
" optimizer.step()\n",
" \n",
" running_loss += loss.item()\n",
"\n",
" print(f'Loss: {running_loss / len(train_loader):0.4f}')"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "aa5b2497-90a7-44a9-9985-427b920945eb",
"metadata": {},
"outputs": [],
"source": [
"torch.save(net.state_dict(), 'trained_net.pth')"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "ff62419f-ead5-4244-9a5e-a21d568bdca8",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<All keys matched successfully>"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"net = NeuralNet()\n",
"net.load_state_dict(torch.load('trained_net.pth'))"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "eb1d4385-d4da-454f-9d8c-d844aa7b24df",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Accuracy: 68.23%\n"
]
}
],
"source": [
"correct = 0\n",
"total = 0\n",
"net.eval()\n",
"with torch.no_grad():\n",
" for data in test_loader:\n",
" images, labels = data\n",
" outputs = net(images)\n",
" _, predicted = torch.max(outputs, 1)\n",
" total += labels.size(0)\n",
" correct += (predicted == labels).sum().item()\n",
"\n",
"accuracy = 100 * correct / total\n",
"print(f'Accuracy: {accuracy}%')"
]
},
{
"cell_type": "code",
"execution_count": 32,
"id": "1a4f098f-b1ea-46b7-a7d6-769f80292f5f",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Prediction: cat\n",
"Prediction: deer\n",
"Prediction: plane\n"
]
}
],
"source": [
"new_transform = transforms.Compose([\n",
" transforms.Resize((32, 32)), \n",
" transforms.ToTensor(),\n",
" transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))\n",
"])\n",
"\n",
"def load_image(image_path):\n",
" image = Image.open(image_path)\n",
" image = new_transform(image)\n",
" image = image.unsqueeze(0)\n",
" return image\n",
"\n",
"image_paths = ['item1.jpg', 'item2.jpg', 'item3.jpg']\n",
"images = [load_image(img) for img in image_paths]\n",
"\n",
"net.eval()\n",
"with torch.no_grad():\n",
" for image in images:\n",
" output = net(image)\n",
" _, predicted = torch.max(output, 1)\n",
" print(f'Prediction: {class_names[predicted.item()]}')"
]
}
],
"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.12.3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
+20
View File
@@ -0,0 +1,20 @@
requires = [
"setuptools>=61.0"
]
build-backend = "setuptools.build_meta"
[project]
name = "pyCnnImageClassifier"
description = "Python CNN image classification from with jupyter, torch, torchvision and pillow"
dynamic = ["version"]
requires-python = ">=3.12"
authors = [
{ name = "Jens Ahrensfeld" }
]
dependencies = [
"pillow",
"torch",
"torchvision",
"jupyterlab"
]
readme = "README.md"