Spaces:
Running
Running
Upload folder using huggingface_hub
Browse files- src/__pycache__/model.cpython-311.pyc +0 -0
- src/__pycache__/model.cpython-312.pyc +0 -0
- src/__pycache__/utils.cpython-311.pyc +0 -0
- src/__pycache__/utils.cpython-312.pyc +0 -0
- src/get_data.py +49 -0
- src/main.py +59 -0
- src/model.py +27 -0
- src/model_training.ipynb +838 -0
- src/templates/index.html +10 -0
- src/test.ipynb +0 -0
- src/utils.py +55 -0
src/__pycache__/model.cpython-311.pyc
ADDED
Binary file (2.14 kB). View file
|
|
src/__pycache__/model.cpython-312.pyc
ADDED
Binary file (1.93 kB). View file
|
|
src/__pycache__/utils.cpython-311.pyc
ADDED
Binary file (3.84 kB). View file
|
|
src/__pycache__/utils.cpython-312.pyc
ADDED
Binary file (3.45 kB). View file
|
|
src/get_data.py
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import random
|
3 |
+
import shutil
|
4 |
+
|
5 |
+
|
6 |
+
def extract_images(source_folder, destination_folder):
|
7 |
+
count = 0
|
8 |
+
for root, _, files in os.walk(source_folder):
|
9 |
+
for file in files:
|
10 |
+
if file.endswith(('jpg', '.png')):
|
11 |
+
src_path = os.path.join(root, file)
|
12 |
+
dst_path = os.path.join(destination_folder, f"{count:05d}" + os.path.splitext(file)[1])
|
13 |
+
shutil.copy(src_path, dst_path)
|
14 |
+
count += 1
|
15 |
+
|
16 |
+
|
17 |
+
def split_data(data_folder):
|
18 |
+
train_folder = f"{data_folder}/train"
|
19 |
+
validation_folder = f"{data_folder}/validation"
|
20 |
+
test_folder = f"{data_folder}/test"
|
21 |
+
|
22 |
+
for folder in [train_folder, validation_folder, test_folder]:
|
23 |
+
if not os.path.exists(folder):
|
24 |
+
os.makedirs(folder)
|
25 |
+
|
26 |
+
image_files = [f for f in os.listdir(data_folder) if os.path.isfile(os.path.join(data_folder, f))]
|
27 |
+
random.shuffle(image_files)
|
28 |
+
|
29 |
+
total_images = len(image_files)
|
30 |
+
train_count = int(0.7 * total_images)
|
31 |
+
validation_count = int(0.2 * total_images)
|
32 |
+
|
33 |
+
for i in range(train_count):
|
34 |
+
shutil.move(os.path.join(data_folder, image_files[i]), train_folder)
|
35 |
+
|
36 |
+
for i in range(train_count, train_count + validation_count):
|
37 |
+
shutil.move(os.path.join(data_folder, image_files[i]), validation_folder)
|
38 |
+
|
39 |
+
for i in range(train_count + validation_count, total_images):
|
40 |
+
shutil.move(os.path.join(data_folder, image_files[i]), test_folder)
|
41 |
+
|
42 |
+
|
43 |
+
if __name__ == "__main__":
|
44 |
+
source_folder = "manga/"
|
45 |
+
destination_folder = "data/"
|
46 |
+
extract_images(source_folder, destination_folder)
|
47 |
+
|
48 |
+
data_folder = "data/"
|
49 |
+
split_data(data_folder)
|
src/main.py
ADDED
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
|
3 |
+
import gradio as gr
|
4 |
+
import torch
|
5 |
+
from PIL import Image
|
6 |
+
|
7 |
+
from model import MangaColorizer
|
8 |
+
from utils import pil_to_torch, torch_to_pil
|
9 |
+
|
10 |
+
def load_html_template():
|
11 |
+
html_dir = os.path.join(os.path.dirname(__file__), "templates")
|
12 |
+
index_html_path = os.path.join(html_dir, "index.html")
|
13 |
+
|
14 |
+
if os.path.exists(index_html_path):
|
15 |
+
with open(index_html_path, "r") as html_file:
|
16 |
+
index_html = html_file.read()
|
17 |
+
return index_html
|
18 |
+
else:
|
19 |
+
print(f"Error: {index_html_path} not found.")
|
20 |
+
|
21 |
+
|
22 |
+
def load_model():
|
23 |
+
model = MangaColorizer()
|
24 |
+
models_dir = os.path.join(os.path.dirname(__file__), '..', 'model')
|
25 |
+
model_file = os.path.join(models_dir, 'best_model_checkpoint.pth')
|
26 |
+
if os.path.exists(model_file):
|
27 |
+
with open(model_file, "rb") as f:
|
28 |
+
checkpoint = torch.load(f, map_location="cpu")
|
29 |
+
model.load_state_dict(checkpoint)
|
30 |
+
else:
|
31 |
+
print(f"Error: {model_file} not found.")
|
32 |
+
|
33 |
+
return model
|
34 |
+
model = load_model()
|
35 |
+
|
36 |
+
def colorize_image(image):
|
37 |
+
global model
|
38 |
+
img = Image.fromarray(image).convert("L")
|
39 |
+
output = model(pil_to_torch(img)).detach().cpu()
|
40 |
+
output_image = torch_to_pil(output)
|
41 |
+
|
42 |
+
return output_image
|
43 |
+
|
44 |
+
|
45 |
+
def main():
|
46 |
+
index_html = load_html_template()
|
47 |
+
with gr.Blocks() as demo:
|
48 |
+
gr.HTML(index_html)
|
49 |
+
gr.Interface(colorize_image, inputs=["image"], outputs=["image"], allow_flagging="never")
|
50 |
+
gr.HTML("""
|
51 |
+
<p style="text-align: center;font-size: large;">
|
52 |
+
Checkout the <a href="https://github.com/zaidmehdi/manga-colorizer">Github Repo</a>
|
53 |
+
</p>
|
54 |
+
""")
|
55 |
+
demo.launch(server_name="0.0.0.0", server_port=8080)
|
56 |
+
|
57 |
+
|
58 |
+
if __name__ == "__main__":
|
59 |
+
main()
|
src/model.py
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch.nn as nn
|
2 |
+
|
3 |
+
|
4 |
+
class MangaColorizer(nn.Module):
|
5 |
+
def __init__(self):
|
6 |
+
super(MangaColorizer, self).__init__()
|
7 |
+
self.encoder = nn.Sequential(
|
8 |
+
nn.Conv2d(1, 64, kernel_size=3, stride=1, padding=1),
|
9 |
+
nn.ReLU(inplace=True),
|
10 |
+
nn.Conv2d(64, 128, kernel_size=3, stride=2, padding=1),
|
11 |
+
nn.ReLU(inplace=True),
|
12 |
+
nn.Conv2d(128, 256, kernel_size=3, stride=2, padding=1),
|
13 |
+
nn.ReLU(inplace=True)
|
14 |
+
)
|
15 |
+
self.decoder = nn.Sequential(
|
16 |
+
nn.ConvTranspose2d(256, 128, kernel_size=4, stride=2, padding=1),
|
17 |
+
nn.ReLU(inplace=True),
|
18 |
+
nn.ConvTranspose2d(128, 64, kernel_size=4, stride=2, padding=1),
|
19 |
+
nn.ReLU(inplace=True),
|
20 |
+
nn.ConvTranspose2d(64, 3, kernel_size=3, stride=1, padding=1),
|
21 |
+
nn.Tanh()
|
22 |
+
)
|
23 |
+
|
24 |
+
def forward(self, x):
|
25 |
+
x = self.encoder(x)
|
26 |
+
x = self.decoder(x)
|
27 |
+
return x
|
src/model_training.ipynb
ADDED
@@ -0,0 +1,838 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"cells": [
|
3 |
+
{
|
4 |
+
"cell_type": "code",
|
5 |
+
"execution_count": 2,
|
6 |
+
"id": "06eef311",
|
7 |
+
"metadata": {
|
8 |
+
"execution": {
|
9 |
+
"iopub.execute_input": "2024-04-01T01:04:34.377065Z",
|
10 |
+
"iopub.status.busy": "2024-04-01T01:04:34.376156Z",
|
11 |
+
"iopub.status.idle": "2024-04-01T01:04:41.159287Z",
|
12 |
+
"shell.execute_reply": "2024-04-01T01:04:41.158448Z"
|
13 |
+
},
|
14 |
+
"papermill": {
|
15 |
+
"duration": 6.79219,
|
16 |
+
"end_time": "2024-04-01T01:04:41.161646",
|
17 |
+
"exception": false,
|
18 |
+
"start_time": "2024-04-01T01:04:34.369456",
|
19 |
+
"status": "completed"
|
20 |
+
},
|
21 |
+
"tags": []
|
22 |
+
},
|
23 |
+
"outputs": [],
|
24 |
+
"source": [
|
25 |
+
"import matplotlib.pyplot as plt\n",
|
26 |
+
"import numpy as np\n",
|
27 |
+
"import torch\n",
|
28 |
+
"import torch.nn as nn\n",
|
29 |
+
"import torch.optim as optim\n",
|
30 |
+
"from torchvision import transforms\n",
|
31 |
+
"from torch.utils.data import DataLoader\n",
|
32 |
+
"from tqdm.auto import tqdm\n",
|
33 |
+
"\n",
|
34 |
+
"from model import MangaColorizer\n",
|
35 |
+
"from utils import ImageDataset, adjust_output_shape"
|
36 |
+
]
|
37 |
+
},
|
38 |
+
{
|
39 |
+
"cell_type": "markdown",
|
40 |
+
"id": "5e7ff784",
|
41 |
+
"metadata": {
|
42 |
+
"papermill": {
|
43 |
+
"duration": 0.004403,
|
44 |
+
"end_time": "2024-04-01T01:04:41.171084",
|
45 |
+
"exception": false,
|
46 |
+
"start_time": "2024-04-01T01:04:41.166681",
|
47 |
+
"status": "completed"
|
48 |
+
},
|
49 |
+
"tags": []
|
50 |
+
},
|
51 |
+
"source": [
|
52 |
+
"## Model architecture"
|
53 |
+
]
|
54 |
+
},
|
55 |
+
{
|
56 |
+
"cell_type": "code",
|
57 |
+
"execution_count": 3,
|
58 |
+
"id": "87d03ce6",
|
59 |
+
"metadata": {
|
60 |
+
"execution": {
|
61 |
+
"iopub.execute_input": "2024-04-01T01:04:41.182184Z",
|
62 |
+
"iopub.status.busy": "2024-04-01T01:04:41.181258Z",
|
63 |
+
"iopub.status.idle": "2024-04-01T01:04:41.190651Z",
|
64 |
+
"shell.execute_reply": "2024-04-01T01:04:41.189724Z"
|
65 |
+
},
|
66 |
+
"papermill": {
|
67 |
+
"duration": 0.017191,
|
68 |
+
"end_time": "2024-04-01T01:04:41.192743",
|
69 |
+
"exception": false,
|
70 |
+
"start_time": "2024-04-01T01:04:41.175552",
|
71 |
+
"status": "completed"
|
72 |
+
},
|
73 |
+
"tags": []
|
74 |
+
},
|
75 |
+
"outputs": [
|
76 |
+
{
|
77 |
+
"data": {
|
78 |
+
"text/plain": [
|
79 |
+
"MangaColorizer(\n",
|
80 |
+
" (encoder): Sequential(\n",
|
81 |
+
" (0): Conv2d(1, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
|
82 |
+
" (1): ReLU(inplace=True)\n",
|
83 |
+
" (2): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))\n",
|
84 |
+
" (3): ReLU(inplace=True)\n",
|
85 |
+
" (4): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))\n",
|
86 |
+
" (5): ReLU(inplace=True)\n",
|
87 |
+
" )\n",
|
88 |
+
" (decoder): Sequential(\n",
|
89 |
+
" (0): ConvTranspose2d(256, 128, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1))\n",
|
90 |
+
" (1): ReLU(inplace=True)\n",
|
91 |
+
" (2): ConvTranspose2d(128, 64, kernel_size=(4, 4), stride=(2, 2), padding=(1, 1))\n",
|
92 |
+
" (3): ReLU(inplace=True)\n",
|
93 |
+
" (4): ConvTranspose2d(64, 3, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
|
94 |
+
" (5): Tanh()\n",
|
95 |
+
" )\n",
|
96 |
+
")"
|
97 |
+
]
|
98 |
+
},
|
99 |
+
"execution_count": 3,
|
100 |
+
"metadata": {},
|
101 |
+
"output_type": "execute_result"
|
102 |
+
}
|
103 |
+
],
|
104 |
+
"source": [
|
105 |
+
"model = MangaColorizer()\n",
|
106 |
+
"model"
|
107 |
+
]
|
108 |
+
},
|
109 |
+
{
|
110 |
+
"cell_type": "markdown",
|
111 |
+
"id": "c4b5ff4a",
|
112 |
+
"metadata": {
|
113 |
+
"papermill": {
|
114 |
+
"duration": 0.004206,
|
115 |
+
"end_time": "2024-04-01T01:04:41.201565",
|
116 |
+
"exception": false,
|
117 |
+
"start_time": "2024-04-01T01:04:41.197359",
|
118 |
+
"status": "completed"
|
119 |
+
},
|
120 |
+
"tags": []
|
121 |
+
},
|
122 |
+
"source": [
|
123 |
+
"## Loading the Data"
|
124 |
+
]
|
125 |
+
},
|
126 |
+
{
|
127 |
+
"cell_type": "code",
|
128 |
+
"execution_count": 5,
|
129 |
+
"id": "42198e39",
|
130 |
+
"metadata": {
|
131 |
+
"execution": {
|
132 |
+
"iopub.execute_input": "2024-04-01T01:04:41.247525Z",
|
133 |
+
"iopub.status.busy": "2024-04-01T01:04:41.247244Z",
|
134 |
+
"iopub.status.idle": "2024-04-01T01:04:41.627306Z",
|
135 |
+
"shell.execute_reply": "2024-04-01T01:04:41.626292Z"
|
136 |
+
},
|
137 |
+
"papermill": {
|
138 |
+
"duration": 0.387773,
|
139 |
+
"end_time": "2024-04-01T01:04:41.629778",
|
140 |
+
"exception": false,
|
141 |
+
"start_time": "2024-04-01T01:04:41.242005",
|
142 |
+
"status": "completed"
|
143 |
+
},
|
144 |
+
"tags": []
|
145 |
+
},
|
146 |
+
"outputs": [],
|
147 |
+
"source": [
|
148 |
+
"transform = transforms.Compose([\n",
|
149 |
+
" transforms.ToTensor()\n",
|
150 |
+
"])\n",
|
151 |
+
"\n",
|
152 |
+
"train_dataset = ImageDataset(dir=\"/kaggle/input/manga-panels-colored/data/train\", \n",
|
153 |
+
" transform=transform)\n",
|
154 |
+
"validation_dataset = ImageDataset(dir=\"/kaggle/input/manga-panels-colored/data/validation\", \n",
|
155 |
+
" transform=transform)\n",
|
156 |
+
"test_dataset = ImageDataset(dir=\"/kaggle/input/manga-panels-colored/data/test\", \n",
|
157 |
+
" transform=transform)"
|
158 |
+
]
|
159 |
+
},
|
160 |
+
{
|
161 |
+
"cell_type": "code",
|
162 |
+
"execution_count": 6,
|
163 |
+
"id": "8e5ea6dd",
|
164 |
+
"metadata": {
|
165 |
+
"execution": {
|
166 |
+
"iopub.execute_input": "2024-04-01T01:04:41.640890Z",
|
167 |
+
"iopub.status.busy": "2024-04-01T01:04:41.640098Z",
|
168 |
+
"iopub.status.idle": "2024-04-01T01:04:41.645385Z",
|
169 |
+
"shell.execute_reply": "2024-04-01T01:04:41.644485Z"
|
170 |
+
},
|
171 |
+
"papermill": {
|
172 |
+
"duration": 0.012881,
|
173 |
+
"end_time": "2024-04-01T01:04:41.647392",
|
174 |
+
"exception": false,
|
175 |
+
"start_time": "2024-04-01T01:04:41.634511",
|
176 |
+
"status": "completed"
|
177 |
+
},
|
178 |
+
"tags": []
|
179 |
+
},
|
180 |
+
"outputs": [],
|
181 |
+
"source": [
|
182 |
+
"train_loader = DataLoader(train_dataset, batch_size=1, shuffle=True)\n",
|
183 |
+
"validation_loader = DataLoader(validation_dataset, batch_size=1, shuffle=True)\n",
|
184 |
+
"test_loader = DataLoader(test_dataset, batch_size=1, shuffle=True)"
|
185 |
+
]
|
186 |
+
},
|
187 |
+
{
|
188 |
+
"cell_type": "markdown",
|
189 |
+
"id": "fd0bbc4c",
|
190 |
+
"metadata": {
|
191 |
+
"papermill": {
|
192 |
+
"duration": 0.004236,
|
193 |
+
"end_time": "2024-04-01T01:04:41.656333",
|
194 |
+
"exception": false,
|
195 |
+
"start_time": "2024-04-01T01:04:41.652097",
|
196 |
+
"status": "completed"
|
197 |
+
},
|
198 |
+
"tags": []
|
199 |
+
},
|
200 |
+
"source": [
|
201 |
+
"## Training the model"
|
202 |
+
]
|
203 |
+
},
|
204 |
+
{
|
205 |
+
"cell_type": "code",
|
206 |
+
"execution_count": 8,
|
207 |
+
"id": "6bb853cd",
|
208 |
+
"metadata": {
|
209 |
+
"execution": {
|
210 |
+
"iopub.execute_input": "2024-04-01T01:04:41.683769Z",
|
211 |
+
"iopub.status.busy": "2024-04-01T01:04:41.683460Z",
|
212 |
+
"iopub.status.idle": "2024-04-01T01:04:41.721713Z",
|
213 |
+
"shell.execute_reply": "2024-04-01T01:04:41.720922Z"
|
214 |
+
},
|
215 |
+
"papermill": {
|
216 |
+
"duration": 0.04614,
|
217 |
+
"end_time": "2024-04-01T01:04:41.724036",
|
218 |
+
"exception": false,
|
219 |
+
"start_time": "2024-04-01T01:04:41.677896",
|
220 |
+
"status": "completed"
|
221 |
+
},
|
222 |
+
"tags": []
|
223 |
+
},
|
224 |
+
"outputs": [],
|
225 |
+
"source": [
|
226 |
+
"criterion = nn.MSELoss()\n",
|
227 |
+
"optimizer = optim.Adam(model.parameters(), lr=0.0001)"
|
228 |
+
]
|
229 |
+
},
|
230 |
+
{
|
231 |
+
"cell_type": "code",
|
232 |
+
"execution_count": null,
|
233 |
+
"id": "7b70952d",
|
234 |
+
"metadata": {
|
235 |
+
"execution": {
|
236 |
+
"iopub.execute_input": "2024-04-01T01:04:41.735281Z",
|
237 |
+
"iopub.status.busy": "2024-04-01T01:04:41.734495Z",
|
238 |
+
"iopub.status.idle": "2024-04-01T01:04:41.955794Z",
|
239 |
+
"shell.execute_reply": "2024-04-01T01:04:41.954865Z"
|
240 |
+
},
|
241 |
+
"papermill": {
|
242 |
+
"duration": 0.229072,
|
243 |
+
"end_time": "2024-04-01T01:04:41.957864",
|
244 |
+
"exception": false,
|
245 |
+
"start_time": "2024-04-01T01:04:41.728792",
|
246 |
+
"status": "completed"
|
247 |
+
},
|
248 |
+
"tags": []
|
249 |
+
},
|
250 |
+
"outputs": [],
|
251 |
+
"source": [
|
252 |
+
"device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n",
|
253 |
+
"model.to(device)"
|
254 |
+
]
|
255 |
+
},
|
256 |
+
{
|
257 |
+
"cell_type": "code",
|
258 |
+
"execution_count": null,
|
259 |
+
"id": "4d252b1e",
|
260 |
+
"metadata": {
|
261 |
+
"execution": {
|
262 |
+
"iopub.execute_input": "2024-04-01T01:04:41.969269Z",
|
263 |
+
"iopub.status.busy": "2024-04-01T01:04:41.968485Z",
|
264 |
+
"iopub.status.idle": "2024-04-01T10:06:12.760575Z",
|
265 |
+
"shell.execute_reply": "2024-04-01T10:06:12.759664Z"
|
266 |
+
},
|
267 |
+
"papermill": {
|
268 |
+
"duration": 32490.811819,
|
269 |
+
"end_time": "2024-04-01T10:06:12.774567",
|
270 |
+
"exception": false,
|
271 |
+
"start_time": "2024-04-01T01:04:41.962748",
|
272 |
+
"status": "completed"
|
273 |
+
},
|
274 |
+
"tags": []
|
275 |
+
},
|
276 |
+
"outputs": [],
|
277 |
+
"source": [
|
278 |
+
"num_epochs = 100\n",
|
279 |
+
"num_training_steps = num_epochs * len(train_loader)\n",
|
280 |
+
"progress_bar = tqdm(range(num_training_steps))\n",
|
281 |
+
"\n",
|
282 |
+
"train_losses = []\n",
|
283 |
+
"valid_losses = []\n",
|
284 |
+
"\n",
|
285 |
+
"best_valid_loss = float(\"inf\")\n",
|
286 |
+
"epochs_no_improve = 0\n",
|
287 |
+
"patience = 10\n",
|
288 |
+
"best_model = None\n",
|
289 |
+
"\n",
|
290 |
+
"for epoch in range(num_epochs):\n",
|
291 |
+
" model.train()\n",
|
292 |
+
" train_loss = 0.0\n",
|
293 |
+
" for images, targets in train_loader:\n",
|
294 |
+
" images = images.to(device)\n",
|
295 |
+
" targets = targets.to(device)\n",
|
296 |
+
" outputs = model(images)\n",
|
297 |
+
" try:\n",
|
298 |
+
" loss = criterion(outputs, targets)\n",
|
299 |
+
" except RuntimeError:\n",
|
300 |
+
" adjusted_output = adjust_output_shape(outputs, targets)\n",
|
301 |
+
" loss = criterion(adjusted_output, targets)\n",
|
302 |
+
" loss.backward()\n",
|
303 |
+
"\n",
|
304 |
+
" optimizer.step()\n",
|
305 |
+
" optimizer.zero_grad()\n",
|
306 |
+
" progress_bar.update(1)\n",
|
307 |
+
"\n",
|
308 |
+
" train_loss += loss.item()\n",
|
309 |
+
" \n",
|
310 |
+
" train_losses.append(train_loss / len(train_loader))\n",
|
311 |
+
"\n",
|
312 |
+
" model.eval()\n",
|
313 |
+
" valid_loss = 0.0\n",
|
314 |
+
" with torch.no_grad():\n",
|
315 |
+
" for images, targets in validation_loader:\n",
|
316 |
+
" images = images.to(device)\n",
|
317 |
+
" targets = targets.to(device)\n",
|
318 |
+
" outputs = model(images)\n",
|
319 |
+
" try:\n",
|
320 |
+
" loss = criterion(outputs, targets)\n",
|
321 |
+
" except RuntimeError:\n",
|
322 |
+
" adjusted_output = adjust_output_shape(outputs, targets)\n",
|
323 |
+
" loss = criterion(adjusted_output, targets)\n",
|
324 |
+
" valid_loss += loss.item()\n",
|
325 |
+
" \n",
|
326 |
+
" valid_loss /= len(validation_loader)\n",
|
327 |
+
" valid_losses.append(valid_loss)\n",
|
328 |
+
"\n",
|
329 |
+
" print(f'Epoch [{epoch+1}/{num_epochs}], Train Loss: {train_losses[-1]:.4f}, Valid Loss: {valid_loss:.4f}') \n",
|
330 |
+
" torch.save(model.state_dict(), \"last_checkpoint.pth\")\n",
|
331 |
+
"\n",
|
332 |
+
" if valid_loss < best_valid_loss:\n",
|
333 |
+
" best_valid_loss = valid_loss\n",
|
334 |
+
" epochs_no_improve = 0\n",
|
335 |
+
" best_model = model.state_dict()\n",
|
336 |
+
" torch.save(best_model, \"best_model_checkpoint.pth\")\n",
|
337 |
+
" else:\n",
|
338 |
+
" epochs_no_improve += 1\n",
|
339 |
+
" if epochs_no_improve == patience:\n",
|
340 |
+
" print(f\"Early stopping after {epoch+1} epochs with no improvement.\")\n",
|
341 |
+
" break\n",
|
342 |
+
"\n",
|
343 |
+
"model.load_state_dict(best_model)"
|
344 |
+
]
|
345 |
+
},
|
346 |
+
{
|
347 |
+
"cell_type": "code",
|
348 |
+
"execution_count": 11,
|
349 |
+
"id": "e3d447f1",
|
350 |
+
"metadata": {
|
351 |
+
"execution": {
|
352 |
+
"iopub.execute_input": "2024-04-01T10:06:12.800929Z",
|
353 |
+
"iopub.status.busy": "2024-04-01T10:06:12.800630Z",
|
354 |
+
"iopub.status.idle": "2024-04-01T10:06:13.054441Z",
|
355 |
+
"shell.execute_reply": "2024-04-01T10:06:13.053544Z"
|
356 |
+
},
|
357 |
+
"papermill": {
|
358 |
+
"duration": 0.269281,
|
359 |
+
"end_time": "2024-04-01T10:06:13.056431",
|
360 |
+
"exception": false,
|
361 |
+
"start_time": "2024-04-01T10:06:12.787150",
|
362 |
+
"status": "completed"
|
363 |
+
},
|
364 |
+
"tags": []
|
365 |
+
},
|
366 |
+
"outputs": [
|
367 |
+
{
|
368 |
+
"data": {
|
369 |
+
"image/png": "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G926dcNvv/2GmTNn4ptvvkFycrJjzU1VSqVXVi1QvqL4w81+bVVYrVbcf//9+PbbbzFhwgSsXbsWycnJjmIWV36+W1X5MDg4GPfffz/+97//wWw245tvvkFubi4GDx7saPPpp59i2LBhaNSoET766CNs2rQJycnJuO+++2q0hP3s2bMxfvx43HPPPfj000/x3XffITk5GS1btrxlpfNr+rqoiuDgYOzfvx/r1q1zrJ/r3bu301rDe+65B3///Tc+/vhjtGrVCh9++CHuvvtufPjhh7esn0TkvlgkhIjoDrR9+3ZcunQJa9aswT333OM4fuLECRf2qlRwcDAMBkOFGztfbbNnu99//x1//fUXVqxYgSFDhjiO30iVvfr162PLli3Iy8tzGkU7cuTIdZ1n8ODB2LRpEzZu3IiVK1fC19cX/fr1czz/5ZdfomHDhlizZo3TtMTp06dXq88AcPToUTRs2NBxPDMzs9yo1Jdffol7770XH330kdPx7OxsBAUFOR5XpYJm2fffvHkzcnNznUbR7FNo7f27FerXr48DBw7AZrM5jaJV1BedTod+/fqhX79+sNlseP755/H+++9j6tSpjhHcWrVqYfjw4Rg+fDjy8vJwzz33YMaMGXjqqadu2WciIvfEETQiojuQfaSi7MiEyWTCe++956ouOVGr1YiPj8fatWuRlpbmOH7s2LFy65Yqez3g/PlkWXYqlX69+vTpA4vFgiVLljiOWa1WLFy48LrOk5iYCE9PT7z33nvYuHEjHn74YRgMhqv2fefOnUhJSbnuPsfHx0Or1WLhwoVO51uwYEG5tmq1utxIVVJSEs6dO+d0zMvLCwCqtL1Anz59YLVasWjRIqfj77zzDiRJqvJ6wpuhT58+SE9Px+rVqx3HLBYLFi5cCG9vb8f010uXLjm9TqVSOTYPLy4urrCNt7c3Gjdu7HieiKgmcQSNiOgO1KlTJwQEBGDo0KEYO3YsJEnCf//731s6lexaZsyYge+//x6dO3fGc8895/hFv1WrVti/f/9VX9usWTM0atQIL7/8Ms6dOwdfX1/873//u6G1TP369UPnzp0xceJEnDx5Ei1atMCaNWuue32Wt7c3EhMTHevQyk5vBIAHHngAa9asQf/+/dG3b1+cOHECS5cuRYsWLZCXl3dd72Xfz23OnDl44IEH0KdPH6SmpmLjxo1Oo2L29505cyaGDx+OTp064ffff8dnn33mNPIGAI0aNYK/vz+WLl0KHx8feHl5ITY2Fg0aNCj3/v369cO9996LV199FSdPnkR0dDS+//57fP3113jhhRecCoLcDFu2bEFRUVG544mJiRg5ciTef/99DBs2DHv37kVkZCS+/PJL/PLLL1iwYIFjhO+pp55CVlYW7rvvPtStWxenTp3CwoULERMT41iv1qJFC3Tv3h1t27ZFrVq1sGfPHnz55ZcYPXr0Tf08REQVYUAjIroDBQYGYv369XjppZcwZcoUBAQE4PHHH0ePHj2QkJDg6u4BANq2bYuNGzfi5ZdfxtSpUxEREYGZM2fi0KFD16wyqdVq8c0332Ds2LGYM2cODAYD+vfvj9GjRyM6Orpa/VGpVFi3bh1eeOEFfPrpp5AkCQ8++CDmz5+PNm3aXNe5Bg8ejJUrVyIsLAz33Xef03PDhg1Deno63n//fXz33Xdo0aIFPv30UyQlJWH79u3X3e/XX38dBoMBS5cuxbZt2xAbG4vvv/8effv2dWo3efJk5OfnY+XKlVi9ejXuvvtufPvtt5g4caJTO61WixUrVmDSpEl49tlnYbFYsGzZsgoDmv07mzZtGlavXo1ly5YhMjIS8+bNw0svvXTdn+VaNm3aVOHG1pGRkWjVqhW2b9+OiRMnYsWKFTAajWjatCmWLVuGYcOGOdo+/vjj+OCDD/Dee+8hOzsboaGhGDhwIGbMmOGYGjl27FisW7cO33//PYqLi1G/fn28/vrreOWVV276ZyIiupIkK+nPqURE5PYSExNZ4pyIiNwW16AREZHLFBYWOj0+evQoNmzYgO7du7umQ0RERC7GETQiInKZsLAwDBs2DA0bNsSpU6ewZMkSFBcXIzU1tdzeXkRERO6Aa9CIiMhlevXqhc8//xzp6enQ6/WIi4vD7NmzGc6IiMhtcQSNiIiIiIhIIbgGjYiIiIiISCEY0IiIiIiIiBSCa9BqkM1mQ1paGnx8fCBJkqu7Q0RERERELiLLMnJzcxEeHu7Yd7EiDGg1KC0tDREREa7uBhERERERKcSZM2dQt27dSp9nQKtBPj4+AMQ/gq+vr4t7Q0RERERErmI0GhEREeHICJVhQKtB9mmNvr6+DGhERERERHTNpU8sEkJERERERKQQDGhEREREREQKwYBGRERERESkEFyDRkRERETkArIsw2KxwGq1urordBOo1WpoNJob3l6LAY2IiIiI6BYzmUw4f/48CgoKXN0Vuok8PT0RFhYGnU5X7XMwoBERERER3UI2mw0nTpyAWq1GeHg4dDrdDY+6kGvJsgyTyYTMzEycOHECTZo0uepm1FfDgEZEREREdAuZTCbYbDZERETA09PT1d2hm8TDwwNarRanTp2CyWSCwWCo1nlYJISIiIiIyAWqO8JCynUz/k15VRARERERESkEAxoREREREZFCMKAREREREZHLREZGYsGCBa7uhmIwoBERERER0TVJknTV24wZM6p13t27d2PkyJE31Lfu3bvjhRdeuKFzKAWrOBIRERER0TWdP3/e8fPq1asxbdo0HDlyxHHM29vb8bMsy7BardBorh03ateufXM7epvjCJob+PX4JfRa8CNGr9zn6q4QERERUQVkWUaByeKSmyzLVepjaGio4+bn5wdJkhyPDx8+DB8fH2zcuBFt27aFXq/Hzz//jL///hsPPfQQQkJC4O3tjfbt22Pz5s1O571yiqMkSfjwww/Rv39/eHp6okmTJli3bt0Nfb//+9//0LJlS+j1ekRGRmL+/PlOz7/33nto0qQJDAYDQkJCMGDAAMdzX375JaKiouDh4YHAwEDEx8cjPz//hvpzNRxBcwOFZisOp+dCreIGiERERERKVGi2osW071zy3n/OTICn7ubEgokTJ+Ktt95Cw4YNERAQgDNnzqBPnz7417/+Bb1ej08++QT9+vXDkSNHUK9evUrP89prr2Hu3LmYN28eFi5ciMGDB+PUqVOoVavWdfdp7969ePTRRzFjxgwMHDgQO3bswPPPP4/AwEAMGzYMe/bswdixY/Hf//4XnTp1QlZWFn766ScAYtRw0KBBmDt3Lvr374/c3Fz89NNPVQ611cGA5gZ0ajFQarbaXNwTIiIiIrqTzZw5E/fff7/jca1atRAdHe14PGvWLHz11VdYt24dRo8eXel5hg0bhkGDBgEAZs+ejXfffRe7du1Cr169rrtPb7/9Nnr06IGpU6cCAO666y78+eefmDdvHoYNG4bTp0/Dy8sLDzzwAHx8fFC/fn20adMGgAhoFosFDz/8MOrXrw8AiIqKuu4+XA8GNDeg09gDWs0lfSIiIiKqPg+tGn/OTHDZe98s7dq1c3qcl5eHGTNm4Ntvv3WEncLCQpw+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RKuWAAAmFgkhIiIiIlIkBjQ3omORECIiIiIiRWNAcyOOMvssEkJEREREpEgMaG7EUSSEUxyJiIiIiBSJAc2N2NegcYojEREREZEyMaC5Ea5BIyIiIiJSNgY0N6LlRtVERERERIrGgOZG7EVCuFE1EREREZEyMaC5kbJr0GSZo2hERERERErDgOZG9Go1AECWAauNAY2IiIiISGkY0NyIViM5fuY0RyIiIiIi5WFAcyP2IiEAYLZwBI2IiIiISGkY0NyIRsURNCIiIiIiJWNAcyOSJHEvNCIiIiIiBWNAczNlKzkSEREREZGyMKC5GfteaAxoRERERETKw4DmZuyFQkwsEkJEREREpDgMaG6Ga9CIiIiIiJSLAc3NcA0aEREREZFyMaC5GccURwY0IiIiIiLFYUBzMzpHkRCuQSMiIiIiUhoGNDdTWiSEI2hERERERErDgOZmWCSEiIiIiEi5GNDcjFbDIiFERERERErFgOZmOMWRiIiIiEi5GNDcjFbNIiFERERERErFgOZmuAaNiIiIiEi5GNDcDDeqJiIiIiJSLgY0N8ONqomIiIiIlIsBzc1o7RtVW7gGjYiIiIhIaRjQ3AzXoBERERERKRcDmpvRaRjQiIiIiIiUShEBbfHixYiMjITBYEBsbCx27dp11fZJSUlo1qwZDAYDoqKisGHDBsdzZrMZEyZMQFRUFLy8vBAeHo4hQ4YgLS3N6RxZWVkYPHgwfH194e/vjxEjRiAvL8+pzYEDB9C1a1cYDAZERERg7ty5N+9Du4i9SEgx90EjIiIiIlIclwe01atXY/z48Zg+fTr27duH6OhoJCQk4MKFCxW237FjBwYNGoQRI0YgNTUViYmJSExMxB9//AEAKCgowL59+zB16lTs27cPa9aswZEjR/Dggw86nWfw4ME4ePAgkpOTsX79evz4448YOXKk43mj0YiePXuifv362Lt3L+bNm4cZM2bggw8+qLkv4xbQcoojEREREZFiSbIsu7RaRGxsLNq3b49FixYBAGw2GyIiIjBmzBhMnDixXPuBAwciPz8f69evdxzr2LEjYmJisHTp0grfY/fu3ejQoQNOnTqFevXq4dChQ2jRogV2796Ndu3aAQA2bdqEPn364OzZswgPD8eSJUvw6quvIj09HTqdDgAwceJErF27FocPH67wfYqLi1FcXOx4bDQaERER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zpw5AIBx48ahW7dumD9/Pvr27YtVq1Zhz549+OCDDxznzMrKwunTp5GWlgYAOHLkCAAx+hYaGuoIZwUFBfj000+dinnUrl0barUa33zzDTIyMtCxY0cYDAYkJydj9uzZePnll2/l13NLaNVimiMDGhERERGR67k0oA0cOBCZmZmYNm0a0tPTERMTg02bNjkKgZw+fRoqVekgX6dOnbBy5UpMmTIFkydPRpMmTbB27Vq0atXK0WbdunWOgAcAjz32GABg+vTpmDFjBvbt24edO3cCABo3buzUnxMnTiAyMhJarRaLFy/Giy++CFmW0bhxY7z99tt4+umna+y7cBXHZtUWVnEkIiIiInI1l+6DdqdT+j5oAND5ja04l12Ir0d1RnSEv6u7Q0RERER0R1L8PmikDFyDRkRERESkHAxo7qI4F7h8qtxh+xo0EwMaEREREZHLMaC5gwNfAG82ADb+X7mn7GvQzFbOdCUiIiIicjUGNHcQ3BywmYETPwIW533cHAGN+6AREREREbkcA5o7CGkFeIcA5gLg9K9OT+nUXINGRERERKQUDGjuQJKARj3Ez8c2Oz2l1XANGhERERGRUjCguYvG9oC2xemwzrEPGgMaEREREZGrMaC5i0b3AZCACwcB43nHYRYJISIiIiJSDgY0d+FZC6hzt/j579JRNC33QSMiIiIiUgwGNHfSOF7cl1mHxiIhRERERETKwYDmTuwB7e9tgM0KgBtVExEREREpCQOaOwm/GzD4AUXZwLl9AMrug8Y1aERERERErsaA5k7UGqDhveLnkmmOWk5xJCIiIiJSDAY0d3PFOjQdi4QQERERESkGA5q7se+Hdm4vUJDFNWhERERERArCgOZufMOB4BYAZOD4Nk5xJCIiIiJSEAY0d2QfRTu2pXSKI4uEEBERERG5HAOaOyqzDk2n4hRHIiIiIiKlYEBzR/XiAK0nkJeB4MJjABjQiIiIiIiUgAHNHWn0QGRXAEBEVgoAwGxhQCMiIiIicjUGNHdVMs2xzsVfALBICBERERGREjCguauSQiFBWfvghUKYrSwSQkRERETkagxo7qpWQyAgEirZgjjVn1yDRkRERESkAAxo7kqSHNMc71Ed4BRHIiIiIiIFYEBzZyUBrbtqP8wWq4s7Q0REREREGld3gFwositsKi3qIRO1TWmu7g0RERERkdvjCJo703sjL7gdAOBu0x4Xd4aIiIiIiBjQ3FxeRHcAQJzlV8DGdWhERERERK7EgObmCiLjYZMltLP9DqzoB1w+5eouERERERG5LQY0NxcY2RqTrM8gX9YDp34GlnQGUj8FZO6LRkRERER0qzGgubkALx0M7Z9Ab9MbOKRtAZhyga9HAasGA3mZru4eEREREZFbYUAjjLq3MTLUYeibOxnHo18GVFrgyLfAkjjg8AZXd4+IiIiIyG0woBGCfQ0YElcfNqgw7uy9kJ/eAgS3APIzgVWDgE8fAbbMAg4kAed/A0wFru4yEREREdEdSZJlLjaqKUajEX5+fsjJyYGvr6+ru3NVl/KK0XXuNhSYrHj/ibZIaBoAbH0d2LEQwJWXiAT41wNqNwUCmwC1GgABDcS9XwSg0bniIxARERERKVZVswEDWg26nQIaALz13REs2nYMzUJ9sGFsV6hUEpD+O3DiJ+DiESDzLyDzMFCYVflJJBXgWxeoFQnU6wR0HQ9o9LfsMxARERERKVFVs4HmFvaJFO7prg2xIuUkDqfn4tvfz6NfdDgQGiVuZeVfBDKPiNB26W8g6wRw+QRw+SRgLgByTovbiR8BmwXoMdUln4eIiIiI6HbDgEYOfp5aPN21Id5O/gvvbP4LvVuFQqOuYJmiV5C4RXZ2Pi7LQF6GCGonfxJTJH9ZALTsD4S2uhUfgYiIiIjotubyIiGLFy9GZGQkDAYDYmNjsWvXrqu2T0pKQrNmzWAwGBAVFYUNG5yrDK5ZswY9e/ZEYGAgJEnC/v37y52jqKgIo0aNQmBgILy9vfHII48gIyPDqc3p06fRt29feHp6Ijg4GK+88gosFssNf16lG945EgGeWhzPzMfX+9Ou78WSBPiEAvU6Ave8AjR7QIygrRsNWO/8746IiIiI6Ea5NKCtXr0a48ePx/Tp07Fv3z5ER0cjISEBFy5cqLD9jh07MGjQIIwYMQKpqalITExEYmIi/vjjD0eb/Px8dOnSBW+++Wal7/viiy/im2++QVJSEn744QekpaXh4YcfdjxvtVrRt29fmEwm7NixAytWrMDy5csxbdq0m/fhFcrHoMUz3RoBABZs+Qtmq636J+vzFqD3A9JSgZ1LblIPiYiIiIjuXC4tEhIbG4v27dtj0aJFAACbzYaIiAiMGTMGEydOLNd+4MCByM/Px/r16x3HOnbsiJiYGCxdutSp7cmTJ9GgQQOkpqYiJibGcTwnJwe1a9fGypUrMWDAAADA4cOH0bx5c6SkpKBjx47YuHEjHnjgAaSlpSEkJAQAsHTpUkyYMAGZmZnQ6apWpfB2KxJiV2Cy4J6523Exrxiz+0fhn7H1qn+yvSuAb8YCGg/g+R1ArYY3r6NERERERLeJqmYDl42gmUwm7N27F/Hx8aWdUakQHx+PlJSUCl+TkpLi1B4AEhISKm1fkb1798JsNjudp1mzZqhXr57jPCkpKYiKinKEM/v7GI1GHDx4sNJzFxcXw2g0Ot1uR546DUbdK0bRFm49iiKztfonu3sIENkVsBQC34wT69SIiIiIiKhCLgtoFy9ehNVqdQpBABASEoL09PQKX5Oenn5d7Ss7h06ng7+/f6Xnqex97M9VZs6cOfDz83PcIiIiqtwvpRnUoR7C/Aw4n1OEVbtOV/9EkgT0+zegMYiqjqmf3rxOEtW0rOPA6V9d3QsiIiJyIy4vEnInmTRpEnJychy3M2fOuLpL1WbQqjH6vsYAgLe+/wsLtxxFbpG5eicLbATcO1n8/P2rQG7G1dsTKUFeJvCfHsDHvYBze13dGyIiInITLgtoQUFBUKvV5aonZmRkIDQ0tMLXhIaGXlf7ys5hMpmQnZ1d6Xkqex/7c5XR6/Xw9fV1ut3O/tE2Au3qByCv2IL5yX+hy5vbsGjrUeQVV6MiY8dRQFg0UJQDbHyl4jbmIuD4D0DqZ0DBVTbDJroVNk0s2ZRdBlIWu7o3RERE5CZcFtB0Oh3atm2LLVu2OI7ZbDZs2bIFcXFxFb4mLi7OqT0AJCcnV9q+Im3btoVWq3U6z5EjR3D69GnHeeLi4vD77787VZNMTk6Gr68vWrRoUeX3ut3pNCqsfiYO/34sBo1qeyGn0Iy3vv8LXd7cisXbjl1fUFNrgAcXAZIa+PNr4NB6wGYDzv8G/PJv4JNE4M36wCcPAl8/D7wXB/y9tcY+G9FV/fUd8MeXgFTyn8iDa4Hs23dEnIiIiG4fLq3iuHr1agwdOhTvv/8+OnTogAULFuCLL77A4cOHERISgiFDhqBOnTqYM2cOAFFmv1u3bnjjjTfQt29frFq1CrNnz8a+ffvQqpXYCDkrKwunT59GWlqao03Tpk0RGhrqGP167rnnsGHDBixfvhy+vr4YM2aM4/yAKLMfExOD8PBwzJ07F+np6XjiiSfw1FNPYfbs2VX+fLdrFceKWG0yvvktDe9uOYrjF/MBAAGeWjzbrRGGdY6EXqOu2ok2zwB+fgcw+ImwVnjFSJl3KKDRAdkl6946Pg/0mA5oDdc+t7kQUOsAVRX7QlSR4lxgcUfAeBboNAZI2y82Xu80Buj5uqt7R0RERLepqmYDlwY0AFi0aBHmzZuH9PR0xMTE4N1330VsbCwAoHv37oiMjMTy5csd7ZOSkjBlyhScPHkSTZo0wdy5c9GnTx/H88uXL8fw4cPLvc/06dMxY8YMAGKj6pdeegmff/45iouLkZCQgPfee89p+uKpU6fw3HPPYfv27fDy8sLQoUPxxhtvQKPRVPmz3UkBzc5itWFdSVA7eakAANCothdmJbZCp0ZB1z6BuRBY0hnI+ls81vkAkV2Aht3FrXZT0SZ5GrD7P6JNcEvgkf8AIS0rPt/hb4HfPhcjbioN4F8fqNUACGhQ5r6hWAvH8EbXsuH/gF3vAwGRwHMporjN5wPFnn7jDwJ6H1f3kIiIiG5Dt01Au5PdiQHNzmK1YU3qOczddBgX80wAgMSYcLzatwVq++iv/uKsE8CRjUCdu4E6bQG1tuJ2f30vpjvmZ4qRsfgZQOxzojLk6RQRyg6uBYqruJ1BQCRwzytA64GVv+fNcnYPkPEH0Ph+wK9Ozb4X3TxndgEf9QQgA0+sBRrdK6biLm4PXDoG9HoT6Pisq3tJREREtyEGNAW4kwOaXU6BGW99fwSf7jwFWQZ8DBr8X0JT/DO2PtQq6cbfIC8TWDcG+GujeFy3A5CXAWSfKm3jVw+Ifgxo/Sig0YvS6FkngMsnSu8vHQfMYmom/OuLoBb92M0PajlngeTpYv0SINYwNekJtB0mwpq66iOw18VqFiOJIS2BoCY18x53OosJeL8rkHkYiBkMJL5X+tzuD4FvXxLXzthUjsQSERHRdWNAUwB3CGh2v53JxpS1f+D3czkAgNZ1/fB6Yiu0rut/4yeXZWDvMmDTZLHhNQDovIEWiUDMIKBeJ0B1jXo3pnxgz8eiIEl+pjjmXx+452UgelD5oGYxAfkXgNx0QOcFBDW9+nuYCoAd7wI/LyjpowSEtAIyfi9t4xMGtHkCuPsJwL/edX4JV3H6V2D9i8CFP8W6vvZPAd0nAp61bt57XC/7f1akmxDSb5XtbwLbZwNetYFRu5y/P1M+8E5LoPAyMPBToHk/1/WTiIiIbksMaArgTgENEIVEPtt5CvM2HUFuSYXH2Aa18M/YekhoGQqD9gZHHS4eFSMZddoCzfqK4HS9TAUlQW1BmaBWD6jfRYzM5WUAueeBgkvOr/MMAhrcAzTsBjToJta2ASKI/PE/MWpmPCuO1esE9H5DbCtw8SiwbwWwf2WZc0pA4x7A3UOAu3qLoijVUZAFbJ4O7PtEPNZ6AmaxLhAeAUD3yUC74Tc2Sph/UXxG79pVa5+bLqaepn4qRhPbPwV0nwTovavfh1vhwmFgaRfAZgYGfAy0eqR8m82vAT+/DdSLA57cdOv7SERERLc1BjQFcLeAZnchtwhzNhzG1/vPwVZydQV4avHI3XXxWId6aBysgF/WKwpqV1JpAO8QMWpiDz52/vVEULt0TKyHAwC/COD+mUDL/uVHjizFwOH1wN4VwIkfSo97BgKtHwPaPA6EVHELB1kGflslNv22h742T4j3Tj8AbJokRtMAMfLXazbQOP7q5yzIElP7LhwSt8zD4hz28wfdBUR2BRp0FfdeZQrCWM2iLH3qp8DR7wHZ6nxuvwigzzygae+qfb5bzWYDlvUCzuwE7uoFDFpV8cif8TywIEqEuKe3ij8UEBEREVURA5oCuGtAs0vLLsQXe85g9e4zOJ9T5DjeoUEtDGhbF41qeyHYx4BgX33Vy/TfbKYC4MBqoOCimILoHQr4hIifPWqJaY2WYlH048SPIlyd3Q3YyuwBp/UEurwoyrBrPa79npf+BlL/C+z/HMhLLz1ep60Iaq0eEdsQlCXLgM0qAuG3LwGnfhbHazcHHngHqF9mL0CrRYzabftXacBq0hO4KwHIvyQCadlb3gWgKLuSztqDyhX/mQhuKcKaSgMc+EJMB7WL6Cg+h0eACIs5JVsmNHsA6D1XeUVTdv0H2PCymDY7aifgV7fytmueAQ6sAloNAAZ8dOv66ApWC/DjXBHW+74DeAW6ukdERES3NQY0BXD3gGZntcnYfuQCPt91GlsPX3CMqpXl76lFSElYC/U14K4QHzQL80GzUN9rV4W81YrzxLqvE9sBSEDss9ULHVYL8PcWMUXxr02loU+lAdR6MRJls4p72eb8Wo0H0H0C0HFU5VMkC7OBH+cBO5c6B8rK+NUDgpsBtZsBwc3Ffe2mIqCe2iEC6smfSkfnyvIKFkVX2jwB1L6r9LgpH/jhTSBlseiDzhu491Wgw8iaK5hSVQVZwPY5wO6PxHfc5y2gw9NXf83534D37xFr/V44cPUwdzsryAKShpWO9kbEAkPWVW0/QiIiIqoQA5oCMKCVdz6nEKt3n8HPRy8iI7cIGcZimCy2q74myFuHZqG+aBbqg2ZhvrinSRCCfe+wXxTzMsXIzL7/AhePXL3tXb3ESFRA/aqd++IxsTl4UbaYmuhVu/zNr07V9/fKyxRB7eRPIqy2TBQjdFdb65ZxEPjmBeDsLvE4tDXQfoT4LD6hlb+uJlgtoujMtn+J6asAEPUo0P/9axebAYDlD4jP3nmcmFZ6q1w8Bvw0X0yFbTvs+vZjy8sUgdgj4NptM/4EVg0CLp8EtF7iDwbFOUDLh4FHPqrad0RERETlMKApAAPatcmyjJxCMzKMxcgwFiHDWIRz2YX4KyMXh8/n4sSlfFx5hUoS0CGyFh6IDkevlqHKG2G7EbIsimvYLKKUu6R2vlfrlF9wozI2m5h6uXk6UJRTejz8bqBpH7FGLaRl+fVfBVml2yVknwYMvqICp18E4B9xfcVijm8HNk4EMg+Jx8EtgF5viOIvVXVkI/D5YyUbV/9Z8b+HLIvbzQgzNpvYOHvza6VVTA3+QMfnxEhkZdU6bVaxNnDPx8CxzSJoRf0DiBsFhLaq+DWHvhHTOM354jse9LmYJvvfh8Xau64vAT2m3fhnolurOE9Mv+b2EERELsWApgAMaDeuwGTB0Yw8HE434tD5XKSeycZvZ7Idz6skoGPDQDzQOhy9WoWillc1KyLSrZN3QRRL+WsjcG6v83N+EWJzaFN+yX52x53DXEU8A0vDmldtEV4MfoBHyb3BT0wZ/fU9UagFECNJ900B7h52/VMtbTZgUTsg628xkhn7jDh28YiYCno6RdznpgMtHhTTUCPaX9972F0+CXw9WozYAUD9zqLS6KVj4rHWC2j/JBA3unQkMjddTJvdu6K0suiVGnYH4saIaqKSJPr/4zyxzQAgCuD8Y3lp+Nu/Elj7nPj5wUViqwhSJlM+kP47kJZaert4VIyeD/hYVKMlIiKXYEBTAAa0mnH2cgE2/H4e3x44j9/Olv7yrlZJCPMzoLaPHrW99Qgqua/to0eQtx4Bnlr4GLTw9dDAx6CFj14D1c3YTJuqLzddjPIc2ShGt+wjRFfyCQMCGojqmUU5QM4ZIPuMmHp3PSS1WGfWbcKN7RNnLyziWwcIiwFO7yidLlmRuh2AuOeBZv2qFghlGdi7HPh+CmDKE0Gs50yg3QixHvHPr4Gf3i7dZ0+tF3sCFmQBRzaUrjn0qAW0GQy0HS7WJKYsFK+1r2ms3Qzo+DxwLFmMngFA7HNAz9fL93Prv0TREJUGGPylCNKkDOm/i+vl1A5R1OXKNat2Kg3Q922g7dBb2j0iIhIY0BSAAa3mnb5UgPW/p+HbA+dxMM14Xa+VJMBbp4GvhxYhvno0rO2NhrW90DDIG42DvVCvlhd0Gq63uWVMBaIoxelfxV/7AxoAtRoCAZGAzrPi1xTliKCWfVqEtoIscawou+Q+RwSTohwgNAqInyEKodxwX/OBt1s4V7/UegJ12wP1O4m90vQ+ogDJ718AVpNo41cP6PisKKZiqOS/CTnngHVjRAEZQOyrl7hYfBdlybLY1uDHt0rX9tlFdATaPQm0eKh8YY/Lp4Cd74vppqa80uNqnagI2ubxivsly8Cap4HfkwC9LzDie1FM5laxj1Lmni/5N82+4j5HfEetB96cf+OKmIuAtH3iGj2zU1RBbfO4+Pe8kf0Gq8NSDPy5TuwNeeZX5+e8Q4HwNqW34OZiavEf/xPPx40W6yc55ZGI6JZiQFMABrRb63xOIdKyC5GZW4zMPBMyc4txMa9YPM4thrHQDGORBcYi8zULkwBiRC4iwAPBPgZAEtMpVZIEqeQeAPQaFXwNWvh6aOHnUXrv56GFv6cWgV46BPno4aPXQKpoby26fR1aDxxcI0bQ6ncSG5NX9Et6bob4JXrPR6XbHmgMIuQAV6y5k0TgsBSJNj2miRGtq61lk2Xg1C9iSqOHP3D30MrXmJVVlCNes/N9ALKY0hjR4eqvsRQDnySKEUO/esBTm8W2FIAovmI8J6ZlXj4pRkdVakCjFyN8Gl3pvcZDFKYJaFB5UAVE8D6+veT2g9gOoyrCYoDoQUDUAOc9++xM+SWVWH8Q1UnzMgHvYDFN1DvE+d5mEWHs9E4xXdBmLn++gEhRnbTVIzUferLPiCI3+z4p3cNRpQGa9xNrDMPvBnzDyr9OlkVF1e1zxOO7egOPfHj7rmklciVTAfD3ViCyc9WKLxGVYEBTAAY05SoyW5FbZEFukRk5hWacyy7E8cx8HM/Mw98l9/km67VPVEU6jQpBXjoEeusR5K1DkLce4f4eqOPvIe4DPBDmZ4BBy79o37HMhWLPvZT3rl2ps047IHGJ85YFNUWWxZS4qgaLgizgw3ixBi/oLjHN8/JJMYJZle0cruQZJEa+apWMmPqEAef3i1CWddy5rdZLtDP4ibWGHv6law713sDJn8WoYtktKxrfL7aA8A4WYey4fS/DCoJWVXgFA/U6iptsA375d2lQCm4B3DdVFLy58g8yNqtYC3Z+v9gLMaID0PDeqk15tVlFoZe9y8WWHPYpjD5hYvrq3UMqDmUV+f1LYO3zgLUYCIkShWD8I6r66Yno4jHgiyHAhYPif4MPLRbreYmqgAFNARjQbl+yLONCbjH+zsxDdoFZ7BMty7CV/M/FJsuw2YBiiw3GkpBnLBT3OSUjddkFJlzKMyGvuOq/tAZ56xDuL8JamJ+4Dy3zs0s39aabw2YTRT7s0x4BOG0ErtKK4KPkcvaX/hYhrTDL+bhaJ6o/BkQCvuEiSFhNYuSt7L0pT4yO2UcUKyOpgbrtRFGThveKzdwr2/fPLv8i8Mca4LfPxXTEyvjWFdU7G3QTwTD/ghj1y8twvrdZgTp3i2mr9WLFqF/Z8FWcJ/Ya/OXd0jWRddoBXccDxbklhTr2i3Vi5nznPniHiFGvmH+KCqZXyj4NpH4qbsZzpccbdAPaPyWCYHWmVp7ZDaz6p/jMXsHAwE9FYOQoP9HVHVwrCjeZcp2Pt39KTBu+nqrC5JYY0BSAAY0AMVp3Ma8Yl/JMjvsLuUU4l12EtOxCnMsuxLnLhSg0V23EztegQWBJ0ZNaXjoEeOpQy1vcA0Cx2YZiixXFFhuKzOK+2GKDt16NEF8DQn0NCPET96G+Bvh7ajn9kq5fxkHg8AYRxAIixc0n7PqCZVGOGH3LOl66lULOWRFQG3YXVSuvNgXyWjKPAL+tEqNGliIgsktJKLunfNC6UYWXRUjbuRQwF1TcRusp9gAMqC9GxMoG1NAoIPqfYl/Bs3vEGsFjW+AI7x61xLTNtsNuzshq9hmxXUTGH6XnD2kpRgGDm5f83Lzq++3lnAPO7RGVWc/uFVtZqDSivL/W0/leYwCsZlEUyFIsRpctReLeahLXVGhr8Z2ERYs+VbYO9UpWC5CXLvqTc0ZcT8ZzImjXbipuQU3F9FX+d4+qymICkqcBO5eIx/U7Aw8tAn5dAuz6QByr1Ujsp1ndqr23miwDKYtFdeN7XuEo4C3CgKYADGhUVfb94M5eFuvo0o1FOJ9ThPScIpzPKcT5HPG4Kmvnrpdeo0ItLx08dGp46TTw1KnFTa+Bl04Nb71YTxfgqYW/p67k59J7T52aAY/ILjdDbFlwZKOYOhgWA4THiPugJqVTSS0mEdJ+Wwkc2VT5lMsG94h1hc37ifV8N1NxrihIU7ay55V8wkXF07JTSu33EsTo4Lm9onhLTZFUQGATEdg8/EWxFkuhCHRlw13BJcCYBshV+GOX3q80sNVqINaE6rxEiNR5i591XiJM2s9vKSzz3kXi30zvK74fj1ql9/bCPOYi8UeHS8fEqLP9Pvu0WINZpx1Qt624969XcWC0FIvXZR4GMv8Sf9SQbeIzyjYRPGWb+GVbrSndWsQ+Ddix1YhWrJsy5YsRbFO++EOCKU+MVIdFi5Fig9/N/Je7eS4cFgWKIIv1k3Xa3rpZBjlngaRhYmo0AHQeB9w3rXR68t9bgbWjgNw0ca12GS8qBV9rtP9mslrE9VPVqeqFl8VU5yMbSg5IYtS/++Tr33rmVigyisJZsk38+1f1DzYKxICmAAxodDPJsozLBWZk5RcjK9+MrHwTsvJNuFxQcp9vAiTAoFVDr1FBrxH3Bq0aOo0KuUVmZBjtoU9sCn65oJrrcMrQqVUI8BJhLcBT5/jZW69BodmK/GIrCkwW5JusKCgW98VmK1QqCRqVBI1aglqlEj+rJLFez1tfMs1TTO8M9TMg3N8DARztoztRQZaosPjbKjEK5RUstkdo8wQQ2Kjm399cKEYbL/wpRkYvHBI/X0/oklRAcMvSwBHWWhwzF4og4HRfKAKDxkOEmbL3ao0YTU0/AJw/IO7ta/yqSqURo3B+EYBfXbFOErIIOJmHRWiqLJDeDPaQl58Jp+nLV+MVLKbz1rlbBLvMw+LfJOt41QLnTSGJwFq3XUl4bC9GUa/1S7/VLCqpFl4Wt6JsEf69Q8QfJbxDqjdaWWQUhZhSPy0NR3beIWKKb7MHxB8xbvYfL+yObRHVawsuiVDffwnQrG/5doWXgY0TxDpjQIwA3/sq0KBrzU17zMsUW6T8tQk4tlVcJx1GigB5tW1k0vaLNXTZp8S09EY9xL6kgJjK/chH4g8IrmY8LwLk4W/F+mH7H7EMfmK2Qbvh4nq9zTCgKQADGildkdmKC8Zi5BSaUWCyoMBkRX7JvT1M5RZZkFNowuV8My4XmJBdYEZ2oQmXC6pWDfNm0mlU8NSpoVGpoFWLcKdVqcS9WgWdRgUPrRoGrRoGrQoGjRp6rRoeWjUCPLUI8/dAeMm6vnB/j0qLshSZrSVVP80wWeSSEUU1PHUaeGjVUHP/PKopBVliWuGtLttfWV8un6hkW4NsMQoY0lL8Qh8WXXO/iOami7CW8bsIL45QV+am8RDV9PzqioIwVwsV5iJR5MYegnLOlows2UeX8kofW4rFKNqVQVLrIYJgUY5Yi1mQJX5JvzJM6X1FyA5sLKbABTYWI6tZJ0QYP7tHTDO9WoEdva/Ys7B2U8CrtvhskkqMfEkqMZIkqcS/R7HReZsR+81iKhkVvGKEUOsl1kae2ytG9q6k0opf4lXqkvctcw+I9yu7XUdl/bd/B4FNgKDG4nPovMW1rvMWRX60JdfPqV9EKPvz69K9MSU1cFcv8f0fTRbva6fzFtPzwmJEX4qMIiAWG0t+Noo+h7Yus/VEi/IjXLIspsOe3SMC4bm9otorZPHaRz8Ro61Xc3AtsP7F0vW5ap0IPY3jxS24uXNYLcwGzv8migelpYrrXJJK1vLWL70PiBQ/G8+JQPbXd6KfFf0BQO8LdBoDdHzOeYqyfX/NjRNEkSD/+uIzhceIdbvrxoq1dR61gP5LgbsSrv5Zq0uWxai0pah0RNo+1dlcKLYNObxB/O+jrKC7xGvKXqeRXUVQa9bv1o5Y3gAGNAVgQKM7mSzLKDBZHaHNPpp3OV+Et/xii9NUSQ+duPfUa2DQqGCTAatNhtlmg9Uqw2KTYbXJKLZYkWEsRnqZqZ3nc4pwMa/4pn+GAE8tQv08YNCqSoq8VG0bBoNWBU+dBn4eWtSr5YkGQV6IDPREZJDYR69OgAdDHJG7sdlEGCjMEsHAt47Y5uFao0fmQvGL+bk94pd0nVdpIKvdTKztvBUzB/IuiF/6z9kDSmr5YhiVksR6UY8AMbVS5w0Yz4pfpqs8WimVTCktLD0U1BS4+wmxv6F3sDhmMQEnfxIjK0c2VG96rVoHhLQSYc1eObayqbp3DwV6zy2/p2RlctPF/pR/fQfkXBF6fcKBRveK0eS0/eIPIDcitLUIrnf1EkV/tr5euq7UMxDo8qIoYCLbgPXjgQOrxHNN+wCJ7zlvEZB1HEgaLr4LQIS8HtNv7I9FNquYomsvlpSWWnHBpMrUbS9GLJv2FWtvbTYxpXTPx2LUz35teQaVFE3SlRwrqU5sn/4r28T3ULdd9T/LTcKApgAMaEQ3T7FFjPYVW6wwW2VYrCLcmS02WGwyzFZbaWEUsw1FFisKTVYUmW0oNFuRlV+M8zmiMMv5nCIUXGMbBZUE+HpooVWrUFgysljV/1pq1RLC/DygUUuQIPbNs++hJ0mSY089lUr8rC7zs1atQpifAZFBXogMLLkFecJT57wuQJZlZBeYcaFkn7/MvCLoNWqE+OoR7MOKn0R0g2xWEVis5pK1blbne8hitMYjQEw7q2jU0lIsfvG/dExsM2Ffh1d4WYx2FeeJEFg2xOl8gKhHxBTfOm2vHk5tNuB8qhhxMZ4T/TH4inu9T8nPfiIQ2ANCWqoYZayIpAZCWohgUKcdEBErRvyqQ5bF5z22WdxO/ixGgK7kX790nWpYtBiZzT4FXD5Vcn9S/Jx/QYzeNuwuRrea9Cw/FdFmA/78Ctg2W7w3IAKo3ge4+Jf4fPHTgU5jK1/zmDxNFDsCxL6KkV1ESFNpRd/UmtKfbRYx9dBqv5lKCwBdOCxGB68WxiRVmZHpkluthkCzPiJE+oRW/tqcc2I/yH0rqhbSH/lI7I3pYgxoCsCARqRMsizDWGjBeWMhzmcXwWS1iY3GDVr4eoiRMS+dBqoyo2CyLKPYYhPTQIstKDRbcSnPhJOX8nHyYj5OlNxOZRXUyNTPEF896tfyQrHVhkxjETLzimG2Xv0/3wGeWkdYC/LWOzZQt9/7e+jg66GFt14DdckaQLVjXaAEjUoFtSQBEhwbtNsDp/3/281WmyMsW8oEZ1kGannp4O+hdfoeiYicyLIYRbRPL/UJE1NIa/L9Lp8sDWu56UBoKxHKanKqrrkQOLVDBDW9T2kou9p6sbJMBSIEV2W9ndUithr54U1RzRQQ6/YGLBOba1/LofXA18+L6bE3yl69NjxGjFiGxYg1ovZpwjc6Omy1iGmf6QdKpv6qSs4plXmsEqFWAWvWGNAUgAGNyP1YbTLO5xQiPacIVpsMGWLfPFmGYz89qyxDLtlLzyrLsNlkMeVTlmGy2HD2coEIfZfEfU5h5cVcAjy1qO2jR20fPYrNNmTkFiHDWHzL1wdWRqOSEFiyObv9Fuitg9UmPmuxxVpyb4PJYoPJaoNeI6aQepWs+/MqM1VWry0tfmMvhmPQinuVSnz/csn0WfvehVYb4KVXo46/B/w8WGiGiNyEpViMMmUeEaX0fUKq/trs00DqZyI0W81lRstK7m2WkjWK9puuzGOdGAkLjynZ15OzOewY0BSAAY2IbobL+WKk7nRWATy0agT7GlDbR48gb12F0xjtI4QirInKnfa1gjmFZmQXmpFTUuwlp9CMgmIrrLLstBbQYrPBdh3/7yBJcBRs0agkyAByi6q+Sfut4qlTI9zfA+H+Hqjjb0C4nwf8PbWw2mRYZcBqE1Nm7d+FSpLEaKNnaaVSf08tArx08KrmFhNWm8w1ikREbogBTQEY0Ijodmaz2Uf7ABmlo4AyZEd406hEBc2KAofJYsOl/GJczBWbtGfmFeNiXjEu55ugVqmg14jKm3rHTQ2tRkKx2ea0LUOByeLYrsG++XrZTdiLLWKtoSyLtYNqVemaP/vPuUVmXMwz3dTvR6OSRNVQnbqkemhpFVGdRlXyOSwoNFlFZVSTmBprtsrw0qlRy1uHWl56BHrpUMtL57jXqkv3d7LnP/u3qyr5PCpJglqFMj+LfwfH6GJJFVP76KJBp4K3XlQh5QgiEZFrVDUbKHA3OiIiUgKVSoIK1f9lXqdRIczPA2F+Nbie5DoUma2OQjHnssWm8GnZhTAWWqBWl67BU0ul6/CsNlGMxT4CebmgdIsJi01GbrEFucXXP1KYb7IiP6sQZ7IKr934JlJJgJdeA2+9Bl4lN71GBYvVXmxHhsVqc1RYlSCVrln0FGsK7T/7eYj1jD4GjWP9po9BCx+98/pN+3RW+xRWs9UGleS8TYb9Z65XJCJiQCMiIjdh0KrRIMgLDYJurAiALMsoNFuRU2gWVUJNVhSarSgquRWWVBL10KnhoVPDU1uyh55ODU+dWDtnLLIgK78Yl/LERvOXSjaez8o3wVIyPGmf4OKY5lKyhtG+rk4uWc9ok8Vop6mkkmlxST/KjjTaq5baZDH1tCann0oS4KlVO9ZUXs9UWbVKgpdODT9PUbTHHgL9PLTw9dDCoFFBKhkxVKtKRklLHquksgVuyj5WQSUBUpk/NpQdRNSpVajto3cU0yk7gklE5AoMaERERNdBkiR46jTltj64HoHe+hsOitfDZpNRYBYVSPOKLWXuRZEW+9pBjVoFbcm9mLYqI6fQjMv59rWLJmQXmh2jiblFYu9AY6EFuUVmFFvEVNP8q2xjoVOrYJNlRxAty2qTYSyywFhkAXBrRxcBEdwCvXSo7WNAiK9eTDlVqaBWS44g6AiAKhH5pJLwV1LwFCjZSsNbr4Fvmeqw9sDpYxBVU+2f3rHQpOxUYpQtLiRCuAwZaklMZdVpVNCqVdCqJU5ZJboDMaARERHd4VQqCd4lUxuvo47bdSsyW5FbJAKgWiVBXxIkdCXrDTWq0kAhyyVTKm02x9RKs1VGXrEFOYVmGAvNMBaJwjY5JQVuTCXTL+2jhvYqqFZZdlTutFjthW7EvbXk+av1+YJRrJG02mRczDPhYp4Jh6qx/7Er6EqCmkatKp2mWyZI2tcn2qe1inu101RXz5J1lPZRXg+tGPH10KrLrXVUlUwDliSg2Fy6BrTIYnXsQ2my2uChVcPHUDLt1aCBj0FTbvuSm8Fqk3EmqwBmqw0RtTxh0LJiIN3+GNCIiIjopjCUFEmp7XPtvZokSYJOI0EHZUwptNlkZBWYkGEsEhvAG4uRVWASYc9qD4FirZ6tJADac1/Z6ahyyZYZ+cWWkpDpHDiLzFXfAsM+KmcvemMr2UKiLJPVBjFgWfmopVJIJSOLeo0aupJQqVVLJaOBYj2iv4cWIb4GBPuKUcwQHwNCSn7OK7bg6IU8HM3ILbnPw9+ZeSgu2VZEkoA6/h5oWNsbDYO80LC2mNIc5C1eayw0l/m3EI8LzFbo1GWKFTm28LAXMVI7ihmVfXxlMBaj0KXHqlvllQhgFccaxSqOREREVJZYlyd+9Sqt0ik5Hts3hJckVPgLvtUmw2wVo1Qmiyi6YraINYjOI4g2x0hiscXmNL1V/CymvOaXVEctKKk2av+5sORn++jklfsL2mQ4goyh7P6EWhG+CktGU8XNDLO15n7dtIcnJW3toVVLCPTSX7EPpPjZJouR4rxiC/KKxL+BfeRZrxF/4Agu2d8y2FePYB+xtYqnTg2LVfz7lx19NlttkCAKAHno1PDS2e/V0HBNpaKwiiMRERGRwug0N/YLs5i+qL6tpvLJsgiJxiIzcosspcGyJFzYQ4fJakN2gQkZxmJkGItKbuLni3nF0GlUaBzsjbuCfdA4xBtNgn1wV4g36gZ4QiUBl/JNOJ6ZjxMX83A8Mx/HL+bjeGYeLheY4WvQOIrNiHWBYm2gh1YNs9VWMl1TTNk0lWzhUWS2OoJwseXKeyssJaOrFput5L40hJqtMtKNRUg3FrnwmxdTYPXa0nq8UsloLICSPwRIju1Syo4I2tc5epYEPjElVu2o/uqlU5ffXqXkxBIAH4MGgV5iHWegt9hD8sprXy4JqvbRTGOhGTZZ7FfpaS+ypNM4iitdbUTSYrWVjJKWjFgXlY5aGwstiG8RckvX/d4oBjQiIiIiqjGSJDmmvwb7VO8clpLtGa62hs0+UtWhQa1q9vTGyCWjjWarjMsFYv9HcSv5OdeES/nFUEsSvA2lawB9yvxcdk3kBWNRyX0xLuQWo7BkOmbZ6ZT2qaGyDBSYLI6RUPtUWFNJ8FUCX4MGgd76kmJApYGsKiQJosJqScEcAI6COkD5qb9XCvM3MKAREREREd0st8NUPalkaweNGvDQeSDc3zV7QMqymPJaaLIi32RFsVmsT7SvkYTjkVjXWHYUs3TqpBgpLDBZy02JFfdWlF0lVXbBlE2WYSy04FJ+sWP7EJuMMhVanenUqpKRTQ0kCSg0WVFgFtNs7esLZVlMD74WT53aUTHVXj3V10OLUF9Dtb5LV2FAIyIiIiK6Q0iSBL1GDb1GDX9PV/dGFODJKTQ79ntUqyT4lQlPV5uua7WJfScLTBaYrbLT1hZAaSEdjVoFH4PmjtnHkAGNiIiIiIhqhEolIcBLhwAv3XW/Vl1mixB3cmfETCIiIiIiojsAAxoREREREZFCKCKgLV68GJGRkTAYDIiNjcWuXbuu2j4pKQnNmjWDwWBAVFQUNmzY4PS8LMuYNm0awsLC4OHhgfj4eBw9etTx/Pbt20vKjJa/7d69GwBw8uTJCp//9ddfb/4XQEREREREBAUEtNWrV2P8+PGYPn069u3bh+joaCQkJODChQsVtt+xYwcGDRqEESNGIDU1FYmJiUhMTMQff/zhaDN37ly8++67WLp0KXbu3AkvLy8kJCSgqEjsRdGpUyecP3/e6fbUU0+hQYMGaNeundP7bd682ald27Zta+7LICIiIiIitybJZWtkukBsbCzat2+PRYsWAQBsNhsiIiIwZswYTJw4sVz7gQMHIj8/H+vXr3cc69ixI2JiYrB06VLIsozw8HC89NJLePnllwEAOTk5CAkJwfLly/HYY4+VO6fZbEadOnUwZswYTJ06FYAYQWvQoAFSU1MRExNTrc9W1d3CiYiIiIjozlbVbODSETSTyYS9e/ciPj7ecUylUiE+Ph4pKSkVviYlJcWpPQAkJCQ42p84cQLp6elObfz8/BAbG1vpOdetW4dLly5h+PDh5Z578MEHERwcjC5dumDdunVX/TzFxcUwGo1ONyIiIiIioqpyaUC7ePEirFYrQkJCnI6HhIQgPT29wtekp6dftb39/nrO+dFHHyEhIQF169Z1HPP29sb8+fORlJSEb7/9Fl26dEFiYuJVQ9qcOXPg5+fnuEVERFTaloiIiIiI6ErutalABc6ePYvvvvsOX3zxhdPxoKAgjB8/3vG4ffv2SEtLw7x58/Dggw9WeK5JkyY5vcZoNDKkERERERFRlbl0BC0oKAhqtRoZGRlOxzMyMhAaGlrha0JDQ6/a3n5f1XMuW7YMgYGBlYausmJjY3Hs2LFKn9fr9fD19XW6ERERERERVZVLA5pOp0Pbtm2xZcsWxzGbzYYtW7YgLi6uwtfExcU5tQeA5ORkR/sGDRogNDTUqY3RaMTOnTvLnVOWZSxbtgxDhgyBVqu9Zn/379+PsLCwKn8+IiIiIiKi6+HyKY7jx4/H0KFD0a5dO3To0AELFixAfn6+o2DHkCFDUKdOHcyZMwcAMG7cOHTr1g3z589H3759sWrVKuzZswcffPABAECSJLzwwgt4/fXX0aRJEzRo0ABTp05FeHg4EhMTnd5769atOHHiBJ566qly/VqxYgV0Oh3atGkDAFizZg0+/vhjfPjhhzX4bRARERERkTtzeUAbOHAgMjMzMW3aNKSnpyMmJgabNm1yFPk4ffo0VKrSgb5OnTph5cqVmDJlCiZPnowmTZpg7dq1aNWqlaPN//3f/yE/Px8jR45EdnY2unTpgk2bNsFgMDi990cffYROnTqhWbNmFfZt1qxZOHXqFDQaDZo1a4bVq1djwIABNfAtEBERERERKWAftDsZ90EjIiIiIiLgNtkHjYiIiIiIiEq5fIrjncw+OMkNq4mIiIiI3Js9E1xrAiMDWg3Kzc0FAO6FRkREREREAERG8PPzq/R5rkGrQTabDWlpafDx8YEkSTX+fvaNsc+cOcM1b1RlvG6oOnjdUHXx2qHq4HVD1aG060aWZeTm5iI8PNypCOKVOIJWg1QqFerWrXvL35ebZFN18Lqh6uB1Q9XFa4eqg9cNVYeSrpurjZzZsUgIERERERGRQjCgERERERERKQQD2h1Er9dj+vTp0Ov1ru4K3UZ43VB18Lqh6uK1Q9XB64aq43a9blgkhIiIiIiISCE4gkZERERERKQQDGhEREREREQKwYBGRERERESkEAxoRERERERECsGAdodYvHgxIiMjYTAYEBsbi127drm6S6Qgc+bMQfv27eHj44Pg4GAkJibiyJEjTm2KioowatQoBAYGwtvbG4888ggyMjJc1GNSojfeeAOSJOGFF15wHON1Q5U5d+4cHn/8cQQGBsLDwwNRUVHYs2eP43lZljFt2jSEhYXBw8MD8fHxOHr0qAt7TK5mtVoxdepUNGjQAB4eHmjUqBFmzZqFsvXseN0QAPz444/o168fwsPDIUkS1q5d6/R8Va6TrKwsDB48GL6+vvD398eIESOQl5d3Cz9F5RjQ7gCrV6/G+PHjMX36dOzbtw/R0dFISEjAhQsXXN01UogffvgBo0aNwq+//ork5GSYzWb07NkT+fn5jjYvvvgivvnmGyQlJeGHH35AWloaHn74YRf2mpRk9+7deP/999G6dWun47xuqCKXL19G586dodVqsXHjRvz555+YP38+AgICHG3mzp2Ld999F0uXLsXOnTvh5eWFhIQEFBUVubDn5EpvvvkmlixZgkWLFuHQoUN48803MXfuXCxcuNDRhtcNAUB+fj6io6OxePHiCp+vynUyePBgHDx4EMnJyVi/fj1+/PFHjBw58lZ9hKuT6bbXoUMHedSoUY7HVqtVDg8Pl+fMmePCXpGSXbhwQQYg//DDD7Isy3J2dras1WrlpKQkR5tDhw7JAOSUlBRXdZMUIjc3V27SpImcnJwsd+vWTR43bpwsy7xuqHITJkyQu3TpUunzNptNDg0NlefNm+c4lp2dLev1evnzzz+/FV0kBerbt6/85JNPOh17+OGH5cGDB8uyzOuGKgZA/uqrrxyPq3Kd/PnnnzIAeffu3Y42GzdulCVJks+dO3fL+l4ZjqDd5kwmE/bu3Yv4+HjHMZVKhfj4eKSkpLiwZ6RkOTk5AIBatWoBAPbu3Quz2ex0HTVr1gz16tXjdUQYNWoU+vbt63R9ALxuqHLr1q1Du3bt8I9//APBwcFo06YN/vOf/zieP3HiBNLT052uHT8/P8TGxvLacWOdOnXCli1b8NdffwEAfvvtN/z888/o3bs3AF43VDVVuU5SUlLg7++Pdu3aOdrEx8dDpVJh586dt7zPV9K4ugN0Yy5evAir1YqQkBCn4yEhITh8+LCLekVKZrPZ8MILL6Bz585o1aoVACA9PR06nQ7+/v5ObUNCQpCenu6CXpJSrFq1Cvv27cPu3bvLPcfrhipz/PhxLFmyBOPHj8fkyZOxe/dujB07FjqdDkOHDnVcHxX9fxevHfc1ceJEGI1GNGvWDGq1GlarFf/6178wePBgAOB1Q1VSleskPT0dwcHBTs9rNBrUqlVLEdcSAxqRmxk1ahT++OMP/Pzzz67uCincmTNnMG7cOCQnJ8NgMLi6O3QbsdlsaNeuHWbPng0AaNOmDf744w8sXboUQ4cOdXHvSKm++OILfPbZZ1i5ciVatmyJ/fv344UXXkB4eDivG3IrnOJ4mwsKCoJarS5XNS0jIwOhoaEu6hUp1ejRo7F+/Xps27YNdevWdRwPDQ2FyWRCdna2U3teR+5t7969uHDhAu6++25oNBpoNBr88MMPePfdd6HRaBASEsLrhioUFhaGFi1aOB1r3rw5Tp8+DQCO64P/30VlvfLKK5g4cSIee+wxREVF4YknnsCLL76IOXPmAOB1Q1VTleskNDS0XDE9i8WCrKwsRVxLDGi3OZ1Oh7Zt22LLli2OYzabDVu2bEFcXJwLe0ZKIssyRo8eja+++gpbt25FgwYNnJ5v27YttFqt03V05MgRnD59mteRG+vRowd+//137N+/33Fr164dBg8e7PiZ1w1VpHPnzuW28vjrr79Qv359AECDBg0QGhrqdO0YjUbs3LmT144bKygogErl/KupWq2GzWYDwOuGqqYq10lcXByys7Oxd+9eR5utW7fCZrMhNjb2lve5HFdXKaEbt2rVKlmv18vLly+X//zzT3nkyJGyv7+/nJ6e7uqukUI899xzsp+fn7x9+3b5/PnzjltBQYGjzbPPPivXq1dP3rp1q7xnzx45Li5OjouLc2GvSYnKVnGUZV43VLFdu3bJGo1G/te//iUfPXpU/uyzz2RPT0/5008/dbR54403ZH9/f/nrr7+WDxw4ID/00ENygwYN5MLCQhf2nFxp6NChcp06deT169fLJ06ckNesWSMHBQXJ//d//+dow+uGZFlUF05NTZVTU1NlAPLbb78tp6amyqdOnZJluWrXSa9eveQ2bdrIO3fulH/++We5SZMm8qBBg1z1kZwwoN0hFi5cKNerV0/W6XRyhw4d5F9//dXVXSIFAVDhbdmyZY42hYWF8vPPPy8HBATInp6ecv/+/eXz58+7rtOkSFcGNF43VJlvvvlGbtWqlazX6+VmzZrJH3zwgdPzNptNnjp1qhwSEiLr9Xq5R48e8pEjR1zUW1ICo9Eojxs3Tq5Xr55sMBjkhg0byq+++qpcXFzsaMPrhmRZlrdt21bh7zVDhw6VZblq18mlS5fkQYMGyd7e3rKvr688fPhwOTc31wWfpjxJlstsz05EREREREQuwzVoRERERERECsGARkREREREpBAMaERERERERArBgEZERERERKQQDGhEREREREQKwYBGRERERESkEAxoRERERERECsGARkREREREpBAMaERERAokSRLWrl3r6m4QEdEtxoBGRER0hWHDhkGSpHK3Xr16ubprRER0h9O4ugNERERK1KtXLyxbtszpmF6vd1FviIjIXXAEjYiIqAJ6vR6hoaFOt4CAAABi+uGSJUvQu3dveHh4oGHDhvjyyy+dXv/777/jvvvug4eHBwIDAzFy5Ejk5eU5tfn444/RsmVL6PV6hIWFYfTo0U7PX7x4Ef3794enpyeaNGmCdevW1eyHJiIil2NAIyIiqoapU6fikUcewW+//YbBgwfjsccew6FDhwAA+fn5SEhIQEBAAHbv3o2kpCRs3rzZKYAtWbIEo0aNwsiRI/H7779j3bp1aNy4sdN7vPbaa3j00Udx4MAB9OnTB4MHD0ZWVtYt/ZxERHRrSbIsy67uBBERkZIMGzYMn376KQwGg9PxyZMnY/LkyZAkCc8++yyWLFnieK5jx464++678d577+E///kPJkyYgDNnzsDLywsAsGHDBvTr1w9paWkICQlBnTp1MHz4cLz++usV9kGSJEyZMgWzZs0CIEKft7c3Nm7cyLVwRER3MK5BIyIiqsC9997rFMAAoFatWo6f4+LinJ6Li4vD/v37AQCHDh1CdHS0I5wBQOfOnWGz2XDkyBFIkoS0tDT06NHjqn1o3bq142cvLy/4+vriwoUL1f1IRER0G2BAIyIiqoCXl1e5KYc3i4eHR5XaabVap8eSJMFms9VEl4iISCG4Bo2IiKgafv3113KPmzdvDgBo3rw5fvvtN+Tn5zue/+WXX6BSqdC0aVP4+PggMjISW7ZsuaV9JiIi5eMIGhERUQWKi4uRnp7udEyj0SAoKAgAkJSUhHbt2qFLly747LPPsGvXLnz00UcAgMGDB2P69OkYOnQoZsyYgczMTIwZMwZPPPEEQkJCAAAzZszAs88+i+DgYPTu3Ru5ubn45ZdfMGbMmFv7QYmISFEY0IiIiCqwadMmhIWFOR1r2rQpDh8+DEBUWFy1ahWef/55hIWF4fPPP0eLFi0AAJ6envjuu+8wbtw4tG/fHp6ennjkkUfw9ttvO841dOhQFBUV4Z133sHLL7+MoKAgDBgw4NZ9QCIiUiRWcSQiIrpOkiThq6++QmJioqu7QkREdxiuQSMiIiIiIlIIBjQiIiIiIiKF4Bo0IiKi68TVAUREVFM4gkZERERERKQQDGhEREREREQKwYBGRERERESkEAxoRERERERECsGARkREREREpBAMaERERERERArBgEZERERERKQQDGhEREREREQK8f8K5dA9Z9deagAAAABJRU5ErkJggg==",
|
370 |
+
"text/plain": [
|
371 |
+
"<Figure size 1000x500 with 1 Axes>"
|
372 |
+
]
|
373 |
+
},
|
374 |
+
"metadata": {},
|
375 |
+
"output_type": "display_data"
|
376 |
+
}
|
377 |
+
],
|
378 |
+
"source": [
|
379 |
+
"epochs = np.arange(1, len(train_losses) + 1)\n",
|
380 |
+
"plt.figure(figsize=(10, 5))\n",
|
381 |
+
"\n",
|
382 |
+
"plt.plot(epochs, train_losses, label='Train Loss')\n",
|
383 |
+
"plt.plot(epochs, valid_losses, label='Valid Loss')\n",
|
384 |
+
"plt.xlabel('Epoch')\n",
|
385 |
+
"plt.ylabel('Loss')\n",
|
386 |
+
"plt.title('Training and Validation Loss')\n",
|
387 |
+
"plt.legend()\n",
|
388 |
+
"\n",
|
389 |
+
"plt.show()"
|
390 |
+
]
|
391 |
+
},
|
392 |
+
{
|
393 |
+
"cell_type": "code",
|
394 |
+
"execution_count": 12,
|
395 |
+
"id": "c3b04bf7",
|
396 |
+
"metadata": {
|
397 |
+
"execution": {
|
398 |
+
"iopub.execute_input": "2024-04-01T10:06:13.084256Z",
|
399 |
+
"iopub.status.busy": "2024-04-01T10:06:13.083932Z",
|
400 |
+
"iopub.status.idle": "2024-04-01T10:06:38.988309Z",
|
401 |
+
"shell.execute_reply": "2024-04-01T10:06:38.987316Z"
|
402 |
+
},
|
403 |
+
"papermill": {
|
404 |
+
"duration": 25.920465,
|
405 |
+
"end_time": "2024-04-01T10:06:38.990405",
|
406 |
+
"exception": false,
|
407 |
+
"start_time": "2024-04-01T10:06:13.069940",
|
408 |
+
"status": "completed"
|
409 |
+
},
|
410 |
+
"tags": []
|
411 |
+
},
|
412 |
+
"outputs": [
|
413 |
+
{
|
414 |
+
"name": "stdout",
|
415 |
+
"output_type": "stream",
|
416 |
+
"text": [
|
417 |
+
"The loss on the test set is 0.008598181701702099\n"
|
418 |
+
]
|
419 |
+
}
|
420 |
+
],
|
421 |
+
"source": [
|
422 |
+
"model.eval()\n",
|
423 |
+
"test_loss = 0.0\n",
|
424 |
+
"with torch.no_grad():\n",
|
425 |
+
" for images, targets in test_loader:\n",
|
426 |
+
" images = images.to(device)\n",
|
427 |
+
" targets = targets.to(device)\n",
|
428 |
+
" outputs = model(images)\n",
|
429 |
+
" try:\n",
|
430 |
+
" loss = criterion(outputs, targets)\n",
|
431 |
+
" except RuntimeError:\n",
|
432 |
+
" adjusted_output = adjust_output_shape(outputs, targets)\n",
|
433 |
+
" loss = criterion(adjusted_output, targets)\n",
|
434 |
+
" test_loss += loss.item()\n",
|
435 |
+
" test_loss /= len(test_loader)\n",
|
436 |
+
"print(f\"The loss on the test set is {test_loss}\")"
|
437 |
+
]
|
438 |
+
}
|
439 |
+
],
|
440 |
+
"metadata": {
|
441 |
+
"kaggle": {
|
442 |
+
"accelerator": "gpu",
|
443 |
+
"dataSources": [
|
444 |
+
{
|
445 |
+
"datasetId": 4705836,
|
446 |
+
"sourceId": 7993213,
|
447 |
+
"sourceType": "datasetVersion"
|
448 |
+
}
|
449 |
+
],
|
450 |
+
"dockerImageVersionId": 30674,
|
451 |
+
"isGpuEnabled": true,
|
452 |
+
"isInternetEnabled": true,
|
453 |
+
"language": "python",
|
454 |
+
"sourceType": "notebook"
|
455 |
+
},
|
456 |
+
"kernelspec": {
|
457 |
+
"display_name": "Python 3",
|
458 |
+
"language": "python",
|
459 |
+
"name": "python3"
|
460 |
+
},
|
461 |
+
"language_info": {
|
462 |
+
"codemirror_mode": {
|
463 |
+
"name": "ipython",
|
464 |
+
"version": 3
|
465 |
+
},
|
466 |
+
"file_extension": ".py",
|
467 |
+
"mimetype": "text/x-python",
|
468 |
+
"name": "python",
|
469 |
+
"nbconvert_exporter": "python",
|
470 |
+
"pygments_lexer": "ipython3",
|
471 |
+
"version": "3.12.2"
|
472 |
+
},
|
473 |
+
"papermill": {
|
474 |
+
"default_parameters": {},
|
475 |
+
"duration": 32529.008488,
|
476 |
+
"end_time": "2024-04-01T10:06:40.496191",
|
477 |
+
"environment_variables": {},
|
478 |
+
"exception": null,
|
479 |
+
"input_path": "__notebook__.ipynb",
|
480 |
+
"output_path": "__notebook__.ipynb",
|
481 |
+
"parameters": {},
|
482 |
+
"start_time": "2024-04-01T01:04:31.487703",
|
483 |
+
"version": "2.5.0"
|
484 |
+
},
|
485 |
+
"widgets": {
|
486 |
+
"application/vnd.jupyter.widget-state+json": {
|
487 |
+
"state": {
|
488 |
+
"0d705fdb53a0460cb06e86e2212618f5": {
|
489 |
+
"model_module": "@jupyter-widgets/controls",
|
490 |
+
"model_module_version": "1.5.0",
|
491 |
+
"model_name": "DescriptionStyleModel",
|
492 |
+
"state": {
|
493 |
+
"_model_module": "@jupyter-widgets/controls",
|
494 |
+
"_model_module_version": "1.5.0",
|
495 |
+
"_model_name": "DescriptionStyleModel",
|
496 |
+
"_view_count": null,
|
497 |
+
"_view_module": "@jupyter-widgets/base",
|
498 |
+
"_view_module_version": "1.2.0",
|
499 |
+
"_view_name": "StyleView",
|
500 |
+
"description_width": ""
|
501 |
+
}
|
502 |
+
},
|
503 |
+
"1a8db5a1fed14afca913a6edb7794b17": {
|
504 |
+
"model_module": "@jupyter-widgets/controls",
|
505 |
+
"model_module_version": "1.5.0",
|
506 |
+
"model_name": "ProgressStyleModel",
|
507 |
+
"state": {
|
508 |
+
"_model_module": "@jupyter-widgets/controls",
|
509 |
+
"_model_module_version": "1.5.0",
|
510 |
+
"_model_name": "ProgressStyleModel",
|
511 |
+
"_view_count": null,
|
512 |
+
"_view_module": "@jupyter-widgets/base",
|
513 |
+
"_view_module_version": "1.2.0",
|
514 |
+
"_view_name": "StyleView",
|
515 |
+
"bar_color": null,
|
516 |
+
"description_width": ""
|
517 |
+
}
|
518 |
+
},
|
519 |
+
"1e977edae4d54b5fbd5b7018ffb9858f": {
|
520 |
+
"model_module": "@jupyter-widgets/base",
|
521 |
+
"model_module_version": "1.2.0",
|
522 |
+
"model_name": "LayoutModel",
|
523 |
+
"state": {
|
524 |
+
"_model_module": "@jupyter-widgets/base",
|
525 |
+
"_model_module_version": "1.2.0",
|
526 |
+
"_model_name": "LayoutModel",
|
527 |
+
"_view_count": null,
|
528 |
+
"_view_module": "@jupyter-widgets/base",
|
529 |
+
"_view_module_version": "1.2.0",
|
530 |
+
"_view_name": "LayoutView",
|
531 |
+
"align_content": null,
|
532 |
+
"align_items": null,
|
533 |
+
"align_self": null,
|
534 |
+
"border": null,
|
535 |
+
"bottom": null,
|
536 |
+
"display": null,
|
537 |
+
"flex": null,
|
538 |
+
"flex_flow": null,
|
539 |
+
"grid_area": null,
|
540 |
+
"grid_auto_columns": null,
|
541 |
+
"grid_auto_flow": null,
|
542 |
+
"grid_auto_rows": null,
|
543 |
+
"grid_column": null,
|
544 |
+
"grid_gap": null,
|
545 |
+
"grid_row": null,
|
546 |
+
"grid_template_areas": null,
|
547 |
+
"grid_template_columns": null,
|
548 |
+
"grid_template_rows": null,
|
549 |
+
"height": null,
|
550 |
+
"justify_content": null,
|
551 |
+
"justify_items": null,
|
552 |
+
"left": null,
|
553 |
+
"margin": null,
|
554 |
+
"max_height": null,
|
555 |
+
"max_width": null,
|
556 |
+
"min_height": null,
|
557 |
+
"min_width": null,
|
558 |
+
"object_fit": null,
|
559 |
+
"object_position": null,
|
560 |
+
"order": null,
|
561 |
+
"overflow": null,
|
562 |
+
"overflow_x": null,
|
563 |
+
"overflow_y": null,
|
564 |
+
"padding": null,
|
565 |
+
"right": null,
|
566 |
+
"top": null,
|
567 |
+
"visibility": null,
|
568 |
+
"width": null
|
569 |
+
}
|
570 |
+
},
|
571 |
+
"38d95f1d4d65453895e3b9f5ea41723c": {
|
572 |
+
"model_module": "@jupyter-widgets/base",
|
573 |
+
"model_module_version": "1.2.0",
|
574 |
+
"model_name": "LayoutModel",
|
575 |
+
"state": {
|
576 |
+
"_model_module": "@jupyter-widgets/base",
|
577 |
+
"_model_module_version": "1.2.0",
|
578 |
+
"_model_name": "LayoutModel",
|
579 |
+
"_view_count": null,
|
580 |
+
"_view_module": "@jupyter-widgets/base",
|
581 |
+
"_view_module_version": "1.2.0",
|
582 |
+
"_view_name": "LayoutView",
|
583 |
+
"align_content": null,
|
584 |
+
"align_items": null,
|
585 |
+
"align_self": null,
|
586 |
+
"border": null,
|
587 |
+
"bottom": null,
|
588 |
+
"display": null,
|
589 |
+
"flex": null,
|
590 |
+
"flex_flow": null,
|
591 |
+
"grid_area": null,
|
592 |
+
"grid_auto_columns": null,
|
593 |
+
"grid_auto_flow": null,
|
594 |
+
"grid_auto_rows": null,
|
595 |
+
"grid_column": null,
|
596 |
+
"grid_gap": null,
|
597 |
+
"grid_row": null,
|
598 |
+
"grid_template_areas": null,
|
599 |
+
"grid_template_columns": null,
|
600 |
+
"grid_template_rows": null,
|
601 |
+
"height": null,
|
602 |
+
"justify_content": null,
|
603 |
+
"justify_items": null,
|
604 |
+
"left": null,
|
605 |
+
"margin": null,
|
606 |
+
"max_height": null,
|
607 |
+
"max_width": null,
|
608 |
+
"min_height": null,
|
609 |
+
"min_width": null,
|
610 |
+
"object_fit": null,
|
611 |
+
"object_position": null,
|
612 |
+
"order": null,
|
613 |
+
"overflow": null,
|
614 |
+
"overflow_x": null,
|
615 |
+
"overflow_y": null,
|
616 |
+
"padding": null,
|
617 |
+
"right": null,
|
618 |
+
"top": null,
|
619 |
+
"visibility": null,
|
620 |
+
"width": null
|
621 |
+
}
|
622 |
+
},
|
623 |
+
"50e7ac5f3f4b4fe58e2e110fea403bbc": {
|
624 |
+
"model_module": "@jupyter-widgets/controls",
|
625 |
+
"model_module_version": "1.5.0",
|
626 |
+
"model_name": "HBoxModel",
|
627 |
+
"state": {
|
628 |
+
"_dom_classes": [],
|
629 |
+
"_model_module": "@jupyter-widgets/controls",
|
630 |
+
"_model_module_version": "1.5.0",
|
631 |
+
"_model_name": "HBoxModel",
|
632 |
+
"_view_count": null,
|
633 |
+
"_view_module": "@jupyter-widgets/controls",
|
634 |
+
"_view_module_version": "1.5.0",
|
635 |
+
"_view_name": "HBoxView",
|
636 |
+
"box_style": "",
|
637 |
+
"children": [
|
638 |
+
"IPY_MODEL_66e2c724e5e54c878bb614d51a452b26",
|
639 |
+
"IPY_MODEL_6901f2bab73b4155b0f53c30467d46c3",
|
640 |
+
"IPY_MODEL_771460c15f794c71af4f6eeb0ea7b1ad"
|
641 |
+
],
|
642 |
+
"layout": "IPY_MODEL_1e977edae4d54b5fbd5b7018ffb9858f"
|
643 |
+
}
|
644 |
+
},
|
645 |
+
"66e2c724e5e54c878bb614d51a452b26": {
|
646 |
+
"model_module": "@jupyter-widgets/controls",
|
647 |
+
"model_module_version": "1.5.0",
|
648 |
+
"model_name": "HTMLModel",
|
649 |
+
"state": {
|
650 |
+
"_dom_classes": [],
|
651 |
+
"_model_module": "@jupyter-widgets/controls",
|
652 |
+
"_model_module_version": "1.5.0",
|
653 |
+
"_model_name": "HTMLModel",
|
654 |
+
"_view_count": null,
|
655 |
+
"_view_module": "@jupyter-widgets/controls",
|
656 |
+
"_view_module_version": "1.5.0",
|
657 |
+
"_view_name": "HTMLView",
|
658 |
+
"description": "",
|
659 |
+
"description_tooltip": null,
|
660 |
+
"layout": "IPY_MODEL_38d95f1d4d65453895e3b9f5ea41723c",
|
661 |
+
"placeholder": "",
|
662 |
+
"style": "IPY_MODEL_0d705fdb53a0460cb06e86e2212618f5",
|
663 |
+
"value": "100%"
|
664 |
+
}
|
665 |
+
},
|
666 |
+
"6901f2bab73b4155b0f53c30467d46c3": {
|
667 |
+
"model_module": "@jupyter-widgets/controls",
|
668 |
+
"model_module_version": "1.5.0",
|
669 |
+
"model_name": "FloatProgressModel",
|
670 |
+
"state": {
|
671 |
+
"_dom_classes": [],
|
672 |
+
"_model_module": "@jupyter-widgets/controls",
|
673 |
+
"_model_module_version": "1.5.0",
|
674 |
+
"_model_name": "FloatProgressModel",
|
675 |
+
"_view_count": null,
|
676 |
+
"_view_module": "@jupyter-widgets/controls",
|
677 |
+
"_view_module_version": "1.5.0",
|
678 |
+
"_view_name": "ProgressView",
|
679 |
+
"bar_style": "",
|
680 |
+
"description": "",
|
681 |
+
"description_tooltip": null,
|
682 |
+
"layout": "IPY_MODEL_dd05d612550a4db28ebf2c7cfc2312fe",
|
683 |
+
"max": 75500,
|
684 |
+
"min": 0,
|
685 |
+
"orientation": "horizontal",
|
686 |
+
"style": "IPY_MODEL_1a8db5a1fed14afca913a6edb7794b17",
|
687 |
+
"value": 75500
|
688 |
+
}
|
689 |
+
},
|
690 |
+
"771460c15f794c71af4f6eeb0ea7b1ad": {
|
691 |
+
"model_module": "@jupyter-widgets/controls",
|
692 |
+
"model_module_version": "1.5.0",
|
693 |
+
"model_name": "HTMLModel",
|
694 |
+
"state": {
|
695 |
+
"_dom_classes": [],
|
696 |
+
"_model_module": "@jupyter-widgets/controls",
|
697 |
+
"_model_module_version": "1.5.0",
|
698 |
+
"_model_name": "HTMLModel",
|
699 |
+
"_view_count": null,
|
700 |
+
"_view_module": "@jupyter-widgets/controls",
|
701 |
+
"_view_module_version": "1.5.0",
|
702 |
+
"_view_name": "HTMLView",
|
703 |
+
"description": "",
|
704 |
+
"description_tooltip": null,
|
705 |
+
"layout": "IPY_MODEL_d08ee627a3cc414489e61161d8a917ae",
|
706 |
+
"placeholder": "",
|
707 |
+
"style": "IPY_MODEL_b2818288e9b9459fb75a1ea2e6f35117",
|
708 |
+
"value": " 75500/75500 [9:00:45<00:00, 2.32it/s]"
|
709 |
+
}
|
710 |
+
},
|
711 |
+
"b2818288e9b9459fb75a1ea2e6f35117": {
|
712 |
+
"model_module": "@jupyter-widgets/controls",
|
713 |
+
"model_module_version": "1.5.0",
|
714 |
+
"model_name": "DescriptionStyleModel",
|
715 |
+
"state": {
|
716 |
+
"_model_module": "@jupyter-widgets/controls",
|
717 |
+
"_model_module_version": "1.5.0",
|
718 |
+
"_model_name": "DescriptionStyleModel",
|
719 |
+
"_view_count": null,
|
720 |
+
"_view_module": "@jupyter-widgets/base",
|
721 |
+
"_view_module_version": "1.2.0",
|
722 |
+
"_view_name": "StyleView",
|
723 |
+
"description_width": ""
|
724 |
+
}
|
725 |
+
},
|
726 |
+
"d08ee627a3cc414489e61161d8a917ae": {
|
727 |
+
"model_module": "@jupyter-widgets/base",
|
728 |
+
"model_module_version": "1.2.0",
|
729 |
+
"model_name": "LayoutModel",
|
730 |
+
"state": {
|
731 |
+
"_model_module": "@jupyter-widgets/base",
|
732 |
+
"_model_module_version": "1.2.0",
|
733 |
+
"_model_name": "LayoutModel",
|
734 |
+
"_view_count": null,
|
735 |
+
"_view_module": "@jupyter-widgets/base",
|
736 |
+
"_view_module_version": "1.2.0",
|
737 |
+
"_view_name": "LayoutView",
|
738 |
+
"align_content": null,
|
739 |
+
"align_items": null,
|
740 |
+
"align_self": null,
|
741 |
+
"border": null,
|
742 |
+
"bottom": null,
|
743 |
+
"display": null,
|
744 |
+
"flex": null,
|
745 |
+
"flex_flow": null,
|
746 |
+
"grid_area": null,
|
747 |
+
"grid_auto_columns": null,
|
748 |
+
"grid_auto_flow": null,
|
749 |
+
"grid_auto_rows": null,
|
750 |
+
"grid_column": null,
|
751 |
+
"grid_gap": null,
|
752 |
+
"grid_row": null,
|
753 |
+
"grid_template_areas": null,
|
754 |
+
"grid_template_columns": null,
|
755 |
+
"grid_template_rows": null,
|
756 |
+
"height": null,
|
757 |
+
"justify_content": null,
|
758 |
+
"justify_items": null,
|
759 |
+
"left": null,
|
760 |
+
"margin": null,
|
761 |
+
"max_height": null,
|
762 |
+
"max_width": null,
|
763 |
+
"min_height": null,
|
764 |
+
"min_width": null,
|
765 |
+
"object_fit": null,
|
766 |
+
"object_position": null,
|
767 |
+
"order": null,
|
768 |
+
"overflow": null,
|
769 |
+
"overflow_x": null,
|
770 |
+
"overflow_y": null,
|
771 |
+
"padding": null,
|
772 |
+
"right": null,
|
773 |
+
"top": null,
|
774 |
+
"visibility": null,
|
775 |
+
"width": null
|
776 |
+
}
|
777 |
+
},
|
778 |
+
"dd05d612550a4db28ebf2c7cfc2312fe": {
|
779 |
+
"model_module": "@jupyter-widgets/base",
|
780 |
+
"model_module_version": "1.2.0",
|
781 |
+
"model_name": "LayoutModel",
|
782 |
+
"state": {
|
783 |
+
"_model_module": "@jupyter-widgets/base",
|
784 |
+
"_model_module_version": "1.2.0",
|
785 |
+
"_model_name": "LayoutModel",
|
786 |
+
"_view_count": null,
|
787 |
+
"_view_module": "@jupyter-widgets/base",
|
788 |
+
"_view_module_version": "1.2.0",
|
789 |
+
"_view_name": "LayoutView",
|
790 |
+
"align_content": null,
|
791 |
+
"align_items": null,
|
792 |
+
"align_self": null,
|
793 |
+
"border": null,
|
794 |
+
"bottom": null,
|
795 |
+
"display": null,
|
796 |
+
"flex": null,
|
797 |
+
"flex_flow": null,
|
798 |
+
"grid_area": null,
|
799 |
+
"grid_auto_columns": null,
|
800 |
+
"grid_auto_flow": null,
|
801 |
+
"grid_auto_rows": null,
|
802 |
+
"grid_column": null,
|
803 |
+
"grid_gap": null,
|
804 |
+
"grid_row": null,
|
805 |
+
"grid_template_areas": null,
|
806 |
+
"grid_template_columns": null,
|
807 |
+
"grid_template_rows": null,
|
808 |
+
"height": null,
|
809 |
+
"justify_content": null,
|
810 |
+
"justify_items": null,
|
811 |
+
"left": null,
|
812 |
+
"margin": null,
|
813 |
+
"max_height": null,
|
814 |
+
"max_width": null,
|
815 |
+
"min_height": null,
|
816 |
+
"min_width": null,
|
817 |
+
"object_fit": null,
|
818 |
+
"object_position": null,
|
819 |
+
"order": null,
|
820 |
+
"overflow": null,
|
821 |
+
"overflow_x": null,
|
822 |
+
"overflow_y": null,
|
823 |
+
"padding": null,
|
824 |
+
"right": null,
|
825 |
+
"top": null,
|
826 |
+
"visibility": null,
|
827 |
+
"width": null
|
828 |
+
}
|
829 |
+
}
|
830 |
+
},
|
831 |
+
"version_major": 2,
|
832 |
+
"version_minor": 0
|
833 |
+
}
|
834 |
+
}
|
835 |
+
},
|
836 |
+
"nbformat": 4,
|
837 |
+
"nbformat_minor": 5
|
838 |
+
}
|
src/templates/index.html
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<title>MangaColorizer</title>
|
5 |
+
</head>
|
6 |
+
<body>
|
7 |
+
<h1 style="text-align: center;font-size: xx-large;">MangaColorizer</h1>
|
8 |
+
<p style="text-align: center;font-size: large;">Upload a black and white drawing and get its colorized version</p>
|
9 |
+
</body>
|
10 |
+
</html>
|
src/test.ipynb
ADDED
The diff for this file is too large to render.
See raw diff
|
|
src/utils.py
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
|
3 |
+
import torch
|
4 |
+
import matplotlib.pyplot as plt
|
5 |
+
from PIL import Image
|
6 |
+
from torch.utils.data import Dataset
|
7 |
+
from torchvision import transforms
|
8 |
+
|
9 |
+
|
10 |
+
class ImageDataset(Dataset):
|
11 |
+
def __init__(self, dir, transform=None) -> None:
|
12 |
+
self.dir = dir
|
13 |
+
self.transform = transform
|
14 |
+
self.file_list = sorted(os.listdir(self.dir))
|
15 |
+
|
16 |
+
def __len__(self):
|
17 |
+
return len(self.file_list)
|
18 |
+
|
19 |
+
def __getitem__(self, idx):
|
20 |
+
image_name = self.file_list[idx]
|
21 |
+
image_path = os.path.join(self.dir, image_name)
|
22 |
+
|
23 |
+
grayscale_image = Image.open(image_path).convert('L')
|
24 |
+
colorized_image = Image.open(image_path).convert('RGB')
|
25 |
+
|
26 |
+
if self.transform:
|
27 |
+
grayscale_image = self.transform(grayscale_image)
|
28 |
+
colorized_image = self.transform(colorized_image)
|
29 |
+
|
30 |
+
return grayscale_image, colorized_image
|
31 |
+
|
32 |
+
|
33 |
+
def show_image(image_tensor):
|
34 |
+
try:
|
35 |
+
if len(image_tensor) == 1:
|
36 |
+
plt.imshow(image_tensor[0], cmap="gray")
|
37 |
+
else:
|
38 |
+
plt.imshow(image_tensor.numpy().transpose(1, 2, 0))
|
39 |
+
except Exception as e:
|
40 |
+
print(f"Exception when showing image: {e}")
|
41 |
+
|
42 |
+
|
43 |
+
# To be able to calculate MSE loss in case output tensor has different shape from target tensor
|
44 |
+
def adjust_output_shape(output_tensor, target_tensor):
|
45 |
+
adjusted_tensor = torch.nn.functional.interpolate(output_tensor, size=target_tensor.shape[2:], mode="bilinear", align_corners=False)
|
46 |
+
return adjusted_tensor
|
47 |
+
|
48 |
+
|
49 |
+
def pil_to_torch(pil_image):
|
50 |
+
transform = transforms.ToTensor()
|
51 |
+
return transform(pil_image).unsqueeze(0)
|
52 |
+
|
53 |
+
def torch_to_pil(torch_image):
|
54 |
+
transform = transforms.ToPILImage()
|
55 |
+
return transform(torch_image.squeeze(0))
|