Rahuletto commited on
Commit
bb5cad1
·
verified ·
1 Parent(s): c755b0e

Upload folder using huggingface_hub

Browse files
.gitattributes CHANGED
@@ -33,3 +33,10 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ assets/rec.mp4 filter=lfs diff=lfs merge=lfs -text
37
+ examples/1.png filter=lfs diff=lfs merge=lfs -text
38
+ examples/2.png filter=lfs diff=lfs merge=lfs -text
39
+ examples/4.png filter=lfs diff=lfs merge=lfs -text
40
+ examples/5.png filter=lfs diff=lfs merge=lfs -text
41
+ examples/6.png filter=lfs diff=lfs merge=lfs -text
42
+ examples/7.png filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+
12
+ .DS_Store
13
+ cifar/
14
+
15
+ .gradio/
.python-version ADDED
@@ -0,0 +1 @@
 
 
1
+ 3.12
LICENSE ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ Copyright 2025 Rahul Marban
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
README.md CHANGED
@@ -1,12 +1,143 @@
1
  ---
2
  title: CNN
3
- emoji: 🔥
4
- colorFrom: indigo
5
- colorTo: indigo
6
  sdk: gradio
7
  sdk_version: 5.35.0
8
- app_file: app.py
9
- pinned: false
10
  ---
 
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
  title: CNN
3
+ app_file: main.py
 
 
4
  sdk: gradio
5
  sdk_version: 5.35.0
 
 
6
  ---
7
+ # CNN with CIFAR-10
8
 
9
+ A PyTorch implementation of a Convolutional Neural Network (CNN) for image classification on the CIFAR-10 dataset, achieving **81.45% test accuracy**.
10
+
11
+ ## Architecture
12
+
13
+ ![CNN Architecture](assets/architecture.png)
14
+
15
+ The CNN model consists of
16
+ ### Convolutional Layers:
17
+ - **Conv1**: 3 → 32 channels, 3x3 kernel, padding=1
18
+ - **Conv2**: 32 → 64 channels, 3x3 kernel, padding=1
19
+ - **Conv3**: 64 → 128 channels, 3x3 kernel, padding=1
20
+
21
+ ### Others
22
+ - **Batch Normalization** after each convolutional layer
23
+ - **MaxPooling2D** (2x2) for downsampling
24
+ - **ReLU** activation functions
25
+ - **Fully Connected Layers**: 2048 → 512 → 10
26
+ - **Dropout** (50%) for regularization
27
+
28
+
29
+ ## Getting Started
30
+
31
+ ### Prerequisites
32
+ - Python 3.12+
33
+ - PyTorch 2.7.1+
34
+ - torchvision 0.22.1+
35
+
36
+ > [!TIP]
37
+ > This project was developed with `uv`, so it is best to use `uv` for project management.
38
+
39
+ ### Installation
40
+
41
+ 1. **Clone the repository:**
42
+ ```bash
43
+ git clone https://github.com/rahuletto/cnn
44
+ cd CNN
45
+ ```
46
+
47
+ 2. **Create virtual environment:**
48
+ ```bash
49
+ python -m venv .venv
50
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
51
+ ```
52
+
53
+ 3. **Install dependencies:**
54
+ ```bash
55
+ pip install -r requirements.txt
56
+ ```
57
+
58
+ ### Running the model
59
+
60
+ 1. Run the main file
61
+ ```bash
62
+ python main.py
63
+ ```
64
+
65
+ You can play around in the gradio interface
66
+
67
+ <video controls src="rec.mp4" title="Title"></video>
68
+
69
+ ## Model Code
70
+ ```py
71
+ class CNN(nn.Module):
72
+ def __init__(self):
73
+ super(CNN, self).__init__()
74
+ self.conv1 = nn.Conv2d(3, 32, 3, stride=1, padding=1) # 32x32 -> 16x16
75
+ self.bn1 = nn.BatchNorm2d(32)
76
+ self.conv2 = nn.Conv2d(32, 64, 3, stride=1, padding=1) # 16x16 -> 8x8
77
+ self.bn2 = nn.BatchNorm2d(64)
78
+ self.conv3 = nn.Conv2d(64, 128, 3, stride=1, padding=1) # 8x8 -> 4x4
79
+ self.bn3 = nn.BatchNorm2d(128)
80
+ self.pool = nn.MaxPool2d(stride=2, kernel_size=2)
81
+ self.fc1 = nn.Linear(128 * 4 * 4, 512)
82
+ self.fc2 = nn.Linear(512, 10)
83
+ self.dropout = nn.Dropout(0.5)
84
+
85
+ def forward(self, x):
86
+ x = self.pool(F.relu(self.bn1(self.conv1(x))))
87
+ x = self.pool(F.relu(self.bn2(self.conv2(x))))
88
+ x = self.pool(F.relu(self.bn3(self.conv3(x))))
89
+ x = x.view(x.size(0), -1)
90
+ x = self.dropout(x)
91
+ x = F.relu(self.fc1(x))
92
+ x = self.dropout(x)
93
+ x = self.fc2(x)
94
+ return x
95
+ ```
96
+
97
+
98
+ ## Training Configuration
99
+
100
+ - **Optimizer**: Adam (lr=0.001)
101
+ - **Batch Size**: 64
102
+ - **Epochs**: 50
103
+
104
+ > Best model checkpoint was saved at epoch 49 with validation loss of 0.6553.
105
+
106
+
107
+ # Model
108
+ There are two CNN models in `cnn/` folder
109
+ - `model.pt`
110
+ - `model-old.pt`
111
+
112
+ `model.pt` was trained with `BatchNorm2d` to reach 81.45% accuracy in CIFAR-10 dataset
113
+ `model-old.pt` was trained without fine tuning which gets 75% accuracy in CIFAR-10 dataset
114
+
115
+ ### Accuracy:
116
+
117
+ Total Accuracy: `81.45%`
118
+
119
+ - **Airplane**: `84.60%`
120
+ - **Automobile**: `93.20%`
121
+ - **Bird**: `76.90%`
122
+ - **Cat**: `69.70%`
123
+ - **Deer**: `77.20%`
124
+ - **Dog**: `64.00%`
125
+ - **Frog**: `89.30%`
126
+ - **Horse**: `82.10%`
127
+ - **Ship**: `89.60%`
128
+ - **Truck**: `87.90%`
129
+
130
+ ![Accuracy Benchmark](assets/accuracy.png)
131
+
132
+ ---
133
+
134
+ ## References
135
+
136
+ - [CIFAR-10 Dataset](https://www.cs.toronto.edu/~kriz/cifar.html)
137
+ - [PyTorch Documentation](https://pytorch.org/docs/)
138
+ - [Convolutional Neural Networks for Visual Recognition (CS231n)](http://cs231n.stanford.edu/)
139
+ - [Deep Learning Book - Ian Goodfellow](https://www.deeplearningbook.org/)
140
+
141
+ ## License
142
+
143
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
assets/accuracy.png ADDED
assets/architecture.png ADDED
assets/classes.png ADDED
assets/loss.png ADDED
assets/rec.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:073651ff52cd0a3886e6b4b98400954fbc438149eba047b46b0427ced78ddf06
3
+ size 2555061
cnn/__init__.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch.nn as nn
2
+ import torch.nn.functional as F
3
+
4
+
5
+ class CNN(nn.Module):
6
+ def __init__(self):
7
+ super(CNN, self).__init__()
8
+ self.conv1 = nn.Conv2d(3, 32, 3, stride=1, padding=1) # 32x32 -> 16x16
9
+ self.bn1 = nn.BatchNorm2d(32)
10
+ self.conv2 = nn.Conv2d(32, 64, 3, stride=1, padding=1) # 16x16 -> 8x8
11
+ self.bn2 = nn.BatchNorm2d(64)
12
+ self.conv3 = nn.Conv2d(64, 128, 3, stride=1, padding=1) # 8x8 -> 4x4
13
+ self.bn3 = nn.BatchNorm2d(128)
14
+ self.pool = nn.MaxPool2d(stride=2, kernel_size=2)
15
+ self.fc1 = nn.Linear(128 * 4 * 4, 512)
16
+ self.fc2 = nn.Linear(512, 10)
17
+ self.dropout = nn.Dropout(0.5)
18
+
19
+ def forward(self, x):
20
+ x = self.pool(F.relu(self.bn1(self.conv1(x))))
21
+ x = self.pool(F.relu(self.bn2(self.conv2(x))))
22
+ x = self.pool(F.relu(self.bn3(self.conv3(x))))
23
+ x = x.view(x.size(0), -1)
24
+ x = self.dropout(x)
25
+ x = F.relu(self.fc1(x))
26
+ x = self.dropout(x)
27
+ x = self.fc2(x)
28
+ return x
cnn/model-old.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:13d2fd35f57156f9e29dc8d8074e9975eea9f228b653b06a0a399f117cd5a46b
3
+ size 2167973
cnn/model.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:58b3f32eee5295b7facfe3c98e6e980c1b27086f483fb7e5414d2e1f648b78e7
3
+ size 4600090
examples/1.png ADDED

Git LFS Details

  • SHA256: 43e89de4d62730a0b78d995b959ea1808af08e37ae70ab33bbafaf39623bf359
  • Pointer size: 131 Bytes
  • Size of remote file: 753 kB
examples/2.png ADDED

Git LFS Details

  • SHA256: 40da165ec8aad12aafef1851b2f6a13b5acbc1a35be4659293c2939e66cef679
  • Pointer size: 131 Bytes
  • Size of remote file: 372 kB
examples/3.png ADDED
examples/4.png ADDED

Git LFS Details

  • SHA256: 33a3ed9cfd749c3345a70b5c3dc41a339e1e7b368baea3683502347a98b07be0
  • Pointer size: 131 Bytes
  • Size of remote file: 341 kB
examples/5.png ADDED

Git LFS Details

  • SHA256: 991754fdb6188526802e3b24e8bf6fe880c45443d9cf579b3b8ac156e3ccd430
  • Pointer size: 131 Bytes
  • Size of remote file: 276 kB
examples/6.png ADDED

Git LFS Details

  • SHA256: 6ebdac0fb95095cef1e42736501efac3613894400b6ff7a40e28c1d684ec93a2
  • Pointer size: 131 Bytes
  • Size of remote file: 224 kB
examples/7.png ADDED

Git LFS Details

  • SHA256: 3e218338198762035f64258e96cd9670975e6359b7365b3f0c74fefa6d92ebe2
  • Pointer size: 131 Bytes
  • Size of remote file: 280 kB
main.py ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn.functional as F
3
+ import gradio as gr
4
+ from PIL import Image
5
+ from torchvision import transforms
6
+ from cnn import CNN
7
+
8
+ device = torch.device(
9
+ "cuda"
10
+ if torch.cuda.is_available()
11
+ else "mps"
12
+ if torch.backends.mps.is_available()
13
+ else "cpu"
14
+ )
15
+
16
+ classes = [
17
+ "airplane",
18
+ "automobile",
19
+ "bird",
20
+ "cat",
21
+ "deer",
22
+ "dog",
23
+ "frog",
24
+ "horse",
25
+ "ship",
26
+ "truck",
27
+ ]
28
+
29
+ model = CNN()
30
+ model.load_state_dict(torch.load("cnn/model.pt", map_location=device))
31
+ model.to(device)
32
+ model.eval()
33
+
34
+ transform = transforms.Compose(
35
+ [
36
+ transforms.Resize((32, 32)),
37
+ transforms.ToTensor(),
38
+ transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),
39
+ ]
40
+ )
41
+
42
+
43
+ def predict(image):
44
+ if image is None:
45
+ return {}
46
+
47
+ image = Image.fromarray(image).convert("RGB")
48
+ image_tensor = transform(image)
49
+ image_tensor = (image_tensor).unsqueeze(0).to(device)
50
+
51
+ with torch.no_grad():
52
+ outputs = model(image_tensor)
53
+ probabilities = F.softmax(outputs, dim=1)[0]
54
+
55
+ return {classes[i]: float(probabilities[i]) for i in range(len(classes))}
56
+
57
+
58
+ demo = gr.Interface(
59
+ fn=predict,
60
+ inputs=gr.Image(type="numpy"),
61
+ outputs=gr.Label(num_top_classes=10),
62
+ title="CNN Classifier",
63
+ description="Upload an image to classify it into one of 10 CIFAR-10 categories: airplane, automobile, bird, cat, deer, dog, frog, horse, ship, truck",
64
+ examples=[
65
+ ["examples/1.png"],
66
+ ["examples/2.png"],
67
+ ["examples/3.png"],
68
+ ["examples/4.png"],
69
+ ["examples/5.png"],
70
+ ["examples/6.png"],
71
+ ["examples/7.png"],
72
+ ],
73
+ )
74
+
75
+ if __name__ == "__main__":
76
+ demo.launch(share=True, pwa=True)
pyproject.toml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
2
+ name = "cnn"
3
+ version = "0.1.0"
4
+ description = "Add your description here"
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ dependencies = []
8
+
9
+ [dependency-groups]
10
+ dev = [
11
+ "ipykernel>=6.29.5",
12
+ ]
requirements.txt ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ appnope==0.1.4
2
+ asttokens==3.0.0
3
+ comm==0.2.2
4
+ contourpy==1.3.2
5
+ cycler==0.12.1
6
+ debugpy==1.8.14
7
+ decorator==5.2.1
8
+ executing==2.2.0
9
+ filelock==3.18.0
10
+ fonttools==4.58.4
11
+ fsspec==2025.5.1
12
+ ipykernel==6.29.5
13
+ ipython==9.4.0
14
+ ipython-pygments-lexers==1.1.1
15
+ jedi==0.19.2
16
+ jinja2==3.1.6
17
+ jupyter-client==8.6.3
18
+ jupyter-core==5.8.1
19
+ kiwisolver==1.4.8
20
+ markupsafe==3.0.2
21
+ matplotlib==3.10.3
22
+ matplotlib-inline==0.1.7
23
+ mpmath==1.3.0
24
+ nest-asyncio==1.6.0
25
+ networkx==3.5
26
+ numpy==2.3.1
27
+ packaging==25.0
28
+ parso==0.8.4
29
+ pexpect==4.9.0
30
+ pillow==11.3.0
31
+ pip==25.1.1
32
+ platformdirs==4.3.8
33
+ prompt-toolkit==3.0.51
34
+ psutil==7.0.0
35
+ ptyprocess==0.7.0
36
+ pure-eval==0.2.3
37
+ pygments==2.19.2
38
+ pyparsing==3.2.3
39
+ python-dateutil==2.9.0.post0
40
+ pyzmq==27.0.0
41
+ setuptools==80.9.0
42
+ six==1.17.0
43
+ stack-data==0.6.3
44
+ sympy==1.14.0
45
+ tabulate==0.9.0
46
+ torch==2.7.1
47
+ torchvision==0.22.1
48
+ tornado==6.5.1
49
+ traitlets==5.14.3
50
+ typing-extensions==4.14.0
51
+ wcwidth==0.2.13
52
+ gradio
testbench.ipynb ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 42,
6
+ "id": "c831c34c",
7
+ "metadata": {},
8
+ "outputs": [
9
+ {
10
+ "name": "stdout",
11
+ "output_type": "stream",
12
+ "text": [
13
+ "Using mps\n",
14
+ "Using 4 threads\n"
15
+ ]
16
+ }
17
+ ],
18
+ "source": [
19
+ "import matplotlib.pyplot as plt\n",
20
+ "import torch\n",
21
+ "from torch.utils.data import DataLoader\n",
22
+ "from torchvision import datasets, transforms\n",
23
+ "from cnn import CNN\n",
24
+ "\n",
25
+ "model = CNN()\n",
26
+ "model.load_state_dict(torch.load(\"cnn/model.pt\"))\n",
27
+ "\n",
28
+ "check_gpu = torch.cuda.is_available()\n",
29
+ "device = torch.device(\"cpu\")\n",
30
+ "\n",
31
+ "if check_gpu:\n",
32
+ " device = torch.device(\"cuda\")\n",
33
+ "elif torch.backends.mps.is_available():\n",
34
+ " device = torch.device(\"mps\")\n",
35
+ "\n",
36
+ "model.to(device)\n",
37
+ "\n",
38
+ "print(f\"Using {device}\")\n",
39
+ "print(f\"Using {torch.get_num_threads()} threads\")\n"
40
+ ]
41
+ },
42
+ {
43
+ "cell_type": "code",
44
+ "execution_count": 43,
45
+ "id": "cd2d6928",
46
+ "metadata": {},
47
+ "outputs": [],
48
+ "source": [
49
+ "test_transforms = transforms.Compose(\n",
50
+ " [\n",
51
+ " transforms.Resize((32, 32)),\n",
52
+ " transforms.ToTensor(),\n",
53
+ " transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),\n",
54
+ " ]\n",
55
+ ")\n"
56
+ ]
57
+ },
58
+ {
59
+ "cell_type": "code",
60
+ "execution_count": 44,
61
+ "id": "f7bb207f",
62
+ "metadata": {},
63
+ "outputs": [],
64
+ "source": [
65
+ "num_workers = 0\n",
66
+ "batch_size = 64\n",
67
+ "\n",
68
+ "test_dataset = datasets.CIFAR10(\n",
69
+ " root=\"./cifar\", train=False, download=True, transform=test_transforms\n",
70
+ ")\n"
71
+ ]
72
+ },
73
+ {
74
+ "cell_type": "code",
75
+ "execution_count": 45,
76
+ "id": "9ca78681",
77
+ "metadata": {},
78
+ "outputs": [],
79
+ "source": [
80
+ "test_loader = DataLoader(test_dataset, batch_size=batch_size, num_workers=num_workers)\n"
81
+ ]
82
+ },
83
+ {
84
+ "cell_type": "code",
85
+ "execution_count": 46,
86
+ "id": "9c5c7fae",
87
+ "metadata": {},
88
+ "outputs": [
89
+ {
90
+ "name": "stdout",
91
+ "output_type": "stream",
92
+ "text": [
93
+ "Accuracy of airplane : 84.60 %\n",
94
+ "Accuracy of automobile : 93.20 %\n",
95
+ "Accuracy of bird : 76.90 %\n",
96
+ "Accuracy of cat : 69.70 %\n",
97
+ "Accuracy of deer : 77.20 %\n",
98
+ "Accuracy of dog : 64.00 %\n",
99
+ "Accuracy of frog : 89.30 %\n",
100
+ "Accuracy of horse : 82.10 %\n",
101
+ "Accuracy of ship : 89.60 %\n",
102
+ "Accuracy of truck : 87.90 %\n",
103
+ "\n",
104
+ "Overall Test Accuracy: 81.45%\n"
105
+ ]
106
+ }
107
+ ],
108
+ "source": [
109
+ "classes = ('airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')\n",
110
+ "\n",
111
+ "class_correct = list(0. for i in range(10))\n",
112
+ "class_total = list(0. for i in range(10))\n",
113
+ "\n",
114
+ "model.eval()\n",
115
+ "\n",
116
+ "with torch.no_grad():\n",
117
+ " for data, target in test_loader:\n",
118
+ " data, target = data.to(device), target.to(device)\n",
119
+ " output = model(data)\n",
120
+ " _, predicted = torch.max(output.data, 1)\n",
121
+ " \n",
122
+ " c = (predicted == target).squeeze()\n",
123
+ " for i in range(len(target)):\n",
124
+ " label = target[i]\n",
125
+ " class_correct[label] += c[i].item()\n",
126
+ " class_total[label] += 1\n",
127
+ "\n",
128
+ "class_accuracies = []\n",
129
+ "for i in range(10):\n",
130
+ " accuracy = 100 * class_correct[i] / class_total[i] if class_total[i] > 0 else 0\n",
131
+ " class_accuracies.append(accuracy)\n",
132
+ " print(f'Accuracy of {classes[i]:10s} : {accuracy:.2f} %')\n",
133
+ "\n",
134
+ "overall_accuracy = 100 * sum(class_correct) / sum(class_total)\n",
135
+ "print(f'\\nOverall Test Accuracy: {overall_accuracy:.2f}%')\n"
136
+ ]
137
+ },
138
+ {
139
+ "cell_type": "code",
140
+ "execution_count": 47,
141
+ "id": "1e171b86",
142
+ "metadata": {},
143
+ "outputs": [
144
+ {
145
+ "data": {
146
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAABb4AAAJyCAYAAAALltY5AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAAieFJREFUeJzs3Qm4XPP9P/DvzUII2UnELpbYEn6E2tdK7bFUqdqK2P3spb/ad2qpvdReS6na2qL2UiRCCErEGkJCyEKIbPf/fL79z3Tuzb1xE3eZTF6v55nn3jlz7plz5px75sz7fOZzqqqrq6sTAAAAAABUiFYtPQMAAAAAANCYBN8AAAAAAFQUwTcAAAAAABVF8A0AAAAAQEURfAMAAAAAUFEE3wAAAAAAVBTBNwAAAAAAFUXwDQAAAABARRF8AwAAAABQUQTfAACUnZEjR6bTTz89bb755qlnz56pXbt2+bbEEkuk/v37p/PPPz+PU2rfffdNVVVVNW5/+tOfZpr2Bx98UGOcZZZZZpaPx2211VZLM2bMmGlatZ/zpptumuNlnjp1alp00UVneu4rrrhijqcJAADzKsE3AABl47vvvkv/+7//m3r16pVOO+209OSTT6ZPP/00D4/bqFGj0j/+8Y904oknpjXWWON7p3fyySenadOm/eD5euONN9If//jH1JT++te/ps8//3ym4T8kTAcAgHmV4BsAgLIwefLktOWWW6bLLrusRli98MILp8022yxtv/32ad11182V36GuCuzaRowYkW688cZGmb9TTz01TZkyJTWV+gLul156Kb3++utN9rwAAFCJBN8AAJSFww8/PD377LPF+9HmI8Lmzz77LD3xxBPpgQceSC+88EL68ssv0/XXX5+WWmqpBk03WqZEqP5DRQuU3//+96kpRKX3Qw89VLzftm3bGo+r+gYAgNkj+AYAoMVFRXPtyuwIrKPdSaHCu2CBBRZIv/zlL9OLL77YoGlHe5TG6pN99tlnp0mTJqXGFm1Uosd3wQknnJAWXHDB4v3bbrvte1u2vPzyy+mQQw5Jq6++eurUqVOab775Uo8ePdL666+f/u///i99/fXXdb42cXJhgw02SN26dcuBe9euXVOfPn3SoYcemoYPH14jfC/tPR7rprZZ9U6v6+/ff//93Cd98cUXT23atMm/hy+++CKdeeaZaZdddkmrrrpqXo75558/vyZxwmOHHXbIr8msqv7jBMmFF16Y+8R37949vx7xuqy88sp5+xk8eHAe75xzzqkxX9ddd91M04p1E69PYZzoO98YLXQAAGg6bZpw2gAA0CBxEcrSEHORRRbJ4e+sRBA6K5tsskl6+umn8+/nnXdeGjhwYOrQocNsz1uEshG2v/POO2nMmDHp0ksvzUFyY6pd0X3AAQfk5ytcnHP06NHp4YcfTtttt91MfxuvW/RFryvcj/mN2/PPP58OPPDAtNBCC9V4zsMOOyx98803MwXGcXvttdfSOuusk1ZaaaXUFIYOHZouueSSNHHixJkei0D8lFNOqfPvPvroo3x78MEH06233pp/1q6Qj+r5vffeO40dO7bG8AkTJuTbW2+9lQP0WL44WRDhd+GExpVXXplfq9rTizC+YP/9989BPQAA5UvFNwAALe5f//pXjftbbLHF9wbb32evvfZKq6yySv49Qsuo/p0TEXCeccYZxfsxnQiGG0tUag8bNqx4f7311svV0nvssUeD2p0ce+yxM4XeUSEd/dK32mqrXKlc23333ZernktD7+ilHpXfEa7HxUWbWrSuidB7iSWWSFtvvXUOoVu3bj3TckRf95/85Ce5yjuq1+MkRMEjjzySg+pSUcm900471Qi941sDMf3oEx8V5KU6d+6cTzQUvPrqqzVa7oTSC5u2atVqpmAcAIDyI/gGAKDFRVVyqdptMuZEhKhnnXVW8X5Uake/8Dmx++67pzXWWCP/HhXDUUHeWGoH2j//+c/zzwiDozVHQVQ21w7coyr88ssvn6lFTFREP/roozkYjmrxP//5zznYDtXV1enoo4/OPwt23HHH3MM8At94nphuBMi1Q+LG9qtf/Sp9+OGH6e9//3saNGhQuuqqq/LwFVZYIb399tvp008/zX3do+L6/vvvzydIohq8ffv2xWnceeedNaZ5/PHHp++++654P8LymFZMP8L2aKvz5ptvpo033rg4TrwepRXcpScSIpyP16Rgm222aXB/eQAAWo7gGwCAslMayv4QUfkblb4helxHj+45EX2dS/82gtFPPvnkB8/flClT0u23314jrP/pT3+af4+e1NHjur5xQ4TB06dPL97fdNNNc4uQ0hA3phnTid7dhQrzCLkLOnbsmG6++ebUpUuXGtPu169fvjWVFVdcMb+mUUFdUKjyj3mK5T3yyCPTmmuumauyo51JrIeoAi/tsx5tSwqiyvuZZ54p3o/xo1p7ySWXrPHcvXv3zr2/C5Zeeuni6x7+8pe/5NA93HPPPTUujnrwwQc34qsAAEBTEXwDANDi4uKDpUqD2R/q3HPPLf5+zTXX5ArjORGVvhtttFH+/dtvv63R/mRORSVxae/owoUYC76v3cl77703U1/z71P7b6KSPYLm5havZe3WJgV33XVXnq+oZn/llVfS+PHj672YZFTgF0Q1eOlJk6jMXnbZZRs0P1EpXnoxy2uvvXamNicRkEclPgAA5U/wDQBAi4ve0qUef/zxGu0qfogIk3/84x/n36OK+NRTT53jaZW2OLn++utzS5AfonaQHW09oud14RYXaCz10ksv5VYd5aB2EF27Xc336dmzZ53DYx3FBSdLpx8XO+3fv3+uXI/bggsumBpbVJZHb/mCCL7jJMlTTz1VHBa9vUsr1AEAKF+O2gAAaHE/+9nPagSK0bLiggsumOXfzE4wfs455+S2F+Hpp5+e4/mMftFx8ccQwWzti3LOjgiKH3744RrDvvrqqzRq1Kjira52KqVh+XLLLVfjsYYsW+2/iYrq0qrp+kTrlVKlleqhtMVIQ9QXIL/xxhs1eplH5Xf0LI/XKnqV1+7pXbs3fGE9h5EjR+Yq8IYqrfqO1z76rc+YMSPfj1Yr+++/f4OnBQBAyxJ8AwDQ4lZbbbW077771hgWldlxocbS/sqFNiNRbT07/afXXnvtGv2yf4gI0Ruj6jdaaNTXvmNWbrvttuLf7bDDDjXmJaqTowVL6XSj9Uf0Ao+TCeF//ud/alycMULvffbZZ6YLZ0Yg/uKLL9Zbof3Xv/41ffzxx/n3ESNGpBNPPDE1hmgzUjtwj9A5RAh90kknpW+++abOv43K8NJvD8Sy/+IXv8jBeal33303PfHEEzP9fVSVr7766sX7zz33XPH3AQMG5P7iAADMHQTfAACUhbhg5IYbblgjtDzttNPSoosumltQ7Ljjjmm99dbLF2E84IADcjXv7DjrrLPq7Sk9OyIYjUrgH6p2m5Po9x3LXNetT58+xfFGjx5drBRfYYUV0mGHHTbTCYMItrfaaqv0k5/8JAfWEdrGxT1DVERfdNFFNf4mgvGolo6+2xGmx8Ufo/VHVF8XxEVCO3ToULwfoXdUj0ff65VWWimHyY11EmShhRYq3h88eHC+EGZU2i+//PLpt7/9bY2q7trimwKl1ekRXsff/+hHP8rLFhXk8br985//rPPvjzvuuDqHu6glAMDcRfANAEBZWGCBBdJjjz2WjjjiiBoBdbT/iOrcBx54IPfALlSAz27VdYSztavK51RUVReqkOfEkCFDavTq7ty5c642nlUrmPpC80suuWSmUPbTTz9Njz76aHrkkUdyUF7brrvumq677rr8mpe+zs8++2wO4IcPHz7T30Rf7ajAr12dHScgIpw/8sgjU2OI54mq+lIRqv/tb3/LbUsOP/zwGhXrtcXJkXvuuSefICmIbWbQoEF52V599dUaF8CsLS4oGv3VS0VwHr3iAQCYewi+AQAoG/PPP3+67LLLctAZlcubbLJJbi8Rw6OKd/HFF88Xqjz33HNzK47ZFRXk7dq1+8Hzueyyy6aBAwc2WrX3zjvvPMsgvXbwHQFuoTVJnCS4+uqrc2X0QQcdlFZdddW08MIL5+l17949VzpHe5Bu3brVmEZUzUfA/Zvf/CaPE0FxmzZtcggfVdcRpkeIXOqoo45Kt956a1prrbXy6xjPE+vo3nvvTb/73e9SY4mTH9HPO+YrwvmoAI+K8xtvvDFdfvnl3/v3UR0eyxYXI435i2WP16Njx47FEyDbbLNNnX8b49UO8eN1BQBg7lJVPatyBwAAgHlMXOQyWqqECN6jrUtpBTkAAOWvTUvPAAAAQEv705/+lD788MP09ttv58rygqjsF3oDAMx9VHwDAADzvE033TQ9/fTTNYbFRTBffPHF3CIFAIC5ix7fAAAA/1/0TF966aXzRTTjYp9CbwCAuVOLBt///Oc/0/bbb5969uyZqqqq0n333Vfj8ShGP+WUU9Jiiy2We+ttueWWacSIETXGiYv67LnnnqlDhw6pU6dOaf/9909ff/11My8JAAAwN3vqqafy549p06alDz74IF9Ec9FFF23p2QIAYG4MvidNmpT69u2brrzyyjofv+CCC9Jll12WrrnmmjRo0KDUvn371L9//zR58uTiOBF6v/HGG+nRRx9Nf/3rX3OYHn34AAAAAACYN5VNj++o+L733nvTgAED8v2YragEP/bYY9Nxxx2Xh02YMCF179493XTTTWn33XdPb775ZlpllVVy37211147j/Pwww+nbbbZJl95Pf4eAAAAAIB5S5tUpt5///00evTo3N6kIPrrrbvuuun555/PwXf8jPYmhdA7xPitWrXKFeI77bRTndP+7rvv8q1gxowZuWVK165dcwAPAAAAAED5iYLpr776Khc9Rw481wXfEXqHqPAuFfcLj8XP2n332rRpk7p06VIcpy7nnntuOv3005tkvgEAAAAAaFofffRRWmKJJea+4LspnXTSSemYY44p3o8WKksttVSuMo+LZIY4WxC3qAaPW0Fh+PTp0/PZhe8bHleFjyryuEhOqRgeYvyGDI9AP6ZbOjymG+PXnsf6hlsmy2SZLJNlskyWyTJZJstkmSyTZbJMlskyWSbLZJksU+u5eJm+/vrrtPTSS6eFF144zUrZBt89evTIP8eMGZMWW2yx4vC4v8YaaxTH+eyzz2r8XaysaFtS+Pu6zD///PlWW1SKF4JvAAAAAADKS4Tt4ftaVtffBKWFLbvssjm8fvzxx4vDJk6cmHt3r7feevl+/Bw/fnx66aWXiuM88cQT+cxA9AIHAAAAAGDe06IV31GW/s477xTvR6uRV155JVdeR+uRo446Kp111llphRVWyEH4ySefnJuWDxgwII+/8sorp5/85CfpwAMPTNdcc02aOnVqOvzww/OFL2M8AAAAAADmPS0afA8ZMiRtttlmxfuFvtv77LNPuummm9IJJ5yQJk2alAYOHJgruzfccMP08MMPp3bt2hX/5rbbbsth9xZbbJF7vuyyyy7psssua5HlAQAAAACg5VVVl3YGn0dFC5WOHTvmi1zq8Q0AAAAAMHdnuWXb4xsAAAAAAOaE4BsAAAAAgIoi+AYAAAAAoKIIvgEAAAAAqCiCbwAAAAAAKorgGwAAAACAiiL4BgAAAACgogi+AQAAAACoKIJvAAAAAAAqiuAbAAAAAICKIvgGAAAAAKCiCL4BAAAAAKgogm+g2X311VfpqKOOSksvvXRaYIEF0vrrr59efPHF4uOnnXZa6t27d2rfvn3q3Llz2nLLLdOgQYNmOc1zzz039evXLy288MJp0UUXTQMGDEjDhw+vMc7kyZPTYYcdlrp27ZoWWmihtMsuu6QxY8YUH//yyy/T9ttvnx9bc80109ChQ2v8ffztRRdd1GivAwAAAABNQ/ANNLsDDjggPfroo+nWW29Nr732Wtpqq61yuD1q1Kj8+IorrpiuuOKK/Nizzz6blllmmTzO559/Xu80n3766RxMv/DCC3naU6dOzX8zadKk4jhHH310evDBB9Pdd9+dx//kk0/SzjvvXHz87LPPzqH8yy+/nDbddNN04IEHFh+L6Ub4HoE9AAAAAOWtqrq6ujrN4yZOnJg6duyYJkyYkDp06NDSswMV7dtvv81V2ffff3/adttti8PXWmuttPXWW6ezzjqr3v/Rxx57LG2xxRYNep4IyaPyOwLujTfeOP9/L7LIIun2229Pu+66ax7nrbfeSiuvvHJ6/vnn049+9KO0zTbbpB122CEdfPDB6c0330xrr712Ds4jRI9q8j/84Q95GAAAAADlneWq+Aaa1bRp09L06dNTu3btagyPlidR3V3blClT0rXXXpt3aH379m3w88TOL3Tp0iX/fOmll3KAHZXlBdFOZamllsrBd4jpP/HEE3keH3nkkdSnT588/IILLsgV4EJvAAAAgLmD4BtoVlHtvd5666UzzzwztxqJEPyPf/xjDp8//fTT4nh//etfc6/tCMgvueSS3L6kW7duDXqOGTNm5JYkG2ywQVpttdXysNGjR6f55psvderUqca43bt3z4+FE088MbVp0yb16tUr3Xvvven6669PI0aMSDfffHM6+eSTcyX4csstl3bbbbdisA4AAABA+RF8A80uentHl6XFF188zT///Omyyy5Le+yxR2rV6r+7pM022yy98sor6bnnnks/+clPctj82WefNWj60ev79ddfT3feeedszVdUlUcrlA8//DC3SFlllVXSQQcdlC688MJ02223pffeey9fMHPBBRdMZ5xxxmwvNwAAAADNQ/ANNLuoqI5g+euvv04fffRRGjx4cG5DEtXUBe3bt0/LL7987r0dlddRiR0/v8/hhx+eq8WffPLJtMQSSxSH9+jRI7dNGT9+fI3xx4wZkx+ry4033pgrxHfcccf01FNPpQEDBqS2bdumn/70p/k+AAAAAOVJ8A20mAi3F1tssTRu3LjcUzsC5lm1L/nuu+/qfTwqyCP0jhYl0ad72WWXrfF4XDwzQuvHH3+8OCyqt0eOHJlbr9R1ccyo6r788svz/WjJEuF8iJ9xHwAAAIDy1KalZwCY90TIHUH1SiutlN555510/PHH5wtN7rfffmnSpEnp7LPPTjvssEMOxceOHZuuvPLKNGrUqFxpXbDFFluknXbaKYfdhfYm0abk/vvvz33EC327o31JXDgzfu6///7pmGOOyRe8jKv+HnHEETn0jqry2qJH+LHHHpvbsYToFx4tWrbaaqt8sc24DwAAAEB5EnwDzS4uDHnSSSeljz/+OIfQu+yySw67oyI7KqnfeuutfEHJCL27du2a+vXrl5555pm06qqrFqfx7rvv5scLrr766vxz0003naldyb777pt/j4tkRh/xeL6oHu/fv3+66qqr6gzmI5CPoLsgAvYhQ4akddddN62zzjrp1FNPbZLXBgAAAIAfrqo6yi7ncRMnTszVoBHGRRUoAAAAAABzb5arxzcAAAAAABVF8A0AAAAAQEURfAMAAAAAUFEE3wAAAAAAVBTBNwAAAAAAFUXwDQAAAABARWnT0jMAtLzzho5t6VlgFk5cs1tLzwIAAADAXEXFNwAAAAAAFUXwDQAAAECLmT59ejr55JPTsssumxZYYIHUq1evdOaZZ6bq6uriOGPGjEn77rtv6tmzZ1pwwQXTT37ykzRixIjvnfb48ePTYYcdlhZbbLE0//zzpxVXXDH9/e9/rzHOlVdemZZZZpnUrl27tO6666bBgwfXePyYY45JXbp0SUsuuWS67bbbajx29913p+233/4HvwZA49PqBAAAAIAWc/7556err7463XzzzWnVVVdNQ4YMSfvtt1/q2LFjOvLII3MAPmDAgNS2bdt0//33pw4dOqSLL744bbnllunf//53at++fZ3TnTJlSvrxj3+cFl100fTnP/85Lb744unDDz9MnTp1Ko7zpz/9KQfb11xzTQ69L7300tS/f/80fPjw/HcPPvhguv3229M//vGPHLT/8pe/zI9369YtTZgwIf3f//1feuyxx5rx1QIaSsU3AAAAFVXl+Ze//CWtvfbaOdyKQGyNNdZIt956a41x4jlOOeWUXAUazx0BWul0v/vuu7TXXnvlgC0qRGsHWxdeeGE64ogjGu21gHnZc889l3bccce07bbb5srrXXfdNW211VbFyuv433zhhRdyON6vX7+00kor5d+//fbbdMcdd9Q73RtuuCF9+eWX6b777ksbbLBBnvYmm2yS+vbtWxwnAvQDDzwwB+2rrLJKDsBjXxN/G95888206aab5n3KHnvskfcJ77//fn7shBNOSIccckhaaqmlmvw1Amaf4BsAAIAWrfK84oorcrgU9y+44IJ0+eWX58cLVZ7vvfdervIc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RNAdVaAFUZkaLRc22mijtNJKK+Ue5QDMueeeey5/kyeq58MyyyyTK/oHDx5cHKd2K6poebPZZpvVG3p/++23+SRpjBcXIQ2nnXZaPmkZQfZZZ52Vq70vvfTSfMHiwjeJbrnlllzxH9dyiFZc0QJnhx12yIF8PFec+Bw7dmw+KRutcSI4F3qXJxXfKr5BxXeZU/ENAABApVd8X3vttekf//hHbicSFw+O/u1RBb7nnnvONH6cDF1iiSVylfbPf/7zetucRM4X3yzaYostisPjRGebNm2KPePj20HxjaNodVOwySab5Pu/+93v8reSbr311vToo4/m1jlxYnXUqFH5pGdUgUdATvNS8Q0AAAAAlL1oRxVhZnxDp3AthWhzUlfoHSLwXnjhhdPOO+9c7zTj8bhuQ/QKj97xUcUdVeTPP/98vvhxafuU2j3d437hsWi/Fa2w4uKl3bp1y98CGjduXP52UoTnUS1+55135gD9hhtuKLZQoeW5uCUAAAAA0GIiTL7ttttyFfXLL7+cg+24rkL8rEsEzBGK125PVVtUakeziwij559//nxdhj322GOmCyvPStu2bdOVV16Z+3nHhTGjYjwuahq9x6NSPCq+o0L9Rz/6UbEfOeVB8A0AAAAAtJjomx1V39FTe/XVV0977bVXOvroo4sXLS71zDPPpOHDhxcvVjwrUYX99NNPp6+//jp99NFHuWf41KlTi33BC33Do3VKqbhfu6d4wZNPPpneeOONdPjhh+eK72222Sa1b98+7bbbbvk+5UPwDQAAAAC0mG+++WamKuxoeTJjxoyZxr3++uvTWmutlfr27dvg6UcwHRdIjhYl0ae7cCHLZZddNgfcjz/+eHHcaLkyaNCg3CaltsmTJ6fDDjss9/0utGSJID3Ez7hP+RB8AwAAAAAtZvvtt889vf/2t7+lDz74IN177735wpY77bRTjfEilI4LStZX7R0XsbziiiuK9yPkfvjhh3Obkrg45WabbZb7iO+333758aqqqnTUUUels846Kz3wwAPptddeS3vvvXfq2bNnGjBgwEzTj37hUeG95ppr5vsbbLBB+stf/pJ7gMfzxn3Kh4tbAgAAAFDDeUPHtvQsMAsnrtktVZLLL788nXzyyenQQw9Nn332WQ6eDzrooHwByVJxEcno2R19uuvy7rvvprFj/7vtTpgwIZ100knp448/Tl26dEm77LJLDtijb3fBCSeckCZNmpQGDhyYxo8fn3t4R1heu3/466+/nnuRv/LKK8Vhu+66a25vstFGG6WVVlop9yinfFRVx9Yyj4uzRR07dsz/DB06dGjp2YFm54CmvFXaAQ0AUN4cG5Y3x4Y0F/uC8mZfwLxsYgOzXK1OAAAAAACoKIJvAAAAAAAqiuAbAAAAAICKIvgGAAAAAKCiCL4BAAAAAKgogm8AAAAAACqK4BsAAAAAgIrSpqVngHnH9OnT02mnnZb++Mc/ptGjR6eePXumfffdN/3mN79JVVVVM41/8MEHp9///vfpkksuSUcdddQspz1q1Kj0q1/9Kj300EPpm2++Scsvv3y68cYb09prr50fr66uTqeeemq67rrr0vjx49MGG2yQrr766rTCCivkx7/77rt0wAEHpPvvvz/16NEjXXXVVWnLLbcsTv/CCy9MI0eOTJdffnmjvy4AAAAA5ei8oWNbehaox4lrdmvpWSh7gm+azfnnn5/D5ptvvjmtuuqqaciQIWm//fZLHTt2TEceeWSNce+99970wgsv5HD8+4wbNy4H2ZtttlkOvhdZZJE0YsSI1Llz5+I4F1xwQbrsssvycy+77LLp5JNPTv3790///ve/U7t27dK1116bXnrppfT888/nafz85z9PY8aMyYH8+++/nwPzmF8AAAAAoPwJvmk2zz33XNpxxx3Ttttum+8vs8wy6Y477kiDBw+eqXr7iCOOSI888khx3O8L1Jdccslc4V0Q4XZBVHtfeumlubI8nj/ccsstqXv37um+++5Lu+++e3rzzTfTDjvskAP55ZZbLh1//PFp7NixOUQ/5JBD8nN06NChEV8NAAAAAKCp6PFNs1l//fXT448/nt5+++18/9VXX03PPvts2nrrrYvjzJgxI+211145eI4QuiEeeOCB3NLkpz/9aVp00UXTmmuumSu0C6JiO1qrlLYuiSrzddddN1d4h759++Z5+fbbb3Pgvthii6Vu3bql2267LVeE77TTTo34SgAAAAAATUnFN83mxBNPTBMnTky9e/dOrVu3zj2/zz777LTnnnsWx4nK6jZt2szU+mRW3nvvvdxC5Zhjjkm//vWv04svvpj/fr755kv77LNPDr1DVHiXivuFx375y1+mYcOGpVVWWSUH3nfddVduoXLKKaekp556KleL33nnnalXr17phhtuSIsvvnijvS4AAAAAQOMSfNNsIkyOCurbb789V3O/8sor+aKV0cc7Aurosf273/0uvfzyy3Ve7LI+USUeFd/nnHNOvh8V36+//nq65ppr8nQbom3btunKK6+sMSz6j0eAPnTo0NwSJSrUo1d4DLvnnntmc+kBAAAAgOai1QnNJtqXRNV39NReffXVc0uTo48+Op177rn58WeeeSZ99tlnaamllspV33H78MMP07HHHpv7gdcn2pJEpXaplVdeOY0cOTL/3qNHj/wzLlZZKu4XHqvtySefTG+88UY6/PDDc8X3Nttsk9q3b5922223fB8AAAAAKF+Cb5rNN998k1q1qrnJRcuTqNgOEYRHu5GoBC/coho8AvPou12fDTbYIA0fPrzGsOgjvvTSSxcvdBkBd/QXL4iWK4MGDUrrrbfeTNObPHlyOuyww9Lvf//7YkuWqVOn5sfiZ9wHAAAAAMqXVic0m+233z739I6K7mh1Ei1ELr744txfO3Tt2jXfarcgidB6pZVWKg7bYost8sUmoxo7RNV4XDgzWp1ERfbgwYPTtddem28h2qZES5WzzjorrbDCCjkIP/nkk3OoPmDAgJnm88wzz8wV3tEypRCsR/gerU+uuOKKfB8AAAAAKF+Cb5rN5ZdfngPnQw89NLc0ieD5oIMOyheQnB3vvvtuGjt2bPF+v3790r333ptOOumkdMYZZ+Rg+9JLL61x0cwTTjghTZo0KQ0cODCNHz8+bbjhhunhhx9O7dq1qzHt6A0evcij2rxg1113ze1NNtpooxzAR49yAAAAAKB8VVVXV1eneVy0vejYsWOaMGFC6tChQ0vPDjS784b+90QC5efENbu19CwAAPMQx4blzbEhzcW+oLw1177AdlC+5uX3g4kNzHL1+AYAAAAAoKIIvgEAAAAAqCiCbwAAAKBFTJ8+PV8LKq7VtMACC6RevXqlM888MxW6sk6dOjX96le/Squvvnpq3759vlbU3nvvnT755JNZTvef//xn2n777fP4VVVV6b777ptpnHiOuObUYostlp97yy23TCNGjCg+/t1336W99torf41+xRVXTI899liNv7/wwgvTEUcc0WivBQCNS/ANAAAAtIjzzz8/XX311emKK65Ib775Zr5/wQUXpMsvvzw//s0336SXX345h+Px8y9/+UsaPnx42mGHHWY53UmTJqW+ffumK6+8st5x4nkuu+yydM0116RBgwblYL1///5p8uTJ+fFrr702vfTSS+n5559PAwcOTD//+c+Lgfz777+frrvuunT22Wc36usBQONp04jTAgAAAGiw5557Lu24445p2223zfeXWWaZdMcdd6TBgwfn+3HxskcffbTG30RIvs4666SRI0empZZaqs7pbr311vlWnwiwL7300vSb3/wmP3+45ZZbUvfu3XN1+O67756D+AjYV1111bTccsul448/Po0dOzYtssgi6ZBDDskh/awuqgZAy1LxDQAAALSI9ddfPz3++OPp7bffzvdfffXV9Oyzz84ytJ4wYUJuX9KpU6c5ft6o2B49enRub1IQIfu6666bK7xDVIzHvHz77bfpkUceyS1RunXrlm677bbUrl27tNNOO83x8wPQ9FR8AwAAAC3ixBNPTBMnTky9e/dOrVu3zj2/o33InnvuWef40YYken7vscceP6jaOkLvEBXepeJ+4bFf/vKXadiwYWmVVVbJgfddd92Vxo0bl/uCP/XUU7la/M4778x9yW+44Ya0+OKLz/H8AND4BN+k84aObelZYBZOXLNbS88CAABAk4gwOSqob7/99txS5JVXXklHHXVUvijlPvvsU2PcuNDlbrvtltuURF/wpta2bduZeoTvt99+6cgjj0xDhw7NLVGiQj16hcewe+65p8nnCYCG0+oEAAAAaBHRNzuqvqOn9uqrr5722muvdPTRR6dzzz23ztD7ww8/zD2/f2hv7R49euSfY8aMqTE87hceq+3JJ59Mb7zxRjr88MNzxfc222yTL4gZ8xX3ASgvgm8AAACgRXzzzTepVaua0US0PJkxY8ZMofeIESPSY489lrp27fqDn3fZZZfNAXf0Fy+IliuDBg1K6623Xp0tVg477LD0+9//vtiSJearMH9xH4DyIvgGAAAAWsT222+fe3r/7W9/Sx988EG6995708UXX1y8cGSEyrvuumsaMmRIbokSAXP04I7blClTitPZYost0hVXXFG8//XXX+e2KXErXMwyfh85cmS+HxfHjJYqZ511VnrggQfSa6+9lvbee+/cYmXAgAEzzeeZZ56ZK7zXXHPNfH+DDTZIf/nLX3IP8HjeuA9AedHjGwAAAGgRl19+eTr55JPToYcemj777LMcPB900EH5ApJh1KhROZgOa6yxxkytRzbddNP8+7vvvpvGjv3v9asiKN9ss82K94855pj8M/qG33TTTfn3E044IU2aNCkNHDgwjR8/Pm244Ybp4YcfTu3atavxPK+//nruRV4I0UOE8dHeZKONNkorrbRS7lEOQHmpqo6rQszj4utMHTt2TBMmTPjBfcLmRi5uWd6a4+KWtoHy5gKnAEBzcmxY3hwb0lzsC8pbc+0LbAfla15+P5jYwCxXqxMAAAAAACqK4BsAAAAAgIoi+AYAAAAAoKIIvgEAAAAAqCiCbwAAAAAAKorgGwAAAACAiiL4BgAAAACgorRp6RkAAAAAyst5Q8e29CxQjxPX7NbSswAwV1DxDQAAAABARRF8AwAAAABQUQTfAAAAAABUFME3AAAAAAAVRfANAAAAAEBFEXwDAAAAAFBRBN8AAAAAAFSUsg6+p0+fnk4++eS07LLLpgUWWCD16tUrnXnmmam6uro4Tvx+yimnpMUWWyyPs+WWW6YRI0a06HwDAAAAANByyjr4Pv/889PVV1+drrjiivTmm2/m+xdccEG6/PLLi+PE/csuuyxdc801adCgQal9+/apf//+afLkyS067wAA1G+ZZZZJVVVVM90OO+yw9MEHH9T5WNzuvvvuOqc3derU9Ktf/Sqtvvrq+XiwZ8+eae+9906ffPJJjfG+/PLLtOeee6YOHTqkTp06pf333z99/fXXxcfjuTfeeOM8jfgZ90ttt9126Z577mmiVwUAAJgngu/nnnsu7bjjjmnbbbfNH4523XXXtNVWW6XBgwcXq70vvfTS9Jvf/CaP16dPn3TLLbfkDzj33XdfS88+ALMZdhU8//zzafPNN8/BU4RTET59++239U7zq6++SkcddVRaeuml87d/1l9//fTiiy/WGOf7viH03Xffpb322is/34orrpgee+yxGn9/4YUXpiOOOKJRXwuYl8X/6Kefflq8Pfroo3n4T3/607TkkkvWeCxup59+elpooYXS1ltvXef0vvnmm/Tyyy/nbwvGz7/85S9p+PDhaYcddqgxXoTeb7zxRn6+v/71r+mf//xnGjhwYPHxY489Ni2++OLplVdeyfuL4447rvjYn/70p9SqVau0yy67NNnrAgAANI42qYxFcHHttdemt99+O4cQr776anr22WfTxRdfnB9///330+jRo3N4UdCxY8e07rrr5tBk9913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6Te/+U3acccd87Bbbrklde/ePd13331p9913T2+++WbaYYcd8vMut9xy6fjjj09jx45NiyyySDrkkEPyvEc1OAAAAOVLxTcA0OweeOCBtPbaa+dAetFFF01rrrlmrqQubTcS2rVrVxzWqlWrNP/886dnn322wc9z/fXX5zA7qroLFdujR4/OleMFHTt2TOuuu26u8A59+/bNz/Htt9+mRx55JLdE6datW7rtttvy/Oy0006N8hoAAADQdATfAECzixYmUcG9wgor5HA5KqmPPPLIdPPNN+fHe/funZZaaql00kkn5bYoU6ZMyZXWH3/8cW5h0hCDBw/OFeOl1eEReoeo8C4V9wuP/fKXv8zh9yqrrJJbmtx11115HqIv+OWXX56rxZdffvncHiX6lAMAAFB+tDoBAJrdjBkzcsX3Oeeck+9HxXeE1NF3e5999sm9v6Nf9/7775/bl0Sf7qjS3nrrrYv9thtS7R0XzFxnnXVma97iua+88soaw/bbb78czEev8WiJ8uqrr+Ze4THsnnvuma3pAwAA0PRUfAMAzS7ah0RFdamVV145jRw5snh/rbXWSq+88koaP358rvJ++OGH0xdffJH7bn+fuABm9PeO4LxU9AgPY8aMqTE87hceq+3JJ59Mb7zxRjr88MPTU089lbbZZpvcOmW33XbL9wEAACg/gm8AoNltsMEGafjw4TWGvf3222nppZeeadzowR0XlowLXg4ZMqR4UcpZufvuu3Of8F/84hc1hscFNCPgfvzxx4vDJk6cmAYNGpTWW2+9maYzefLkdNhhh6Xf//73uep8+vTpaerUqfmx+Bn3AQAAKD+CbwCg2R199NHphRdeyK1O3nnnnXT77bena6+9NofMpeF1VFRHP/D7778//fjHP04DBgxIW221VXGcvffeO/cBr6vNSYzbtWvXGsOrqqrSUUcdlc4666x8gc3XXnstT6Nnz555/NrOPPPMXOEdrVgKgX20YBk2bFi64oor8n0AAADKjx7fAECz69evX7r33ntzaH3GGWfkSuxLL7007bnnnsVxor3JMccck9uQRGuUCKhPPvnkGtOJ1iitWtU8jx+V5M8++2z6xz/+Uedzn3DCCbkVysCBA3MblQ033DC3UWnXrl2N8aLneFzYMtqtFOy66645jN9oo43SSiutlAN7AAAAyo/gGwBoEdttt12+1ScuHBm3Wamrx3YE0rO6AGZUfUfYHrdZWW211XJ7lVIRsl911VX5BgAAQPnS6gQAAAAAgIoi+AYAAAAAoKIIvgEAAAAAqCiCbwAAAAAAKorgGwAAAACAiiL4BgAAAACgogi+AQAAAACoKG1aegYAgPJw3tCxLT0LzMKJa3Zr6VkAAACYa6j4BgAAAACgogi+AQAAAACoKIJvAAAAAAAqiuAbAAAAAICKIvgGAAAAAKCiCL4BAAAAAKgogm8AAAAAACqK4BsAAAAAgIoi+AYAAAAAoKIIvgEAAAAAqCiCbwAAAAAAKorgGwAAAACAiiL4BgAAWsyoUaPSL37xi9S1a9e0wAILpNVXXz0NGTKkznEPPvjgVFVVlS699NLvne6VV16ZlllmmdSuXbu07rrrpsGDB9d4fPLkyemwww7Lz7vQQgulXXbZJY0ZM6b4+Jdffpm23377/Niaa66Zhg4dWuPv428vuuiiOV5uAACaluAbAABoEePGjUsbbLBBatu2bXrooYfSv//97xwmd+7ceaZx77333vTCCy+knj17fu90//SnP6VjjjkmnXrqqenll19Offv2Tf3790+fffZZcZyjjz46Pfjgg+nuu+9OTz/9dPrkk0/SzjvvXHz87LPPTl999VX++0033TQdeOCBxcdiPgYNGpSOOuqoRnkdAABofIJvAACgRZx//vlpySWXTDfeeGNaZ5110rLLLpu22mqr1KtXr5mqwo844oh022235ZD8+1x88cU5qN5vv/3SKquskq655pq04IILphtuuCE/PmHChHT99dfn8TbffPO01lpr5Xl47rnncqgd3nzzzbT77runFVdcMQ0cODDfD1OnTs2V5zHN1q1bN8nrAgDADyf4BgAAWsQDDzyQ1l577fTTn/40LbroormlyHXXXVdjnBkzZqS99torHX/88WnVVVf93mlOmTIlvfTSS2nLLbcsDmvVqlW+//zzz+f78XgE2KXj9O7dOy211FLFcaJK/IknnkjTpk1LjzzySOrTp08efsEFF+QK8JhvAADKl+AbAABoEe+99166+uqr0worrJDD5UMOOSQdeeSR6eabb65RFd6mTZs8vCHGjh2bpk+fnrp3715jeNwfPXp0/j1+zjfffKlTp071jnPiiSfm543q82izEhXiI0aMyPN28skn56rv5ZZbLu222265ghwAgPLS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/GVDJg0AAAAAAM0ffO+9997p2GOPTauvvnqdj6+55pr5YpJxEcphw4aliy66qHHnEgAAAAAAGjP4vummmxo6vdSnT5908803N3h8AAAAAABokYtb1uXNN99MTzzxRP59s802S6usskpjzRcAAAAAADRv8H3rrbfmPt7Tp0/P91u3bp0vgrnPPvvM6SQBAAAAAOAHazWnf3jGGWekHXfcMT3wwAPpoYceSoccckg6/fTTf/gcAQAAAABAcwTfBx98cPr666+L9ydMmJB22GGHtN1226X+/funfffdN40fP/6HzAsAAAAAADRf8P3888+n3r17p/vvvz/f33bbbdN+++2XFllkkbT44ounfv365RAcAAAAAADmih7fL7/8cjr//PPTHnvskUPvc889Ny266KLp8ccfT9XV1ekXv/hFOvnkk5t2bgEAAAAAoLEqvuPilb/+9a/Tq6++msaOHZvWWWedtOKKK6YhQ4akl156KYfiCy20UEMnBwAAAAAA5XFxyxVWWCE9+eST6YILLkjHH3982nzzzdO7777bNHMHAAAAAABNFXx/9tlnaa+99kp9+vRJe++9d76w5b///e/UpUuXPCwqvmfMmDG7zw8AAAAAAC0TfA8cODDdeeed6Ysvvkh33HFHOuigg1KPHj3Sn//853T77benK664Iq299tqNO3cAAAAAANBUwXe0N3n99dfTqFGj0rBhw/L9gh133DG98cYbab311pvd5wcAAAAAgEbVpqEjdujQIf3pT39KG2ywQXr22WfTwgsvPNPjV155ZePOHQAAAAAANFXwfeihh6b/+7//S1VVVfn+OeecM7vPBQAAAAAA5RN8n3TSSbmH96uvvprWWGONtOWWWzbtnAEAAAAAQFMG3+HHP/5xvgEAAAAAwFx9ccv99tsvX9iyIeIilzE+AAAAAACUbcX3zTffnG655Za02mqrpe233z7169cvLbPMMvkCl19//XX68MMP05AhQ9KDDz6YW6GEG2+8sannHQAAAAAA5iz4vuaaa9JZZ52VXnvttVlWfldXV6cll1wy/eY3v2nIZAEAAAAAoGVanQwcODC999576Z577km77LJL6t69ew65C7dFF100D4/H33333XTggQc2/pwCAAAAAEBjXtyyTZs2aaeddsq3MGnSpDRhwoTUoUOHtNBCCzV0MgAAAAAAUB7Bd23t27fPNwAAAAAAmOtanQAAAAAAwNxC8A0AAAAAQEURfAMAAAAAUFEE3wAAAAAAzNvB91133ZWmTJnSNHMDAAAAAADNHXzvvvvuabHFFksHH3xweu65537o8wMAAAAAQMsG361bt07jxo1L1113Xdpoo43SiiuumM4666z04YcfNu6cAQAAAABAcwTfn332WbrxxhvTNttsk+abb770zjvvpFNPPTX16tUrbbrppunmm29OU6dOnZN5AQAAAACA5g++O3funPbZZ5/04IMPps8//zxdfvnlacEFF0wzZsxIzzzzTPrlL3+ZQ/AhQ4b88LkDAAAAAICmDr4L/vGPf6QDDjggHX/88embb77JwyIAX2mlldLHH3+cDjrooDmdNAAAAAAAzLE2s/sHp5xySm5nEuF2dXV1HrbKKqukQw45JO29995p4YUXzr2/Bw0aNOdzBQAAAAAAzRV8x4UsQ9u2bdPOO++cDj300Bx0l1p77bVzMA4AAAAAAGXf6mSppZZKZ599dvroo4/SHXfcMVPoHS655JL0/vvvN9Y8AgAAAABA01V8R6BdVVU1u38GAAAAAADlWfH9q1/9Kv3P//xPevXVV4vDhg0bloedcMIJjT1/AAAAAADQtMF3tDcZM2ZM6tu3b3FYnz590meffZYfAwAAAACAuSr4joC7c+fOMw3v1KlT+vzzzxtrvgAAAAAAoHmC7y5duqS33347DRo0qDhs8ODBafjw4XUG4gAAAAAAUNbB92abbZamTZuWNtlkk9S/f/9823jjjdOMGTPSFlts0TRzCQAAAAAADdQmzaYzzjgjPfTQQ2nChAnpsccey8Oqq6tztffpp58+u5MDAAAAAICWrfhefvnl05AhQ9K+++6bVl555Xzbb7/9cruTXr16Ne7cAQAAAABAU1d8hwi4b7jhhjn5UwAAAAAAKL/ge8qUKelf//pX+uSTT9L06dNrPLb33ns31rwBAAAAAEDTB98jRoxIW265Zfr4449neqyqqkrwDQAAAADA3BV8n3jiiemjjz5qmrkBAAAAAIDmvrjlM888k9q0aZMeffTRfH/NNddMd9xxR+rWrVtxGAAAAAAAzDXB9/jx49PKK6+ctthii9zapG3btulnP/tZ6tGjRzrnnHOaZi4BAAAAAKCpWp0svPDCacaMGfn3hRZaKL311ltp0KBBaeTIkendd9+d3ckBAAAAAEDLVnwvueSS6cMPP0zTp09Pq6++evrqq6/S+uuvn38utthijTt3AAAAAADQ1MH3Pvvsk9ucjBgxIv3f//1fbnVSXV2dWrVqlU477bTZnRwAAAAAALRsq5Ojjz4630Lv3r3Tm2++mYYOHZpWXXXVtNJKKzXu3AEAAAAAQFMG31OnTs1hd8eOHdNLL72UL2657LLL5hsAAAAAAMx1rU6irUn08o7+3hF6AwAAAADAXN/je999903Dhw9Pr7/+etPMEQAAAAAANGeP79GjR+ef/fr1S5tttlnq3r17sfo7fl5//fU/ZH4AAAAAAKB5g+8//vGPOeCurq5ODz/8cDH0jvuCbwAAAAAA5rrge+ONN9bfGwAAAACAygm+n3rqqaaZEwAAAAAAaImLWwIAAAAAQEVVfLdu3brex6IFyrRp037oPAEAAAAAQPMF33ERSwAAAAAAqJjg+8Ybb6xxf8KECenee+9Nzz77bDrrrLMac94AAAAAAKDpg+999tlnpmGHHXZY6tOnT3rllVdmfw4AAAAAAKDcLm4Zvb1btWqV/va3vzXG5AAAAAAAoPkqvjfffPMa96dPn57ef//9NGrUqNSzZ885nxMAAAAAAGiJ4Pupp57KFd51XeTy0EMPbYx5AgAAAACA5gu+99577xx8F8Tviy66aNpiiy3Sj3/84zmfEwAAAAAAaIng+6abbmqM5wUAAAAAgPK4uOWwYcPSAw88kD755JPisOjvHcPiMQAAAAAAmKsqvg888MAccH/88cfFYQsssED62c9+ltZYY430/PPPN/Y8AgAAAABA01V8v/nmm2mFFVZIXbt2LQ7r0qVLHvbGG2/M7uQAAAAAAKBlg+9p06al0aNH558FU6dOzcOmT5/euHMHAAAAAABNHXz37t07ffHFF2mPPfbIbU3i9otf/CKNHTs2PwYAAAAAAHNVj+8DDjggHX744ekvf/lLvhVUVVXl/t8AAAAAADBXVXwfeuih6bDDDsu/V1dX51uIYQcffHDjzyEAAAAAADRlxXe4/PLL03HHHZdefPHFfL9fv35p6aWXnpNJAQAAAABAywbf3333Xb4tvvjixbA7LnQ5ceLENP/88+cbAAAAAADMNa1OBgwYkLp06ZJGjBhRHPbOO++krl27pp122qmx5w8AAAAAAJo2+I72Jr169Uorr7xycVjv3r3TcsstV2x9AgAAAAAAc03w/dVXX6WpU6fONDyGxWMAAAAAADBXBd9LLrlk+vDDD9PFF1+cqqur87BLL700ffDBB2mJJZZoinkEAAAAAICm7fEdgffxxx+f2rdvnxZccMF07LHHpqqqqrTzzjvP7uQAAAAAAKBlg+/TTjstrbnmmjn8njx5cr7F7zHslFNOady5AwAAAACA2dRmdv9goYUWSi+88EK6884706BBg/KwddddN+2+++6pbdu2szs5AAAAAABo2eA7RMC911575VvBqFGj0s0335x+/etfN+b8AQAAAABA07Y6KRVtTm6//fa01VZbpWWWWUarEwAAAAAA5s6K7+eeey7ddNNN6e67704TJ07Mw6LPd1zgEgAAAAAA5orgu9DKJG7vvPNOMewOEXhfeumlaeedd266OQUAAAAAgMYMvpdeeukcdBfC7j59+uQe36eddlr65ptv0pFHHtnQSQEAAAAAQMv3+J4xY0b+2a9fv/TKK6/k27HHHpvatJmjbikAAAAAAFAeF7ccMmRI2nrrrdMJJ5yQhg0b1jRzBQAAAAAATR1833DDDWnjjTfOv3/66afpoosuSmuuuWaaMGFCHvbWW2/N6TwAAAAAAEDzB9/77rtvevLJJ9O7776bTjnllLTMMssU+32HVVddNa2yyiqpKZ133nn5QppHHXVUcdjkyZPTYYcdlrp27ZoWWmihtMsuu6QxY8Y06XwAAAAAAFBBrU4i8I4LWkYAHkH43nvvnRZccMEcgg8fPrxp5jKl9OKLL6bf//73+aKapY4++uj04IMPprvvvjs9/fTT6ZNPPkk777xzk80HAAAAAAAVFnyX2mSTTdJNN92URo8eXaMVSmP7+uuv05577pmuu+661Llz5+LwaLNy/fXXp4svvjhtvvnmaa211ko33nhjeu6559ILL7zQJPMCAAAAAEB5a9MYE2nfvn1uhRK3phCtTLbddtu05ZZbprPOOqs4/KWXXkpTp07Nwwt69+6dllpqqfT888+nH/3oR3VO77vvvsu3gokTJ+af06ZNy7fQqlWrfJsxY0a+FRSGT58+vUarl/qGt27dOrdnKUy3dHiI8RsyvE2bNnm6pcNjujF+7Xmsb3h9y5SqZ6RU1SpVxc+Sea+uahUTq3/4jJrzmIfH88f4DRneqnWebo3hVVX/Gb/e4TNSVY15qcrzXt/w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Z41mFi1sTj311Jla2TDvsA0QbAfYBrANEGwH2AYItgNsA9gG5k1V1dENHAAAAAAAKsRc3+MbAAAAAABKCb4BAAAAAKgogm8AAAAAACqK4JsW98EHH6Sqqqr0yiuv/OBp7bvvvmnAgAGNMl/Mm2666abUqVOnWY5z2mmn5YvoFtjumt6mm26ajjrqqHofX2aZZdKll14629OtvS6BytkvMG+xPcxb4jJVAwcOTF26dGm0zxGUL//fzI6GfDab088OzDsaM6eiZQm+aXFLLrlk+vTTT9Nqq63W0rNCmQbN5ea4445Ljz/+eEvPBiVefPHF/AEYGsIJD4C528MPP5yPIf/617/6HAHMNp8d5l5OhDG72sz2X0Aja926derRo8csKzqmT5+e2rSxuVIeFlpooXyjfCyyyCKzfHzq1Kmpbdu2zTY/wNxvypQpab755mvp2QDq8O6776bFFlssrb/++nU+7v+XWbF98H2fHZh7yY+oTcU3zVaVseGGG+bK3q5du6btttsuH7DW9RWSp556Kt9/6KGH0lprrZXmn3/+9OyzzxYr9H7/+9/nKvEFF1ww7bbbbmnChAlz9Lylz/2Xv/wlbbbZZnmaffv2Tc8//3yN6cTzb7TRRmmBBRbIz33kkUemSZMmNdnrNTeZ1WtcWJfjx48vjh/rOYbFax+P77fffnkdxrC4xXoO48aNS3vvvXfq3LlzXi9bb711GjFixEyV4lHps9JKK+Vxdt111/TNN9+km2++OX99Lf421lW88RV833QL7rvvvrTCCiukdu3apf79+6ePPvqowdWiM2bMSOeee25adtll8zYT29Sf//znRni1523Tpk1Lhx9+eOrYsWPq1q1bOvnkk/OBTV1fV4xt6eqrr0477LBDat++fTr77LPz8PPOOy917949Lbzwwmn//fdPkydPbrHl4YeJ/7MLLrggLb/88vl9Yqmlliqu51/96ldpxRVXzP/jyy23XN5W4uRHYd9x+umnp1dffbW434lhlLd4z419d5x0jLDroosuqvH4d999l7+Ns/jii+f/+XXXXTe/x8zOe3nsR84888z8PB06dFAJNhdvDw15r7/uuuuKx5M77bRTuvjii+e6b6DNy20MjjjiiDRy5Mi8D4//3agAjGOEqAKMY4Q4dgtPP/10WmeddfL7RGwrJ554Yj6eKPjqq6/Snnvumfcb8fgll1yimrCM3/dPOOGE3N4miqYKnxlCbAs77rhj3ifE/js+I44ZM2amY/c//OEP+fg8ju9DHJ+vvvrq+X0hPsdsueWWNd4XYvyVV145j9+7d+901VVXNfNSMyvft/5++9vf5v/reOywww4rHgvO6rNDvF/E9OL40ee38tz/x379d7/7XY3j+Lryo7pa3sS+PfbxDfk8UVtkCr/85S/zviD2Ocw9BN80i3gDOuaYY9KQIUNyi4hWrVrlDxmxo6lPHJhGSPXmm2+mPn365GHvvPNOuuuuu9KDDz6YA9ehQ4emQw899Ac/7//93//lD8wRykZYssceexQPiiPE/clPfpJ22WWXNGzYsPSnP/0p70jj4Jo5W7cFUaUTBxxxgBpfU41brIcQb1QxzQceeCCfiIiAc5tttqlxwBIh92WXXZbuvPPOvD1EyBHP/fe//z3fbr311nyipPSgpaHTjTe8W265Jf3rX//Kwf3uu+/e4NckQu/422uuuSa98cYb6eijj06/+MUv8ps0cy5OaMSZ+8GDB+eDnQgp4gNJfeJDTmwPr732Wj5IiX1HDDvnnHPyNhAHwj7AzL1OOumk/B4Rofa///3vdPvtt+eTGiFObMRBcAyPbSUCrggzws9+9rN07LHHplVXXbW434lhlLfjjz8+70Pvv//+9I9//CPv719++eXi4/GeHPv0eD+I9+qf/vSn+b27EHY29L08PiTHyco4vohti7lze/i+9/p4bz/44IPT//7v/+Zjvx//+Mf1ftCl/MR+/YwzzkhLLLFE3odHy4LCcUJU8cb6jWOwUaNG5fXer1+/fLIzQq3rr78+nXXWWcVpxTFsjB/byqOPPpqeeeaZGtsS5SPWb5ygGDRoUA6qYhuIdRafOSL0/vLLL/N+IYa99957M723x+fIe+65Jxc8xf99bDvxmS+OEePzZuxHdt5552JRxW233ZZOOeWUvG+Ix+P4Md4XYj5oed+3/p588sn83h8/Y53FceH3FTrE+o3jhNhfxAmx+PwX06a89v/rrbdeOvDAA4vH8XESu7786Id8nqhdYBHHlrHviPeJCMiZi1RDC/j888/jHan6tddeq37//ffz70OHDs2PPfnkk/n+fffdV+NvTj311OrWrVtXf/zxx8VhDz30UHWrVq2qP/3003x/n332qd5xxx0b9Lyh8Nx/+MMfiuO88cYb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wLx5EiT6f0eP12iRE1X/3bp1a+nZAgAagVYnAAAAAABUFBe3BAAAAACgogi+AQAAAACoKIJvAAAAAAAqiuAbAAAAAICKIvgGAAAAAKCiCL4BAGAus++++6aqqqq06aabtvSsAABAWRJ8AwBAmZk8eXK6+OKL07rrrps6dOiQFlxwwbTiiiumgw46KL333nstPXsAAFD22rT0DAAAAP81bty4tMUWW6ShQ4fm+wsvvHDq1atXGjlyZLr22mvTeuut19KzCAAAZU/FNwAAlJHDDz+8GHoff/zx6csvv0yvvfZamjBhQnr66afTSiutVOffnXjiiWnVVVdNnTp1Sm3btk09e/ZM++yzT/r000+L44wePTrtueeeabHFFkvzzz9/6tGjR9p8883T3//+9/z49OnT00knnZSWW2651K5du9SlS5e09tprpwsvvLCZlh4AABqH4BsAAMpEhNt33XVX/r1v377p/PPPT23a/PdLmhtvvHG9Fd8PP/xwGjVqVFpyySXT8ssvn0PuW265Je24447FcQ499NB0++23p6+//jqtttpqab755ktPPfVUGjx4cH78yiuvTOedd16uLo+AvWvXrjl0/9vf/tbkyw4AAI1JqxMAACgTb7/9dpo2bVr+faONNsoXsGyoW2+9NVd8t2r1n9qWP/zhD+nAAw9ML774Ynr33Xdzu5QRI0bkx6655ppc+R2iIjwC91B4fL/99kvXXXdd/j1C8jfffLORlxQAAJqWim8AACgT1dXVxd9nJ/QOr7zySurXr19aaKGF8t9G6F3wySef5J/bb799/hktUKIqfLvttkt//OMfc1uUEPfjbyM0X3zxxdNmm22WzjrrrNzyBAAA5iYqvgEAoExEe5FobRJV388++2wOwhsSgMe4EWbH+NGeZJVVVqlRqR29u8PZZ5+dNthgg/TII4+k119/Pf3zn//MbUyi3Un87N+/f3r55ZfT3XffnV599dXcazweu+mmm9I777yTQ3UAAJgbqPgGAIAy0bFjx7Tbbrvl3yN0/vWvf11sfRIee+yx9Nxzz830d4MGDSpWi0dP7ujZvffee8803r/+9a+0ySabpMsuuyw98cQT6dprr83DIwAPw4YNS4ssskgOyP/617+ml156KQ8fM2ZMGj58eBMtNQAAND4V3wAAUEYuv/zy9O9//zu3LokLTV511VVpmWWWSR999FEaN25cuvHGG2f6mz59+hR/X3311XN4/dlnn8003oknnph7fscFMCNkL1SEF/4+Lqx5zjnnpCWWWCJPIy5yGRZccMHcIxwAAOYWKr4BAKCMRD/t559/Pv32t7/NPbtnzJiRq607d+6cDjjggLTxxhvP9Dc//vGP0/nnn597dX/77bepd+/e6eqrr55pvJ/97Gdp7bXXThMnTsyV4Z06dUq77757uuOOO/LjMe2f/OQn+TmjFUpUkW+++ebpoYceyuMCAMDcoqq69Ao6AAAAAAAwl1PxDQAAAABARRF8AwAAAABQUQTfAAAAAABUFME3AAAAAAAVRfANAAAAAEBFEXwDAAAAAFBRBN/A/2vHDmgAAAAQBtk/tT0+iAEAAAAApIhvAAAAAABSxDcAAAAAACniGwAAAACAFPENAAAAAMBKDkpC/D59lUDvAAAAAElFTkSuQmCC",
147
+ "text/plain": [
148
+ "<Figure size 1800x700 with 1 Axes>"
149
+ ]
150
+ },
151
+ "metadata": {},
152
+ "output_type": "display_data"
153
+ }
154
+ ],
155
+ "source": [
156
+ "import numpy as np\n",
157
+ "\n",
158
+ "plt.figure(figsize=(18, 7))\n",
159
+ "bars = plt.bar(np.arange(len(classes)), class_accuracies, color='skyblue')\n",
160
+ "plt.xlabel('Class', fontweight='bold')\n",
161
+ "plt.ylabel('Accuracy (%)', fontweight='bold')\n",
162
+ "plt.title('CNN Accuracy', fontweight='bold', fontsize=16)\n",
163
+ "plt.xticks(np.arange(len(classes)), classes, ha='center')\n",
164
+ "plt.ylim([0, 100])\n",
165
+ "plt.grid(axis='y', linestyle='--', alpha=0.7)\n",
166
+ "\n",
167
+ "for bar in bars:\n",
168
+ " yval = bar.get_height()\n",
169
+ " plt.text(bar.get_x() + bar.get_width()/2.0, yval + 1, f'{yval:.2f}%', ha='center', va='bottom')\n",
170
+ "\n",
171
+ "\n",
172
+ "plt.show()\n"
173
+ ]
174
+ }
175
+ ],
176
+ "metadata": {
177
+ "kernelspec": {
178
+ "display_name": ".venv",
179
+ "language": "python",
180
+ "name": "python3"
181
+ },
182
+ "language_info": {
183
+ "codemirror_mode": {
184
+ "name": "ipython",
185
+ "version": 3
186
+ },
187
+ "file_extension": ".py",
188
+ "mimetype": "text/x-python",
189
+ "name": "python",
190
+ "nbconvert_exporter": "python",
191
+ "pygments_lexer": "ipython3",
192
+ "version": "3.12.10"
193
+ }
194
+ },
195
+ "nbformat": 4,
196
+ "nbformat_minor": 5
197
+ }
train.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
uv.lock ADDED
@@ -0,0 +1,462 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version = 1
2
+ revision = 2
3
+ requires-python = ">=3.12"
4
+
5
+ [[package]]
6
+ name = "appnope"
7
+ version = "0.1.4"
8
+ source = { registry = "https://pypi.org/simple" }
9
+ sdist = { url = "https://files.pythonhosted.org/packages/35/5d/752690df9ef5b76e169e68d6a129fa6d08a7100ca7f754c89495db3c6019/appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee", size = 4170, upload-time = "2024-02-06T09:43:11.258Z" }
10
+ wheels = [
11
+ { url = "https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c", size = 4321, upload-time = "2024-02-06T09:43:09.663Z" },
12
+ ]
13
+
14
+ [[package]]
15
+ name = "asttokens"
16
+ version = "3.0.0"
17
+ source = { registry = "https://pypi.org/simple" }
18
+ sdist = { url = "https://files.pythonhosted.org/packages/4a/e7/82da0a03e7ba5141f05cce0d302e6eed121ae055e0456ca228bf693984bc/asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7", size = 61978, upload-time = "2024-11-30T04:30:14.439Z" }
19
+ wheels = [
20
+ { url = "https://files.pythonhosted.org/packages/25/8a/c46dcc25341b5bce5472c718902eb3d38600a903b14fa6aeecef3f21a46f/asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2", size = 26918, upload-time = "2024-11-30T04:30:10.946Z" },
21
+ ]
22
+
23
+ [[package]]
24
+ name = "cffi"
25
+ version = "1.17.1"
26
+ source = { registry = "https://pypi.org/simple" }
27
+ dependencies = [
28
+ { name = "pycparser" },
29
+ ]
30
+ sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621, upload-time = "2024-09-04T20:45:21.852Z" }
31
+ wheels = [
32
+ { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178, upload-time = "2024-09-04T20:44:12.232Z" },
33
+ { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840, upload-time = "2024-09-04T20:44:13.739Z" },
34
+ { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803, upload-time = "2024-09-04T20:44:15.231Z" },
35
+ { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850, upload-time = "2024-09-04T20:44:17.188Z" },
36
+ { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729, upload-time = "2024-09-04T20:44:18.688Z" },
37
+ { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256, upload-time = "2024-09-04T20:44:20.248Z" },
38
+ { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424, upload-time = "2024-09-04T20:44:21.673Z" },
39
+ { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568, upload-time = "2024-09-04T20:44:23.245Z" },
40
+ { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736, upload-time = "2024-09-04T20:44:24.757Z" },
41
+ { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448, upload-time = "2024-09-04T20:44:26.208Z" },
42
+ { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976, upload-time = "2024-09-04T20:44:27.578Z" },
43
+ { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989, upload-time = "2024-09-04T20:44:28.956Z" },
44
+ { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802, upload-time = "2024-09-04T20:44:30.289Z" },
45
+ { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792, upload-time = "2024-09-04T20:44:32.01Z" },
46
+ { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893, upload-time = "2024-09-04T20:44:33.606Z" },
47
+ { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810, upload-time = "2024-09-04T20:44:35.191Z" },
48
+ { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200, upload-time = "2024-09-04T20:44:36.743Z" },
49
+ { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447, upload-time = "2024-09-04T20:44:38.492Z" },
50
+ { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358, upload-time = "2024-09-04T20:44:40.046Z" },
51
+ { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469, upload-time = "2024-09-04T20:44:41.616Z" },
52
+ { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475, upload-time = "2024-09-04T20:44:43.733Z" },
53
+ { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009, upload-time = "2024-09-04T20:44:45.309Z" },
54
+ ]
55
+
56
+ [[package]]
57
+ name = "cnn"
58
+ version = "0.1.0"
59
+ source = { virtual = "." }
60
+
61
+ [package.dev-dependencies]
62
+ dev = [
63
+ { name = "ipykernel" },
64
+ ]
65
+
66
+ [package.metadata]
67
+
68
+ [package.metadata.requires-dev]
69
+ dev = [{ name = "ipykernel", specifier = ">=6.29.5" }]
70
+
71
+ [[package]]
72
+ name = "colorama"
73
+ version = "0.4.6"
74
+ source = { registry = "https://pypi.org/simple" }
75
+ sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
76
+ wheels = [
77
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
78
+ ]
79
+
80
+ [[package]]
81
+ name = "comm"
82
+ version = "0.2.2"
83
+ source = { registry = "https://pypi.org/simple" }
84
+ dependencies = [
85
+ { name = "traitlets" },
86
+ ]
87
+ sdist = { url = "https://files.pythonhosted.org/packages/e9/a8/fb783cb0abe2b5fded9f55e5703015cdf1c9c85b3669087c538dd15a6a86/comm-0.2.2.tar.gz", hash = "sha256:3fd7a84065306e07bea1773df6eb8282de51ba82f77c72f9c85716ab11fe980e", size = 6210, upload-time = "2024-03-12T16:53:41.133Z" }
88
+ wheels = [
89
+ { url = "https://files.pythonhosted.org/packages/e6/75/49e5bfe642f71f272236b5b2d2691cf915a7283cc0ceda56357b61daa538/comm-0.2.2-py3-none-any.whl", hash = "sha256:e6fb86cb70ff661ee8c9c14e7d36d6de3b4066f1441be4063df9c5009f0a64d3", size = 7180, upload-time = "2024-03-12T16:53:39.226Z" },
90
+ ]
91
+
92
+ [[package]]
93
+ name = "debugpy"
94
+ version = "1.8.14"
95
+ source = { registry = "https://pypi.org/simple" }
96
+ sdist = { url = "https://files.pythonhosted.org/packages/bd/75/087fe07d40f490a78782ff3b0a30e3968936854105487decdb33446d4b0e/debugpy-1.8.14.tar.gz", hash = "sha256:7cd287184318416850aa8b60ac90105837bb1e59531898c07569d197d2ed5322", size = 1641444, upload-time = "2025-04-10T19:46:10.981Z" }
97
+ wheels = [
98
+ { url = "https://files.pythonhosted.org/packages/d9/2a/ac2df0eda4898f29c46eb6713a5148e6f8b2b389c8ec9e425a4a1d67bf07/debugpy-1.8.14-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:8899c17920d089cfa23e6005ad9f22582fd86f144b23acb9feeda59e84405b84", size = 2501268, upload-time = "2025-04-10T19:46:26.044Z" },
99
+ { url = "https://files.pythonhosted.org/packages/10/53/0a0cb5d79dd9f7039169f8bf94a144ad3efa52cc519940b3b7dde23bcb89/debugpy-1.8.14-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6bb5c0dcf80ad5dbc7b7d6eac484e2af34bdacdf81df09b6a3e62792b722826", size = 4221077, upload-time = "2025-04-10T19:46:27.464Z" },
100
+ { url = "https://files.pythonhosted.org/packages/f8/d5/84e01821f362327bf4828728aa31e907a2eca7c78cd7c6ec062780d249f8/debugpy-1.8.14-cp312-cp312-win32.whl", hash = "sha256:281d44d248a0e1791ad0eafdbbd2912ff0de9eec48022a5bfbc332957487ed3f", size = 5255127, upload-time = "2025-04-10T19:46:29.467Z" },
101
+ { url = "https://files.pythonhosted.org/packages/33/16/1ed929d812c758295cac7f9cf3dab5c73439c83d9091f2d91871e648093e/debugpy-1.8.14-cp312-cp312-win_amd64.whl", hash = "sha256:5aa56ef8538893e4502a7d79047fe39b1dae08d9ae257074c6464a7b290b806f", size = 5297249, upload-time = "2025-04-10T19:46:31.538Z" },
102
+ { url = "https://files.pythonhosted.org/packages/4d/e4/395c792b243f2367d84202dc33689aa3d910fb9826a7491ba20fc9e261f5/debugpy-1.8.14-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:329a15d0660ee09fec6786acdb6e0443d595f64f5d096fc3e3ccf09a4259033f", size = 2485676, upload-time = "2025-04-10T19:46:32.96Z" },
103
+ { url = "https://files.pythonhosted.org/packages/ba/f1/6f2ee3f991327ad9e4c2f8b82611a467052a0fb0e247390192580e89f7ff/debugpy-1.8.14-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f920c7f9af409d90f5fd26e313e119d908b0dd2952c2393cd3247a462331f15", size = 4217514, upload-time = "2025-04-10T19:46:34.336Z" },
104
+ { url = "https://files.pythonhosted.org/packages/79/28/b9d146f8f2dc535c236ee09ad3e5ac899adb39d7a19b49f03ac95d216beb/debugpy-1.8.14-cp313-cp313-win32.whl", hash = "sha256:3784ec6e8600c66cbdd4ca2726c72d8ca781e94bce2f396cc606d458146f8f4e", size = 5254756, upload-time = "2025-04-10T19:46:36.199Z" },
105
+ { url = "https://files.pythonhosted.org/packages/e0/62/a7b4a57013eac4ccaef6977966e6bec5c63906dd25a86e35f155952e29a1/debugpy-1.8.14-cp313-cp313-win_amd64.whl", hash = "sha256:684eaf43c95a3ec39a96f1f5195a7ff3d4144e4a18d69bb66beeb1a6de605d6e", size = 5297119, upload-time = "2025-04-10T19:46:38.141Z" },
106
+ { url = "https://files.pythonhosted.org/packages/97/1a/481f33c37ee3ac8040d3d51fc4c4e4e7e61cb08b8bc8971d6032acc2279f/debugpy-1.8.14-py2.py3-none-any.whl", hash = "sha256:5cd9a579d553b6cb9759a7908a41988ee6280b961f24f63336835d9418216a20", size = 5256230, upload-time = "2025-04-10T19:46:54.077Z" },
107
+ ]
108
+
109
+ [[package]]
110
+ name = "decorator"
111
+ version = "5.2.1"
112
+ source = { registry = "https://pypi.org/simple" }
113
+ sdist = { url = "https://files.pythonhosted.org/packages/43/fa/6d96a0978d19e17b68d634497769987b16c8f4cd0a7a05048bec693caa6b/decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360", size = 56711, upload-time = "2025-02-24T04:41:34.073Z" }
114
+ wheels = [
115
+ { url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190, upload-time = "2025-02-24T04:41:32.565Z" },
116
+ ]
117
+
118
+ [[package]]
119
+ name = "executing"
120
+ version = "2.2.0"
121
+ source = { registry = "https://pypi.org/simple" }
122
+ sdist = { url = "https://files.pythonhosted.org/packages/91/50/a9d80c47ff289c611ff12e63f7c5d13942c65d68125160cefd768c73e6e4/executing-2.2.0.tar.gz", hash = "sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755", size = 978693, upload-time = "2025-01-22T15:41:29.403Z" }
123
+ wheels = [
124
+ { url = "https://files.pythonhosted.org/packages/7b/8f/c4d9bafc34ad7ad5d8dc16dd1347ee0e507a52c3adb6bfa8887e1c6a26ba/executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa", size = 26702, upload-time = "2025-01-22T15:41:25.929Z" },
125
+ ]
126
+
127
+ [[package]]
128
+ name = "ipykernel"
129
+ version = "6.29.5"
130
+ source = { registry = "https://pypi.org/simple" }
131
+ dependencies = [
132
+ { name = "appnope", marker = "sys_platform == 'darwin'" },
133
+ { name = "comm" },
134
+ { name = "debugpy" },
135
+ { name = "ipython" },
136
+ { name = "jupyter-client" },
137
+ { name = "jupyter-core" },
138
+ { name = "matplotlib-inline" },
139
+ { name = "nest-asyncio" },
140
+ { name = "packaging" },
141
+ { name = "psutil" },
142
+ { name = "pyzmq" },
143
+ { name = "tornado" },
144
+ { name = "traitlets" },
145
+ ]
146
+ sdist = { url = "https://files.pythonhosted.org/packages/e9/5c/67594cb0c7055dc50814b21731c22a601101ea3b1b50a9a1b090e11f5d0f/ipykernel-6.29.5.tar.gz", hash = "sha256:f093a22c4a40f8828f8e330a9c297cb93dcab13bd9678ded6de8e5cf81c56215", size = 163367, upload-time = "2024-07-01T14:07:22.543Z" }
147
+ wheels = [
148
+ { url = "https://files.pythonhosted.org/packages/94/5c/368ae6c01c7628438358e6d337c19b05425727fbb221d2a3c4303c372f42/ipykernel-6.29.5-py3-none-any.whl", hash = "sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5", size = 117173, upload-time = "2024-07-01T14:07:19.603Z" },
149
+ ]
150
+
151
+ [[package]]
152
+ name = "ipython"
153
+ version = "9.4.0"
154
+ source = { registry = "https://pypi.org/simple" }
155
+ dependencies = [
156
+ { name = "colorama", marker = "sys_platform == 'win32'" },
157
+ { name = "decorator" },
158
+ { name = "ipython-pygments-lexers" },
159
+ { name = "jedi" },
160
+ { name = "matplotlib-inline" },
161
+ { name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
162
+ { name = "prompt-toolkit" },
163
+ { name = "pygments" },
164
+ { name = "stack-data" },
165
+ { name = "traitlets" },
166
+ ]
167
+ sdist = { url = "https://files.pythonhosted.org/packages/54/80/406f9e3bde1c1fd9bf5a0be9d090f8ae623e401b7670d8f6fdf2ab679891/ipython-9.4.0.tar.gz", hash = "sha256:c033c6d4e7914c3d9768aabe76bbe87ba1dc66a92a05db6bfa1125d81f2ee270", size = 4385338, upload-time = "2025-07-01T11:11:30.606Z" }
168
+ wheels = [
169
+ { url = "https://files.pythonhosted.org/packages/63/f8/0031ee2b906a15a33d6bfc12dd09c3dfa966b3cb5b284ecfb7549e6ac3c4/ipython-9.4.0-py3-none-any.whl", hash = "sha256:25850f025a446d9b359e8d296ba175a36aedd32e83ca9b5060430fe16801f066", size = 611021, upload-time = "2025-07-01T11:11:27.85Z" },
170
+ ]
171
+
172
+ [[package]]
173
+ name = "ipython-pygments-lexers"
174
+ version = "1.1.1"
175
+ source = { registry = "https://pypi.org/simple" }
176
+ dependencies = [
177
+ { name = "pygments" },
178
+ ]
179
+ sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393, upload-time = "2025-01-17T11:24:34.505Z" }
180
+ wheels = [
181
+ { url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074, upload-time = "2025-01-17T11:24:33.271Z" },
182
+ ]
183
+
184
+ [[package]]
185
+ name = "jedi"
186
+ version = "0.19.2"
187
+ source = { registry = "https://pypi.org/simple" }
188
+ dependencies = [
189
+ { name = "parso" },
190
+ ]
191
+ sdist = { url = "https://files.pythonhosted.org/packages/72/3a/79a912fbd4d8dd6fbb02bf69afd3bb72cf0c729bb3063c6f4498603db17a/jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0", size = 1231287, upload-time = "2024-11-11T01:41:42.873Z" }
192
+ wheels = [
193
+ { url = "https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9", size = 1572278, upload-time = "2024-11-11T01:41:40.175Z" },
194
+ ]
195
+
196
+ [[package]]
197
+ name = "jupyter-client"
198
+ version = "8.6.3"
199
+ source = { registry = "https://pypi.org/simple" }
200
+ dependencies = [
201
+ { name = "jupyter-core" },
202
+ { name = "python-dateutil" },
203
+ { name = "pyzmq" },
204
+ { name = "tornado" },
205
+ { name = "traitlets" },
206
+ ]
207
+ sdist = { url = "https://files.pythonhosted.org/packages/71/22/bf9f12fdaeae18019a468b68952a60fe6dbab5d67cd2a103cac7659b41ca/jupyter_client-8.6.3.tar.gz", hash = "sha256:35b3a0947c4a6e9d589eb97d7d4cd5e90f910ee73101611f01283732bd6d9419", size = 342019, upload-time = "2024-09-17T10:44:17.613Z" }
208
+ wheels = [
209
+ { url = "https://files.pythonhosted.org/packages/11/85/b0394e0b6fcccd2c1eeefc230978a6f8cb0c5df1e4cd3e7625735a0d7d1e/jupyter_client-8.6.3-py3-none-any.whl", hash = "sha256:e8a19cc986cc45905ac3362915f410f3af85424b4c0905e94fa5f2cb08e8f23f", size = 106105, upload-time = "2024-09-17T10:44:15.218Z" },
210
+ ]
211
+
212
+ [[package]]
213
+ name = "jupyter-core"
214
+ version = "5.8.1"
215
+ source = { registry = "https://pypi.org/simple" }
216
+ dependencies = [
217
+ { name = "platformdirs" },
218
+ { name = "pywin32", marker = "platform_python_implementation != 'PyPy' and sys_platform == 'win32'" },
219
+ { name = "traitlets" },
220
+ ]
221
+ sdist = { url = "https://files.pythonhosted.org/packages/99/1b/72906d554acfeb588332eaaa6f61577705e9ec752ddb486f302dafa292d9/jupyter_core-5.8.1.tar.gz", hash = "sha256:0a5f9706f70e64786b75acba995988915ebd4601c8a52e534a40b51c95f59941", size = 88923, upload-time = "2025-05-27T07:38:16.655Z" }
222
+ wheels = [
223
+ { url = "https://files.pythonhosted.org/packages/2f/57/6bffd4b20b88da3800c5d691e0337761576ee688eb01299eae865689d2df/jupyter_core-5.8.1-py3-none-any.whl", hash = "sha256:c28d268fc90fb53f1338ded2eb410704c5449a358406e8a948b75706e24863d0", size = 28880, upload-time = "2025-05-27T07:38:15.137Z" },
224
+ ]
225
+
226
+ [[package]]
227
+ name = "matplotlib-inline"
228
+ version = "0.1.7"
229
+ source = { registry = "https://pypi.org/simple" }
230
+ dependencies = [
231
+ { name = "traitlets" },
232
+ ]
233
+ sdist = { url = "https://files.pythonhosted.org/packages/99/5b/a36a337438a14116b16480db471ad061c36c3694df7c2084a0da7ba538b7/matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90", size = 8159, upload-time = "2024-04-15T13:44:44.803Z" }
234
+ wheels = [
235
+ { url = "https://files.pythonhosted.org/packages/8f/8e/9ad090d3553c280a8060fbf6e24dc1c0c29704ee7d1c372f0c174aa59285/matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca", size = 9899, upload-time = "2024-04-15T13:44:43.265Z" },
236
+ ]
237
+
238
+ [[package]]
239
+ name = "nest-asyncio"
240
+ version = "1.6.0"
241
+ source = { registry = "https://pypi.org/simple" }
242
+ sdist = { url = "https://files.pythonhosted.org/packages/83/f8/51569ac65d696c8ecbee95938f89d4abf00f47d58d48f6fbabfe8f0baefe/nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", size = 7418, upload-time = "2024-01-21T14:25:19.227Z" }
243
+ wheels = [
244
+ { url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195, upload-time = "2024-01-21T14:25:17.223Z" },
245
+ ]
246
+
247
+ [[package]]
248
+ name = "packaging"
249
+ version = "25.0"
250
+ source = { registry = "https://pypi.org/simple" }
251
+ sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" }
252
+ wheels = [
253
+ { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" },
254
+ ]
255
+
256
+ [[package]]
257
+ name = "parso"
258
+ version = "0.8.4"
259
+ source = { registry = "https://pypi.org/simple" }
260
+ sdist = { url = "https://files.pythonhosted.org/packages/66/94/68e2e17afaa9169cf6412ab0f28623903be73d1b32e208d9e8e541bb086d/parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d", size = 400609, upload-time = "2024-04-05T09:43:55.897Z" }
261
+ wheels = [
262
+ { url = "https://files.pythonhosted.org/packages/c6/ac/dac4a63f978e4dcb3c6d3a78c4d8e0192a113d288502a1216950c41b1027/parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18", size = 103650, upload-time = "2024-04-05T09:43:53.299Z" },
263
+ ]
264
+
265
+ [[package]]
266
+ name = "pexpect"
267
+ version = "4.9.0"
268
+ source = { registry = "https://pypi.org/simple" }
269
+ dependencies = [
270
+ { name = "ptyprocess" },
271
+ ]
272
+ sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" }
273
+ wheels = [
274
+ { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" },
275
+ ]
276
+
277
+ [[package]]
278
+ name = "platformdirs"
279
+ version = "4.3.8"
280
+ source = { registry = "https://pypi.org/simple" }
281
+ sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362, upload-time = "2025-05-07T22:47:42.121Z" }
282
+ wheels = [
283
+ { url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567, upload-time = "2025-05-07T22:47:40.376Z" },
284
+ ]
285
+
286
+ [[package]]
287
+ name = "prompt-toolkit"
288
+ version = "3.0.51"
289
+ source = { registry = "https://pypi.org/simple" }
290
+ dependencies = [
291
+ { name = "wcwidth" },
292
+ ]
293
+ sdist = { url = "https://files.pythonhosted.org/packages/bb/6e/9d084c929dfe9e3bfe0c6a47e31f78a25c54627d64a66e884a8bf5474f1c/prompt_toolkit-3.0.51.tar.gz", hash = "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed", size = 428940, upload-time = "2025-04-15T09:18:47.731Z" }
294
+ wheels = [
295
+ { url = "https://files.pythonhosted.org/packages/ce/4f/5249960887b1fbe561d9ff265496d170b55a735b76724f10ef19f9e40716/prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07", size = 387810, upload-time = "2025-04-15T09:18:44.753Z" },
296
+ ]
297
+
298
+ [[package]]
299
+ name = "psutil"
300
+ version = "7.0.0"
301
+ source = { registry = "https://pypi.org/simple" }
302
+ sdist = { url = "https://files.pythonhosted.org/packages/2a/80/336820c1ad9286a4ded7e845b2eccfcb27851ab8ac6abece774a6ff4d3de/psutil-7.0.0.tar.gz", hash = "sha256:7be9c3eba38beccb6495ea33afd982a44074b78f28c434a1f51cc07fd315c456", size = 497003, upload-time = "2025-02-13T21:54:07.946Z" }
303
+ wheels = [
304
+ { url = "https://files.pythonhosted.org/packages/ed/e6/2d26234410f8b8abdbf891c9da62bee396583f713fb9f3325a4760875d22/psutil-7.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:101d71dc322e3cffd7cea0650b09b3d08b8e7c4109dd6809fe452dfd00e58b25", size = 238051, upload-time = "2025-02-13T21:54:12.36Z" },
305
+ { url = "https://files.pythonhosted.org/packages/04/8b/30f930733afe425e3cbfc0e1468a30a18942350c1a8816acfade80c005c4/psutil-7.0.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:39db632f6bb862eeccf56660871433e111b6ea58f2caea825571951d4b6aa3da", size = 239535, upload-time = "2025-02-13T21:54:16.07Z" },
306
+ { url = "https://files.pythonhosted.org/packages/2a/ed/d362e84620dd22876b55389248e522338ed1bf134a5edd3b8231d7207f6d/psutil-7.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fcee592b4c6f146991ca55919ea3d1f8926497a713ed7faaf8225e174581e91", size = 275004, upload-time = "2025-02-13T21:54:18.662Z" },
307
+ { url = "https://files.pythonhosted.org/packages/bf/b9/b0eb3f3cbcb734d930fdf839431606844a825b23eaf9a6ab371edac8162c/psutil-7.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b1388a4f6875d7e2aff5c4ca1cc16c545ed41dd8bb596cefea80111db353a34", size = 277986, upload-time = "2025-02-13T21:54:21.811Z" },
308
+ { url = "https://files.pythonhosted.org/packages/eb/a2/709e0fe2f093556c17fbafda93ac032257242cabcc7ff3369e2cb76a97aa/psutil-7.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5f098451abc2828f7dc6b58d44b532b22f2088f4999a937557b603ce72b1993", size = 279544, upload-time = "2025-02-13T21:54:24.68Z" },
309
+ { url = "https://files.pythonhosted.org/packages/50/e6/eecf58810b9d12e6427369784efe814a1eec0f492084ce8eb8f4d89d6d61/psutil-7.0.0-cp37-abi3-win32.whl", hash = "sha256:ba3fcef7523064a6c9da440fc4d6bd07da93ac726b5733c29027d7dc95b39d99", size = 241053, upload-time = "2025-02-13T21:54:34.31Z" },
310
+ { url = "https://files.pythonhosted.org/packages/50/1b/6921afe68c74868b4c9fa424dad3be35b095e16687989ebbb50ce4fceb7c/psutil-7.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:4cf3d4eb1aa9b348dec30105c55cd9b7d4629285735a102beb4441e38db90553", size = 244885, upload-time = "2025-02-13T21:54:37.486Z" },
311
+ ]
312
+
313
+ [[package]]
314
+ name = "ptyprocess"
315
+ version = "0.7.0"
316
+ source = { registry = "https://pypi.org/simple" }
317
+ sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762, upload-time = "2020-12-28T15:15:30.155Z" }
318
+ wheels = [
319
+ { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993, upload-time = "2020-12-28T15:15:28.35Z" },
320
+ ]
321
+
322
+ [[package]]
323
+ name = "pure-eval"
324
+ version = "0.2.3"
325
+ source = { registry = "https://pypi.org/simple" }
326
+ sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752, upload-time = "2024-07-21T12:58:21.801Z" }
327
+ wheels = [
328
+ { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" },
329
+ ]
330
+
331
+ [[package]]
332
+ name = "pycparser"
333
+ version = "2.22"
334
+ source = { registry = "https://pypi.org/simple" }
335
+ sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736, upload-time = "2024-03-30T13:22:22.564Z" }
336
+ wheels = [
337
+ { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552, upload-time = "2024-03-30T13:22:20.476Z" },
338
+ ]
339
+
340
+ [[package]]
341
+ name = "pygments"
342
+ version = "2.19.2"
343
+ source = { registry = "https://pypi.org/simple" }
344
+ sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" }
345
+ wheels = [
346
+ { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" },
347
+ ]
348
+
349
+ [[package]]
350
+ name = "python-dateutil"
351
+ version = "2.9.0.post0"
352
+ source = { registry = "https://pypi.org/simple" }
353
+ dependencies = [
354
+ { name = "six" },
355
+ ]
356
+ sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" }
357
+ wheels = [
358
+ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" },
359
+ ]
360
+
361
+ [[package]]
362
+ name = "pywin32"
363
+ version = "310"
364
+ source = { registry = "https://pypi.org/simple" }
365
+ wheels = [
366
+ { url = "https://files.pythonhosted.org/packages/6b/ec/4fdbe47932f671d6e348474ea35ed94227fb5df56a7c30cbbb42cd396ed0/pywin32-310-cp312-cp312-win32.whl", hash = "sha256:8a75a5cc3893e83a108c05d82198880704c44bbaee4d06e442e471d3c9ea4f3d", size = 8796239, upload-time = "2025-03-17T00:55:58.807Z" },
367
+ { url = "https://files.pythonhosted.org/packages/e3/e5/b0627f8bb84e06991bea89ad8153a9e50ace40b2e1195d68e9dff6b03d0f/pywin32-310-cp312-cp312-win_amd64.whl", hash = "sha256:bf5c397c9a9a19a6f62f3fb821fbf36cac08f03770056711f765ec1503972060", size = 9503839, upload-time = "2025-03-17T00:56:00.8Z" },
368
+ { url = "https://files.pythonhosted.org/packages/1f/32/9ccf53748df72301a89713936645a664ec001abd35ecc8578beda593d37d/pywin32-310-cp312-cp312-win_arm64.whl", hash = "sha256:2349cc906eae872d0663d4d6290d13b90621eaf78964bb1578632ff20e152966", size = 8459470, upload-time = "2025-03-17T00:56:02.601Z" },
369
+ { url = "https://files.pythonhosted.org/packages/1c/09/9c1b978ffc4ae53999e89c19c77ba882d9fce476729f23ef55211ea1c034/pywin32-310-cp313-cp313-win32.whl", hash = "sha256:5d241a659c496ada3253cd01cfaa779b048e90ce4b2b38cd44168ad555ce74ab", size = 8794384, upload-time = "2025-03-17T00:56:04.383Z" },
370
+ { url = "https://files.pythonhosted.org/packages/45/3c/b4640f740ffebadd5d34df35fecba0e1cfef8fde9f3e594df91c28ad9b50/pywin32-310-cp313-cp313-win_amd64.whl", hash = "sha256:667827eb3a90208ddbdcc9e860c81bde63a135710e21e4cb3348968e4bd5249e", size = 9503039, upload-time = "2025-03-17T00:56:06.207Z" },
371
+ { url = "https://files.pythonhosted.org/packages/b4/f4/f785020090fb050e7fb6d34b780f2231f302609dc964672f72bfaeb59a28/pywin32-310-cp313-cp313-win_arm64.whl", hash = "sha256:e308f831de771482b7cf692a1f308f8fca701b2d8f9dde6cc440c7da17e47b33", size = 8458152, upload-time = "2025-03-17T00:56:07.819Z" },
372
+ ]
373
+
374
+ [[package]]
375
+ name = "pyzmq"
376
+ version = "27.0.0"
377
+ source = { registry = "https://pypi.org/simple" }
378
+ dependencies = [
379
+ { name = "cffi", marker = "implementation_name == 'pypy'" },
380
+ ]
381
+ sdist = { url = "https://files.pythonhosted.org/packages/f1/06/50a4e9648b3e8b992bef8eb632e457307553a89d294103213cfd47b3da69/pyzmq-27.0.0.tar.gz", hash = "sha256:b1f08eeb9ce1510e6939b6e5dcd46a17765e2333daae78ecf4606808442e52cf", size = 280478, upload-time = "2025-06-13T14:09:07.087Z" }
382
+ wheels = [
383
+ { url = "https://files.pythonhosted.org/packages/93/a7/9ad68f55b8834ede477842214feba6a4c786d936c022a67625497aacf61d/pyzmq-27.0.0-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:cbabc59dcfaac66655c040dfcb8118f133fb5dde185e5fc152628354c1598e52", size = 1305438, upload-time = "2025-06-13T14:07:31.676Z" },
384
+ { url = "https://files.pythonhosted.org/packages/ba/ee/26aa0f98665a22bc90ebe12dced1de5f3eaca05363b717f6fb229b3421b3/pyzmq-27.0.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:cb0ac5179cba4b2f94f1aa208fbb77b62c4c9bf24dd446278b8b602cf85fcda3", size = 895095, upload-time = "2025-06-13T14:07:33.104Z" },
385
+ { url = "https://files.pythonhosted.org/packages/cf/85/c57e7ab216ecd8aa4cc7e3b83b06cc4e9cf45c87b0afc095f10cd5ce87c1/pyzmq-27.0.0-cp312-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53a48f0228eab6cbf69fde3aa3c03cbe04e50e623ef92ae395fce47ef8a76152", size = 651826, upload-time = "2025-06-13T14:07:34.831Z" },
386
+ { url = "https://files.pythonhosted.org/packages/69/9a/9ea7e230feda9400fb0ae0d61d7d6ddda635e718d941c44eeab22a179d34/pyzmq-27.0.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:111db5f395e09f7e775f759d598f43cb815fc58e0147623c4816486e1a39dc22", size = 839750, upload-time = "2025-06-13T14:07:36.553Z" },
387
+ { url = "https://files.pythonhosted.org/packages/08/66/4cebfbe71f3dfbd417011daca267539f62ed0fbc68105357b68bbb1a25b7/pyzmq-27.0.0-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c8878011653dcdc27cc2c57e04ff96f0471e797f5c19ac3d7813a245bcb24371", size = 1641357, upload-time = "2025-06-13T14:07:38.21Z" },
388
+ { url = "https://files.pythonhosted.org/packages/ac/f6/b0f62578c08d2471c791287149cb8c2aaea414ae98c6e995c7dbe008adfb/pyzmq-27.0.0-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:c0ed2c1f335ba55b5fdc964622254917d6b782311c50e138863eda409fbb3b6d", size = 2020281, upload-time = "2025-06-13T14:07:39.599Z" },
389
+ { url = "https://files.pythonhosted.org/packages/37/b9/4f670b15c7498495da9159edc374ec09c88a86d9cd5a47d892f69df23450/pyzmq-27.0.0-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e918d70862d4cfd4b1c187310015646a14e1f5917922ab45b29f28f345eeb6be", size = 1877110, upload-time = "2025-06-13T14:07:41.027Z" },
390
+ { url = "https://files.pythonhosted.org/packages/66/31/9dee25c226295b740609f0d46db2fe972b23b6f5cf786360980524a3ba92/pyzmq-27.0.0-cp312-abi3-win32.whl", hash = "sha256:88b4e43cab04c3c0f0d55df3b1eef62df2b629a1a369b5289a58f6fa8b07c4f4", size = 559297, upload-time = "2025-06-13T14:07:42.533Z" },
391
+ { url = "https://files.pythonhosted.org/packages/9b/12/52da5509800f7ff2d287b2f2b4e636e7ea0f001181cba6964ff6c1537778/pyzmq-27.0.0-cp312-abi3-win_amd64.whl", hash = "sha256:dce4199bf5f648a902ce37e7b3afa286f305cd2ef7a8b6ec907470ccb6c8b371", size = 619203, upload-time = "2025-06-13T14:07:43.843Z" },
392
+ { url = "https://files.pythonhosted.org/packages/93/6d/7f2e53b19d1edb1eb4f09ec7c3a1f945ca0aac272099eab757d15699202b/pyzmq-27.0.0-cp312-abi3-win_arm64.whl", hash = "sha256:56e46bbb85d52c1072b3f809cc1ce77251d560bc036d3a312b96db1afe76db2e", size = 551927, upload-time = "2025-06-13T14:07:45.51Z" },
393
+ { url = "https://files.pythonhosted.org/packages/19/62/876b27c4ff777db4ceba1c69ea90d3c825bb4f8d5e7cd987ce5802e33c55/pyzmq-27.0.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:c36ad534c0c29b4afa088dc53543c525b23c0797e01b69fef59b1a9c0e38b688", size = 1340826, upload-time = "2025-06-13T14:07:46.881Z" },
394
+ { url = "https://files.pythonhosted.org/packages/43/69/58ef8f4f59d3bcd505260c73bee87b008850f45edca40ddaba54273c35f4/pyzmq-27.0.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:67855c14173aec36395d7777aaba3cc527b393821f30143fd20b98e1ff31fd38", size = 897283, upload-time = "2025-06-13T14:07:49.562Z" },
395
+ { url = "https://files.pythonhosted.org/packages/43/15/93a0d0396700a60475ad3c5d42c5f1c308d3570bc94626b86c71ef9953e0/pyzmq-27.0.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8617c7d43cd8ccdb62aebe984bfed77ca8f036e6c3e46dd3dddda64b10f0ab7a", size = 660567, upload-time = "2025-06-13T14:07:51.364Z" },
396
+ { url = "https://files.pythonhosted.org/packages/0e/b3/fe055513e498ca32f64509abae19b9c9eb4d7c829e02bd8997dd51b029eb/pyzmq-27.0.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:67bfbcbd0a04c575e8103a6061d03e393d9f80ffdb9beb3189261e9e9bc5d5e9", size = 847681, upload-time = "2025-06-13T14:07:52.77Z" },
397
+ { url = "https://files.pythonhosted.org/packages/b6/4f/ff15300b00b5b602191f3df06bbc8dd4164e805fdd65bb77ffbb9c5facdc/pyzmq-27.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5cd11d46d7b7e5958121b3eaf4cd8638eff3a720ec527692132f05a57f14341d", size = 1650148, upload-time = "2025-06-13T14:07:54.178Z" },
398
+ { url = "https://files.pythonhosted.org/packages/c4/6f/84bdfff2a224a6f26a24249a342e5906993c50b0761e311e81b39aef52a7/pyzmq-27.0.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:b801c2e40c5aa6072c2f4876de8dccd100af6d9918d4d0d7aa54a1d982fd4f44", size = 2023768, upload-time = "2025-06-13T14:07:55.714Z" },
399
+ { url = "https://files.pythonhosted.org/packages/64/39/dc2db178c26a42228c5ac94a9cc595030458aa64c8d796a7727947afbf55/pyzmq-27.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:20d5cb29e8c5f76a127c75b6e7a77e846bc4b655c373baa098c26a61b7ecd0ef", size = 1885199, upload-time = "2025-06-13T14:07:57.166Z" },
400
+ { url = "https://files.pythonhosted.org/packages/c7/21/dae7b06a1f8cdee5d8e7a63d99c5d129c401acc40410bef2cbf42025e26f/pyzmq-27.0.0-cp313-cp313t-win32.whl", hash = "sha256:a20528da85c7ac7a19b7384e8c3f8fa707841fd85afc4ed56eda59d93e3d98ad", size = 575439, upload-time = "2025-06-13T14:07:58.959Z" },
401
+ { url = "https://files.pythonhosted.org/packages/eb/bc/1709dc55f0970cf4cb8259e435e6773f9946f41a045c2cb90e870b7072da/pyzmq-27.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:d8229f2efece6a660ee211d74d91dbc2a76b95544d46c74c615e491900dc107f", size = 639933, upload-time = "2025-06-13T14:08:00.777Z" },
402
+ ]
403
+
404
+ [[package]]
405
+ name = "six"
406
+ version = "1.17.0"
407
+ source = { registry = "https://pypi.org/simple" }
408
+ sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" }
409
+ wheels = [
410
+ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" },
411
+ ]
412
+
413
+ [[package]]
414
+ name = "stack-data"
415
+ version = "0.6.3"
416
+ source = { registry = "https://pypi.org/simple" }
417
+ dependencies = [
418
+ { name = "asttokens" },
419
+ { name = "executing" },
420
+ { name = "pure-eval" },
421
+ ]
422
+ sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707, upload-time = "2023-09-30T13:58:05.479Z" }
423
+ wheels = [
424
+ { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" },
425
+ ]
426
+
427
+ [[package]]
428
+ name = "tornado"
429
+ version = "6.5.1"
430
+ source = { registry = "https://pypi.org/simple" }
431
+ sdist = { url = "https://files.pythonhosted.org/packages/51/89/c72771c81d25d53fe33e3dca61c233b665b2780f21820ba6fd2c6793c12b/tornado-6.5.1.tar.gz", hash = "sha256:84ceece391e8eb9b2b95578db65e920d2a61070260594819589609ba9bc6308c", size = 509934, upload-time = "2025-05-22T18:15:38.788Z" }
432
+ wheels = [
433
+ { url = "https://files.pythonhosted.org/packages/77/89/f4532dee6843c9e0ebc4e28d4be04c67f54f60813e4bf73d595fe7567452/tornado-6.5.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:d50065ba7fd11d3bd41bcad0825227cc9a95154bad83239357094c36708001f7", size = 441948, upload-time = "2025-05-22T18:15:20.862Z" },
434
+ { url = "https://files.pythonhosted.org/packages/15/9a/557406b62cffa395d18772e0cdcf03bed2fff03b374677348eef9f6a3792/tornado-6.5.1-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9e9ca370f717997cb85606d074b0e5b247282cf5e2e1611568b8821afe0342d6", size = 440112, upload-time = "2025-05-22T18:15:22.591Z" },
435
+ { url = "https://files.pythonhosted.org/packages/55/82/7721b7319013a3cf881f4dffa4f60ceff07b31b394e459984e7a36dc99ec/tornado-6.5.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b77e9dfa7ed69754a54c89d82ef746398be82f749df69c4d3abe75c4d1ff4888", size = 443672, upload-time = "2025-05-22T18:15:24.027Z" },
436
+ { url = "https://files.pythonhosted.org/packages/7d/42/d11c4376e7d101171b94e03cef0cbce43e823ed6567ceda571f54cf6e3ce/tornado-6.5.1-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:253b76040ee3bab8bcf7ba9feb136436a3787208717a1fb9f2c16b744fba7331", size = 443019, upload-time = "2025-05-22T18:15:25.735Z" },
437
+ { url = "https://files.pythonhosted.org/packages/7d/f7/0c48ba992d875521ac761e6e04b0a1750f8150ae42ea26df1852d6a98942/tornado-6.5.1-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:308473f4cc5a76227157cdf904de33ac268af770b2c5f05ca6c1161d82fdd95e", size = 443252, upload-time = "2025-05-22T18:15:27.499Z" },
438
+ { url = "https://files.pythonhosted.org/packages/89/46/d8d7413d11987e316df4ad42e16023cd62666a3c0dfa1518ffa30b8df06c/tornado-6.5.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:caec6314ce8a81cf69bd89909f4b633b9f523834dc1a352021775d45e51d9401", size = 443930, upload-time = "2025-05-22T18:15:29.299Z" },
439
+ { url = "https://files.pythonhosted.org/packages/78/b2/f8049221c96a06df89bed68260e8ca94beca5ea532ffc63b1175ad31f9cc/tornado-6.5.1-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:13ce6e3396c24e2808774741331638ee6c2f50b114b97a55c5b442df65fd9692", size = 443351, upload-time = "2025-05-22T18:15:31.038Z" },
440
+ { url = "https://files.pythonhosted.org/packages/76/ff/6a0079e65b326cc222a54720a748e04a4db246870c4da54ece4577bfa702/tornado-6.5.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5cae6145f4cdf5ab24744526cc0f55a17d76f02c98f4cff9daa08ae9a217448a", size = 443328, upload-time = "2025-05-22T18:15:32.426Z" },
441
+ { url = "https://files.pythonhosted.org/packages/49/18/e3f902a1d21f14035b5bc6246a8c0f51e0eef562ace3a2cea403c1fb7021/tornado-6.5.1-cp39-abi3-win32.whl", hash = "sha256:e0a36e1bc684dca10b1aa75a31df8bdfed656831489bc1e6a6ebed05dc1ec365", size = 444396, upload-time = "2025-05-22T18:15:34.205Z" },
442
+ { url = "https://files.pythonhosted.org/packages/7b/09/6526e32bf1049ee7de3bebba81572673b19a2a8541f795d887e92af1a8bc/tornado-6.5.1-cp39-abi3-win_amd64.whl", hash = "sha256:908e7d64567cecd4c2b458075589a775063453aeb1d2a1853eedb806922f568b", size = 444840, upload-time = "2025-05-22T18:15:36.1Z" },
443
+ { url = "https://files.pythonhosted.org/packages/55/a7/535c44c7bea4578e48281d83c615219f3ab19e6abc67625ef637c73987be/tornado-6.5.1-cp39-abi3-win_arm64.whl", hash = "sha256:02420a0eb7bf617257b9935e2b754d1b63897525d8a289c9d65690d580b4dcf7", size = 443596, upload-time = "2025-05-22T18:15:37.433Z" },
444
+ ]
445
+
446
+ [[package]]
447
+ name = "traitlets"
448
+ version = "5.14.3"
449
+ source = { registry = "https://pypi.org/simple" }
450
+ sdist = { url = "https://files.pythonhosted.org/packages/eb/79/72064e6a701c2183016abbbfedaba506d81e30e232a68c9f0d6f6fcd1574/traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", size = 161621, upload-time = "2024-04-19T11:11:49.746Z" }
451
+ wheels = [
452
+ { url = "https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f", size = 85359, upload-time = "2024-04-19T11:11:46.763Z" },
453
+ ]
454
+
455
+ [[package]]
456
+ name = "wcwidth"
457
+ version = "0.2.13"
458
+ source = { registry = "https://pypi.org/simple" }
459
+ sdist = { url = "https://files.pythonhosted.org/packages/6c/63/53559446a878410fc5a5974feb13d31d78d752eb18aeba59c7fef1af7598/wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5", size = 101301, upload-time = "2024-01-06T02:10:57.829Z" }
460
+ wheels = [
461
+ { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166, upload-time = "2024-01-06T02:10:55.763Z" },
462
+ ]